Ejemplo n.º 1
0
Archivo: mmgs1.c Proyecto: XL64/mmg
/* attempt to collapse small edges */
static int colelt(pMesh mesh,pSol met,char typchk) {
    pTria    pt;
    pPoint   p1,p2;
    double   ll,ux,uy,uz;
    int      ier,list[LMAX+2],ilist,k,nc;
    char     i,i1,i2;

    nc = 0;
    for (k=1; k<=mesh->nt; k++) {
        pt = &mesh->tria[k];
        if ( !MS_EOK(pt) || pt->ref < 0 )   continue;

        /* check edge length */
        pt->flag = 0;
        ier = 0;
        for (i=0; i<3; i++) {
            if ( MS_SIN(pt->tag[i]) )  continue;

            i1 = inxt[i];
            i2 = iprv[i];
            p1 = &mesh->point[pt->v[i1]];
            p2 = &mesh->point[pt->v[i2]];
            if ( p1->tag & MS_NOM || p2->tag & MS_NOM )  continue;
            else if ( MS_SIN(p1->tag) )   continue;
            else if ( p1->tag > p2->tag || p1->tag > pt->tag[i] )  continue;

            /* check length */
            if ( typchk == 1 ) {
                ux = p2->c[0] - p1->c[0];
                uy = p2->c[1] - p1->c[1];
                uz = p2->c[2] - p1->c[2];
                ll = ux*ux + uy*uy + uz*uz;
                if ( ll > info.hmin*info.hmin )  continue;
            }
            else {
                ll = lenedg(mesh,met,pt->v[i1],pt->v[i2],0);
                if ( ll > LSHRT )  continue;
            }

            /* check if geometry preserved */
            ilist = chkcol(mesh,met,k,i,list,typchk);
            if ( ilist > 3 ) {
                nc += colver(mesh,list,ilist);
                break;
            }
            else if ( ilist == 3 ) {
                nc += colver3(mesh,list);
                break;
            }
            else if ( ilist == 2 ) {
                nc += colver2(mesh,list);
                break;
            }
        }
    }
    if ( nc > 0 && (abs(info.imprim) > 5 || info.ddebug) )
        fprintf(stdout,"     %8d vertices removed\n",nc);

    return(nc);
}
Ejemplo n.º 2
0
Archivo: mmgs1.c Proyecto: XL64/mmg
/* check if splitting edge i of k is ok */
int chkspl(pMesh mesh,pSol met,int k,int i) {
    pTria    pt,pt1;
    pPoint   ppt;
    pGeom    go;
    Bezier   b;
    double   s,uv[2],o[3],no[3],to[3];
    int     *adja,jel,ip,ier;
    char     i1,i2,j,jj,j2;

    if ( mesh->ng > mesh->ngmax-2 )  return(0);
    pt = &mesh->tria[k];
    i1 = inxt[i];
    i2 = iprv[i];
    if ( MS_SIN(pt->tag[i1]) || MS_SIN(pt->tag[i2]) )  return(0);
    adja = &mesh->adja[3*(k-1)+1];
    jel  = adja[i] / 3;
    if ( jel ) {
        j   = adja[i] % 3;
        jj  = inxt[j];
        j2  = iprv[j];
        pt1 = &mesh->tria[jel];
        if ( MS_SIN(pt1->tag[jj]) || MS_SIN(pt1->tag[j2]) )  return(0);
    }

    ier = bezierCP(mesh,k,&b);
    assert(ier);

    /* create midedge point */
    uv[0] = 0.5;
    uv[1] = 0.5;
    if (i == 1)         uv[0] = 0.0;
    else if ( i == 2 )  uv[1] = 0.0;

    ier = bezierInt(&b,uv,o,no,to);
    assert(ier);
    ip = newPt(mesh,o,MS_EDG(pt->tag[i]) ? to : no);
    assert(ip);

    if ( MS_EDG(pt->tag[i]) ) {
        ++mesh->ng;
        ppt = &mesh->point[ip];
        ppt->ig  = mesh->ng;
        go = &mesh->geom[mesh->ng];
        memcpy(go->n1,no,3*sizeof(double));
    }
    s = 0.5;

    intmet(mesh,met,k,i,ip,s);

    return(ip);
}
Ejemplo n.º 3
0
Archivo: mmgs1.c Proyecto: XL64/mmg
/* analyze triangles and split or collapse to match gradation */
static int adpcol(pMesh mesh,pSol met) {
    pTria    pt;
    pPoint   p1,p2;
    double   len;
    int      k,list[LMAX+2],ilist,nc;
    char     i,i1,i2;

    nc = 0;
    for (k=1; k<=mesh->nt; k++) {
        pt = &mesh->tria[k];
        if ( !MS_EOK(pt) || pt->ref < 0 )   continue;

        /* check edge length */
        pt->flag = 0;
        for (i=0; i<3; i++) {
            if ( MS_SIN(pt->tag[i]) )  continue;

            /* check length */
            i1 = inxt[i];
            i2 = iprv[i];
            p1 = &mesh->point[pt->v[i1]];
            p2 = &mesh->point[pt->v[i2]];
            if ( p1->tag & MS_NOM || p2->tag & MS_NOM )  continue;

            len = lenedg(mesh,met,pt->v[i1],pt->v[i2],0);
            if ( len > LOPTS )  continue;

            p1 = &mesh->point[pt->v[i1]];
            p2 = &mesh->point[pt->v[i2]];
            if ( MS_SIN(p1->tag) )  continue;
            else if ( p1->tag > p2->tag || p1->tag > pt->tag[i] )  continue;

            /* check if geometry preserved */
            ilist = chkcol(mesh,met,k,i,list,2);
            if ( ilist > 3 ) {
                nc += colver(mesh,list,ilist);
                break;
            }
            else if ( ilist == 3 ) {
                nc += colver3(mesh,list);
                break;
            }
            else if ( ilist == 2 ) {
                nc += colver2(mesh,list);
                break;
            }
        }
    }
    return(nc);
}
Ejemplo n.º 4
0
Archivo: mmgs1.c Proyecto: XL64/mmg
static int swpmsh(pMesh mesh,pSol met,char typchk) {
    pTria    pt;
    int      k,it,ns,nns,maxit;
    char     i;

    it = nns = 0;
    maxit = 2;
    mesh->base++;
    do {
        ns = 0;
        for (k=1; k<=mesh->nt; k++) {
            pt = &mesh->tria[k];
            if ( !MS_EOK(pt) || pt->ref < 0 )   continue;

            for (i=0; i<3; i++) {
                if ( MS_SIN(pt->tag[i]) || MS_EDG(pt->tag[i]) )  continue;
                else if ( chkswp(mesh,met,k,i,typchk) ) {
                    ns += swapar(mesh,k,i);
                    break;
                }
            }
        }
        nns += ns;
    }
    while ( ns > 0 && ++it < maxit );
    if ( (abs(info.imprim) > 5 || info.ddebug) && nns > 0 )
        fprintf(stdout,"     %8d edge swapped\n",nns);

    return(nns);
}
Ejemplo n.º 5
0
Archivo: mmgs1.c Proyecto: XL64/mmg
/* Analyze triangles and move points to make mesh more uniform */
static int movtri(pMesh mesh,pSol met,int maxit) {
    pTria    pt;
    pPoint   ppt;
    int      it,k,ier,base,nm,ns,nnm,list[LMAX+2],ilist;
    char     i;

    if ( abs(info.imprim) > 5 || info.ddebug )
        fprintf(stdout,"  ** OPTIMIZING MESH\n");

    base = 1;
    for (k=1; k<=mesh->np; k++)  mesh->point[k].flag = base;

    it = nnm = 0;
    do {
        base++;
        nm = ns = 0;
        for (k=1; k<=mesh->nt; k++) {
            pt = &mesh->tria[k];
            if ( !MS_EOK(pt) || pt->ref < 0 )   continue;

            for (i=0; i<3; i++) {
                ppt = &mesh->point[pt->v[i]];

                if ( ppt->flag == base || MS_SIN(ppt->tag) || ppt->tag & MS_NOM )
                    continue;
                ier = 0;
                ilist = boulet(mesh,k,i,list);

                if ( MS_EDG(ppt->tag) ) {
                    ier = movridpt(mesh,met,list,ilist);
                    if ( ier )  ns++;
                }
                else
                    ier = movintpt(mesh,met,list,ilist);
                if ( ier ) {
                    nm++;
                    ppt->flag = base;
                }
            }
        }
        nnm += nm;
        if ( info.ddebug )  fprintf(stdout,"     %8d moved, %d geometry\n",nm,ns);
    }
    while ( ++it < maxit && nm > 0);

    if ( (abs(info.imprim) > 5 || info.ddebug) && nnm > 0 )
        fprintf(stdout,"     %8d vertices moved, %d iter.\n",nnm,it);

    return(nnm);
}
Ejemplo n.º 6
0
Archivo: mmgs1.c Proyecto: XL64/mmg
static int adpspl(pMesh mesh,pSol met) {
    pTria    pt;
    pPoint   p1,p2;
    double   len,lmax;
    int      ip,k,ns;
    char     i,i1,i2,imax;

    ns = 0;
    for (k=1; k<=mesh->nt; k++) {
        pt = &mesh->tria[k];
        if ( !MS_EOK(pt) || pt->ref < 0 )   continue;

        /* check edge length */
        pt->flag = 0;
        imax = -1;
        lmax = -1.0;
        for (i=0; i<3; i++) {
            i1  = inxt[i];
            i2  = iprv[i];
            len = lenedg(mesh,met,pt->v[i1],pt->v[i2],0);
            if ( len > lmax ) {
                lmax = len;
                imax = i;
            }
        }
        if ( lmax < LOPTL )  continue;
        else if ( MS_SIN(pt->tag[imax]) )  continue;

        /* check length */
        i1 = inxt[imax];
        i2 = iprv[imax];
        p1 = &mesh->point[pt->v[i1]];
        p2 = &mesh->point[pt->v[i2]];
        if ( p1->tag & MS_NOM || p2->tag & MS_NOM )  continue;

        ip = chkspl(mesh,met,k,imax);
        if ( ip > 0 )
            ns += split1b(mesh,k,imax,ip);
    }
    return(ns);
}
Ejemplo n.º 7
0
Archivo: mmgs1.c Proyecto: XL64/mmg
/* check if edge need to be split and return a binary coding the numbers of the edges of tria iel
   that should be split according to a hausdorff distance criterion */
int chkedg(pMesh mesh,int iel) {
    pTria    pt;
    pPoint   p[3];
    double   n[3][3],t[3][3],nt[3],c1[3],c2[3],*n1,*n2,t1[3],t2[3];
    double   ps,ps2,cosn,ux,uy,uz,ll,li,dd;
    char     i,i1,i2;

    pt   = &mesh->tria[iel];
    p[0] = &mesh->point[pt->v[0]];
    p[1] = &mesh->point[pt->v[1]];
    p[2] = &mesh->point[pt->v[2]];

    /* normal recovery */
    for (i=0; i<3; i++) {
        if ( MS_SIN(p[i]->tag) ) {
            nortri(mesh,pt,n[i]);
        }
        else if ( MS_EDG(p[i]->tag) ) {
            nortri(mesh,pt,nt);
            n1  = &mesh->geom[p[i]->ig].n1[0];
            n2  = &mesh->geom[p[i]->ig].n2[0];
            ps  = n1[0]*nt[0] + n1[1]*nt[1] + n1[2]*nt[2];
            ps2 = n2[0]*nt[0] + n2[1]*nt[1] + n2[2]*nt[2];
            if ( fabs(ps) > fabs(ps2) )
                memcpy(&n[i],n1,3*sizeof(double));
            else
                memcpy(&n[i],n2,3*sizeof(double));
            memcpy(&t[i],p[i]->n,3*sizeof(double));
        }
        else
            memcpy(&n[i],p[i]->n,3*sizeof(double));
    }

    /* analyze edges */
    for (i=0; i<3; i++) {
        i1 = inxt[i];
        i2 = iprv[i];

        /* check length */
        ux = p[i2]->c[0] - p[i1]->c[0];
        uy = p[i2]->c[1] - p[i1]->c[1];
        uz = p[i2]->c[2] - p[i1]->c[2];
        ll = ux*ux + uy*uy + uz*uz;
        if ( ll > info.hmax*info.hmax ) {
            MS_SET(pt->flag,i);
            continue;
        }
        else if ( !MS_EDG(pt->tag[i]) && p[i1]->tag > MS_NOTAG && p[i2]->tag > MS_NOTAG ) {
            MS_SET(pt->flag,i);
            continue;
        }

        /* Hausdorff w/r tangent direction */
        if ( MS_EDG(pt->tag[i]) ) {
            if ( MS_SIN(p[i1]->tag) ) {
                li = 1.0 / sqrt(ll);
                t1[0] = li*ux;
                t1[1] = li*uy;
                t1[2] = li*uz;
            }
            else{
                memcpy(t1,t[i1],3*sizeof(double));
            }

            if ( MS_SIN(p[i2]->tag) ) {
                li = 1.0 / sqrt(ll);
                t2[0] = li*ux;
                t2[1] = li*uy;
                t2[2] = li*uz;
            }
            else{
                memcpy(t2,t[i2],3*sizeof(double));
            }

            ps = t1[0]*ux + t1[1]*uy + t1[2]*uz;
            ps *= ps;
            cosn = ps/ll ;
            cosn *= (1.0-cosn);
            cosn *= (0.25*ll);
            if ( cosn > info.hausd*info.hausd ) {
                MS_SET(pt->flag,i);
                continue;
            }

            ps = -(t2[0]*ux + t2[1]*uy + t2[2]*uz);
            ps *= ps;
            cosn = ps/ll ;
            cosn *= (1.0-cosn);
            cosn *= (0.25*ll);
            if ( cosn > info.hausd*info.hausd ) {
                MS_SET(pt->flag,i);
                continue;
            }
        }
        else {
            n1 = n[i1];
            n2 = n[i2];

            ps = ux*n1[0] + uy*n1[1] + uz*n1[2];
            c1[0] = (2.0*p[i1]->c[0] + p[i2]->c[0] - ps*n1[0]) / 3.0 - p[i1]->c[0];
            c1[1] = (2.0*p[i1]->c[1] + p[i2]->c[1] - ps*n1[1]) / 3.0 - p[i1]->c[1];
            c1[2] = (2.0*p[i1]->c[2] + p[i2]->c[2] - ps*n1[2]) / 3.0 - p[i1]->c[2];

            ps = -(ux*n2[0] + uy*n2[1] + uz*n2[2]);
            c2[0] = (2.0*p[i2]->c[0] + p[i1]->c[0] - ps*n2[0]) / 3.0 - p[i2]->c[0];
            c2[1] = (2.0*p[i2]->c[1] + p[i1]->c[1] - ps*n2[1]) / 3.0 - p[i2]->c[1];
            c2[2] = (2.0*p[i2]->c[2] + p[i1]->c[2] - ps*n2[2]) / 3.0 - p[i2]->c[2];

            /* squared cosines */
            ps = c1[0]*ux + c1[1]*uy + c1[2]*uz;
            ps *= ps;
            dd = c1[0]*c1[0] + c1[1]*c1[1] + c1[2]*c1[2];
            cosn  =  ps / (dd*ll);
            cosn *= (1.0-cosn);
            cosn *= (0.25*ll);
            if ( cosn > info.hausd*info.hausd ) {
                MS_SET(pt->flag,i);
                continue;
            }

            ps = -c2[0]*ux - c2[1]*uy - c2[2]*uz;
            ps *= ps;
            dd = c2[0]*c2[0]+c2[1]*c2[1]+c2[2]*c2[2];
            cosn  =  ps / (dd*ll);
            cosn *= (1.0-cosn);
            cosn *= (0.25*ll);
            if ( cosn > info.hausd*info.hausd ) {
                MS_SET(pt->flag,i);
                continue;
            }
        }
    }

    return(pt->flag);
}
Ejemplo n.º 8
0
Archivo: mmgs1.c Proyecto: XL64/mmg
/* analyze triangles and split if needed */
static int anaelt(pMesh mesh,pSol met,char typchk) {
    pTria    pt;
    pPoint   ppt,p1,p2;
    Hash     hash;
    Bezier   pb;
    pGeom    go;
    double   s,o[3],no[3],to[3],dd,len;
    int      vx[3],i,j,ip,ip1,ip2,ier,k,ns,nc,nt;
    char     i1,i2;
    static double uv[3][2] = { {0.5,0.5}, {0.,0.5}, {0.5,0.} };

    hashNew(&hash,mesh->np);
    ns = 0;
    s  = 0.5;
    for (k=1; k<=mesh->nt; k++) {
        pt = &mesh->tria[k];
        if ( !MS_EOK(pt) || pt->ref < 0 )  continue;
        if ( MS_SIN(pt->tag[0]) || MS_SIN(pt->tag[1]) || MS_SIN(pt->tag[2]) )  continue;

        /* check element cut */
        pt->flag = 0;
        if ( typchk == 1 ) {
            if ( !chkedg(mesh,k) )  continue;
        }
        else if ( typchk == 2 ) {
            for (i=0; i<3; i++) {
                i1 = inxt[i];
                i2 = iprv[i];
                len = lenedg(mesh,met,pt->v[i1],pt->v[i2],0);
                if ( len > LLONG )  MS_SET(pt->flag,i);
            }
            if ( !pt->flag )  continue;
        }
        ns++;

        /* geometric support */
        ier = bezierCP(mesh,k,&pb);
        assert(ier);

        /* scan edges to split */
        for (i=0; i<3; i++) {
            if ( !MS_GET(pt->flag,i) )  continue;
            i1  = inxt[i];
            i2  = iprv[i];
            ip1 = pt->v[i1];
            ip2 = pt->v[i2];
            ip = hashGet(&hash,ip1,ip2);
            if ( !MS_EDG(pt->tag[i]) && ip > 0 )  continue;

            /* new point along edge */
            ier = bezierInt(&pb,uv[i],o,no,to);
            if ( !ip ) {
                ip = newPt(mesh,o,MS_EDG(pt->tag[i]) ? to : no);
                assert(ip);
                hashEdge(&hash,ip1,ip2,ip);
                p1  = &mesh->point[ip1];
                p2  = &mesh->point[ip2];
                ppt = &mesh->point[ip];

                if ( MS_EDG(pt->tag[i]) ) {
                    ++mesh->ng;
                    assert(mesh->ng < mesh->ngmax);
                    ppt->tag = pt->tag[i];
                    if ( p1->ref == pt->edg[i] || p2->ref == pt->edg[i] )
                        ppt->ref = pt->edg[i];
                    ppt->ig  = mesh->ng;
                    go = &mesh->geom[mesh->ng];
                    memcpy(go->n1,no,3*sizeof(double));

                    dd = go->n1[0]*ppt->n[0] + go->n1[1]*ppt->n[1] + go->n1[2]*ppt->n[2];
                    ppt->n[0] -= dd*go->n1[0];
                    ppt->n[1] -= dd*go->n1[1];
                    ppt->n[2] -= dd*go->n1[2];
                    dd = ppt->n[0]*ppt->n[0] + ppt->n[1]*ppt->n[1] + ppt->n[2]*ppt->n[2];
                    if ( dd > EPSD2 ) {
                        dd = 1.0 / sqrt(dd);
                        ppt->n[0] *= dd;
                        ppt->n[1] *= dd;
                        ppt->n[2] *= dd;
                    }
                }
                if ( met->m ) {
                    if ( typchk == 1 )
                        intmet33(mesh,met,ip1,ip2,ip,s);
                    else
                        intmet(mesh,met,k,i,ip,s);
                }
            }
            else if ( pt->tag[i] & MS_GEO ) {
                ppt = &mesh->point[ip];
                go  = &mesh->geom[ppt->ig];
                memcpy(go->n2,no,3*sizeof(double));

                /* a computation of the tangent with respect to these two normals is possible */
                ppt->n[0] = go->n1[1]*go->n2[2] - go->n1[2]*go->n2[1];
                ppt->n[1] = go->n1[2]*go->n2[0] - go->n1[0]*go->n2[2];
                ppt->n[2] = go->n1[0]*go->n2[1] - go->n1[1]*go->n2[0];
                dd = ppt->n[0]*ppt->n[0] + ppt->n[1]*ppt->n[1] + ppt->n[2]*ppt->n[2];
                if ( dd > EPSD2 ) {
                    dd = 1.0 / sqrt(dd);
                    ppt->n[0] *= dd;
                    ppt->n[1] *= dd;
                    ppt->n[2] *= dd;
                }
            }
        }
    }
    if ( !ns ) {
        free(hash.item);
        return(ns);
    }

    /* step 2. checking if split by adjacent */
    for (k=1; k<=mesh->nt; k++) {
        pt = &mesh->tria[k];
        if ( !MS_EOK(pt) || pt->ref < 0 )  continue;
        else if ( pt->flag == 7 )  continue;

        /* geometric support */
        ier = bezierCP(mesh,k,&pb);
        assert(ier);
        nc = 0;

        for (i=0; i<3; i++) {
            i1 = inxt[i];
            i2 = inxt[i1];
            if ( !MS_GET(pt->flag,i) && !MS_SIN(pt->tag[i]) ) {
                ip = hashGet(&hash,pt->v[i1],pt->v[i2]);
                if ( ip > 0 ) {
                    MS_SET(pt->flag,i);
                    nc++;
                    if ( pt->tag[i] & MS_GEO ) {
                        /* new point along edge */
                        ier = bezierInt(&pb,uv[i],o,no,to);
                        assert(ier);

                        ppt = &mesh->point[ip];
                        go  = &mesh->geom[ppt->ig];
                        memcpy(go->n2,no,3*sizeof(double));

                        /* a computation of the tangent with respect to these two normals is possible */
                        ppt->n[0] = go->n1[1]*go->n2[2] - go->n1[2]*go->n2[1];
                        ppt->n[1] = go->n1[2]*go->n2[0] - go->n1[0]*go->n2[2];
                        ppt->n[2] = go->n1[0]*go->n2[1] - go->n1[1]*go->n2[0];
                        dd = ppt->n[0]*ppt->n[0] + ppt->n[1]*ppt->n[1] + ppt->n[2]*ppt->n[2];
                        if ( dd > EPSD2 ) {
                            dd = 1.0 / sqrt(dd);
                            ppt->n[0] *= dd;
                            ppt->n[1] *= dd;
                            ppt->n[2] *= dd;
                        }
                    }
                }
            }
        }
        if ( nc > 0 )  ++ns;
    }
    if ( info.ddebug && ns ) {
        fprintf(stdout,"     %d analyzed  %d proposed\n",mesh->nt,ns);
        fflush(stdout);
    }

    /* step 3. splitting */
    ns = 0;
    nt = mesh->nt;
    for (k=1; k<=nt; k++) {
        pt = &mesh->tria[k];
        if ( !MS_EOK(pt) || pt->ref < 0 )  continue;
        else if ( pt->flag == 0 )  continue;

        j  = -1;
        vx[0] = vx[1] = vx[2] = 0;
        for (i=0; i<3; i++) {
            i1 = inxt[i];
            i2 = inxt[i1];
            if ( MS_GET(pt->flag,i) ) {
                vx[i] = hashGet(&hash,pt->v[i1],pt->v[i2]);
                assert(vx[i]);
                j = i;
            }
        }
        if ( pt->flag == 1 || pt->flag == 2 || pt->flag == 4 ) {
            ier = split1(mesh,met,k,j,vx);
            assert(ier);
            ns++;
        }
        else if ( pt->flag == 7 ) {
            ier = split3(mesh,met,k,vx);
            assert(ier);
            ns++;
        }
        else {
            ier = split2(mesh,met,k,vx);
            assert(ier);
            ns++;
        }
    }
    if ( (info.ddebug || abs(info.imprim) > 5) && ns > 0 )
        fprintf(stdout,"     %7d splitted\n",ns);
    free(hash.item);

    return(ns);
}
Ejemplo n.º 9
0
/* Computes the Bezier coefficients associated to the underlying curve to [p0p1].
   isrid = 0 if p0p1 is not a special edge, 1 otherwise */
inline void bezierEdge(MMG5_pMesh mesh,int i0,int i1,double b0[3],double b1[3],char isrid,double v[3]) {
  MMG5_pPoint    p0,p1;
  double    ux,uy,uz,*n1,*n2,*t,ps1,ps2;

  p0 = &mesh->point[i0];
  p1 = &mesh->point[i1];

  ux = p1->c[0] - p0->c[0];
  uy = p1->c[1] - p0->c[1];
  uz = p1->c[2] - p0->c[2];

  if ( isrid ) {
    if ( MS_SIN(p0->tag) ) {
      b0[0] = p0->c[0] + _MMG5_ATHIRD*ux;
      b0[1] = p0->c[1] + _MMG5_ATHIRD*uy;
      b0[2] = p0->c[2] + _MMG5_ATHIRD*uz;
    }
    else {
      t = &p0->n[0];
      ps1 = t[0]*ux + t[1]*uy + t[2]*uz;
      b0[0] = p0->c[0] + _MMG5_ATHIRD*ps1*t[0];
      b0[1] = p0->c[1] + _MMG5_ATHIRD*ps1*t[1];
      b0[2] = p0->c[2] + _MMG5_ATHIRD*ps1*t[2];
    }

    if (MS_SIN(p1->tag) ) {
      b1[0] = p1->c[0] - _MMG5_ATHIRD*ux;
      b1[1] = p1->c[1] - _MMG5_ATHIRD*uy;
      b1[2] = p1->c[2] - _MMG5_ATHIRD*uz;
    }
    else {
      t = &p1->n[0];
      ps1 = -(t[0]*ux + t[1]*uy + t[2]*uz);
      b1[0] = p1->c[0] + _MMG5_ATHIRD*ps1*t[0];
      b1[1] = p1->c[1] + _MMG5_ATHIRD*ps1*t[1];
      b1[2] = p1->c[2] + _MMG5_ATHIRD*ps1*t[2];
    }
  }

  /* regular edge */
  else {
    if ( MS_SIN(p0->tag) ) {
      b0[0] = p0->c[0] + _MMG5_ATHIRD*ux;
      b0[1] = p0->c[1] + _MMG5_ATHIRD*uy;
      b0[2] = p0->c[2] + _MMG5_ATHIRD*uz;
    }
    else {
      if ( MG_GEO & p0->tag ) {
        n1 = &mesh->xpoint[p0->ig].n1[0];
        n2 = &mesh->xpoint[p0->ig].n2[0];
        ps1 = v[0]*n1[0] + v[1]*n1[1] + v[2]*n1[2];
        ps2 = v[0]*n2[0] + v[1]*n2[1] + v[2]*n2[2];
        if ( ps1 < ps2 ) {
          n1 = &mesh->xpoint[p0->ig].n2[0];
          ps1 = ps2;
        }
      }
      else if ( MG_REF & p0->tag ) {
        n1 = &mesh->xpoint[p0->ig].n1[0];
        ps1 = ux*n1[0] + uy*n1[1] + uz*n1[2];
      }
      else {
        n1 = &p0->n[0];
        ps1 = ux*n1[0] + uy*n1[1] + uz*n1[2];
      }
      b0[0] = _MMG5_ATHIRD*(2.0*p0->c[0] + p1->c[0] - ps1*n1[0]);
      b0[1] = _MMG5_ATHIRD*(2.0*p0->c[1] + p1->c[1] - ps1*n1[1]);
      b0[2] = _MMG5_ATHIRD*(2.0*p0->c[2] + p1->c[2] - ps1*n1[2]);
    }

    if ( MS_SIN(p1->tag) ) {
      b1[0] = p1->c[0] - _MMG5_ATHIRD*ux;
      b1[1] = p1->c[1] - _MMG5_ATHIRD*uy;
      b1[2] = p1->c[2] - _MMG5_ATHIRD*uz;
    }
    else {
      if ( MG_GEO & p1->tag ) {
        n1 = &mesh->xpoint[p1->ig].n1[0];
        n2 = &mesh->xpoint[p1->ig].n2[0];
        ps1 = -(v[0]*n1[0] + v[1]*n1[1] + v[2]*n1[2]);
        ps2 = -(v[0]*n2[0] + v[1]*n2[1] + v[2]*n2[2]);
        if ( fabs(ps2) < fabs(ps1) ) {
          n1 = &mesh->xpoint[p1->ig].n2[0];
          ps1 = ps2;
        }
      }
      else if ( MG_REF & p1->tag ) {
        n1 = &mesh->xpoint[p1->ig].n1[0];
        ps1 = -(ux*n1[0] + uy*n1[1] + uz*n1[2]);
      }
      else {
        n1 = &p1->n[0];
        ps1 = -(ux*n1[0] + uy*n1[1] + uz*n1[2]);
      }
      b1[0] = _MMG5_ATHIRD*(2.0*p1->c[0] + p0->c[0] - ps1*n1[0]);
      b1[1] = _MMG5_ATHIRD*(2.0*p1->c[1] + p0->c[1] - ps1*n1[1]);
      b1[2] = _MMG5_ATHIRD*(2.0*p1->c[2] + p0->c[2] - ps1*n1[2]);
    }
  }
}
Ejemplo n.º 10
0
/**
 * \param mesh pointer toward the mesh structure.
 * \param met pointer toward the sol structure.
 * \param np0 index of edge's extremity.
 * \param np1 index of edge's extremity.
 * \param isedg 1 if the edge is a ridge, 0 otherwise.
 * \return length of edge according to the prescribed metric.
 *
 * Compute length of edge \f$[i0;i1]\f$ according to the prescribed aniso.
 * metric.
 *
 */
double _MMG5_lenedg_ani(MMG5_pMesh mesh,MMG5_pSol met,int np0,int np1,char isedg) {
  MMG5_pPoint   p0,p1;
  double        gammaprim0[3],gammaprim1[3],t[3],*n1,*n2,ux,uy,uz,ps1,ps2,l0,l1;
  double        *m0,*m1,met0[6],met1[6];

  p0 = &mesh->point[np0];
  p1 = &mesh->point[np1];

  ux = p1->c[0] - p0->c[0];
  uy = p1->c[1] - p0->c[1];
  uz = p1->c[2] - p0->c[2];

  /* computation of the two tangent vectors to the underlying curve of [i0i1] */
  if ( MS_SIN(p0->tag) ) {
    gammaprim0[0] = ux;
    gammaprim0[1] = uy;
    gammaprim0[2] = uz;
  }
  else if ( isedg ) {
    memcpy(t,p0->n,3*sizeof(double));
    ps1 = ux*t[0] + uy*t[1] + uz*t[2];
    gammaprim0[0] = ps1*t[0];
    gammaprim0[1] = ps1*t[1];
    gammaprim0[2] = ps1*t[2];
  }
  else {
    if ( MG_GEO & p0->tag ) {
      //assert(p0->ig);
      n1 = &mesh->xpoint[p0->ig].n1[0];
      n2 = &mesh->xpoint[p0->ig].n2[0];
      ps1 = ux*n1[0] + uy*n1[1] + uz*n1[2];
      ps2 = ux*n2[0] + uy*n2[1] + uz*n2[2];

      if ( fabs(ps2) < fabs(ps1) ) {
        n1  = &mesh->xpoint[p0->ig].n2[0];
        ps1 = ps2;
      }
    }
    else if ( MG_REF & p0->tag ) {
      n1  = &mesh->xpoint[p0->ig].n1[0];
      ps1 = ux*n1[0] + uy*n1[1] + uz*n1[2];
    }
    else {
      n1  = &(p0->n[0]);
      ps1 = ux*n1[0] + uy*n1[1] + uz*n1[2];
    }
    gammaprim0[0] = ux - ps1*n1[0];
    gammaprim0[1] = uy - ps1*n1[1];
    gammaprim0[2] = uz - ps1*n1[2];
  }

  if ( MS_SIN(p1->tag) ) {
    gammaprim1[0] = -ux;
    gammaprim1[1] = -uy;
    gammaprim1[2] = -uz;
  }
  else if ( isedg ) {
    memcpy(t,p1->n,3*sizeof(double));
    ps1 = -ux*t[0] - uy*t[1] - uz*t[2];
    gammaprim1[0] = ps1*t[0];
    gammaprim1[1] = ps1*t[1];
    gammaprim1[2] = ps1*t[2];
  }
  else {
    if ( MG_GEO & p1->tag ) {
      n1 = &mesh->xpoint[p1->ig].n1[0];
      n2 = &mesh->xpoint[p1->ig].n2[0];
      ps1 = -ux*n1[0] - uy*n1[1] - uz*n1[2];
      ps2 = -ux*n2[0] - uy*n2[1] - uz*n2[2];

      if ( fabs(ps2) < fabs(ps1) ) {
        n1  = &mesh->xpoint[p1->ig].n2[0];
        ps1 = ps2;
      }
    }
    else if ( MG_REF & p1->tag ) {
      n1  = &mesh->xpoint[p1->ig].n1[0];
      ps1 = - ux*n1[0] - uy*n1[1] - uz*n1[2];
    }
    else {
      n1  = &(p1->n[0]);
      ps1 = -ux*n1[0] - uy*n1[1] - uz*n1[2];
    }
    gammaprim1[0] = - ux - ps1*n1[0];
    gammaprim1[1] = - uy - ps1*n1[1];
    gammaprim1[2] = - uz - ps1*n1[2];
  }

  /* Set metrics */
  if ( MS_SIN(p0->tag) ) {
    m0 = &met->m[6*(np0)+1];
  }
  else if ( MG_GEO & p0->tag ) {
    if ( !_MMG5_buildridmet(mesh,met,np0,ux,uy,uz,met0) )  return(-1.0);
    m0 = met0;
  }
  else {
    m0 = &met->m[6*(np0)+1];
  }

  if ( MS_SIN(p1->tag) ) {
    m1 = &met->m[6*(np1)+1];
  }
  else if ( MG_GEO & p1->tag ) {
    if ( !_MMG5_buildridmet(mesh,met,np1,ux,uy,uz,met1) )  return(-1.0);
    m1 = met1;
  }
  else {
    m1 = &met->m[6*(np1)+1];
  }

  /* computation of the length of the two tangent vectors in their respective tangent plane */
  l0 = m0[0]*gammaprim0[0]*gammaprim0[0] + m0[3]*gammaprim0[1]*gammaprim0[1] \
    + m0[5]*gammaprim0[2]*gammaprim0[2] \
    + 2.0*m0[1]*gammaprim0[0]*gammaprim0[1]  + 2.0*m0[2]*gammaprim0[0]*gammaprim0[2] \
    + 2.0*m0[4]*gammaprim0[1]*gammaprim0[2];

  l1 = m1[0]*gammaprim1[0]*gammaprim1[0] + m1[3]*gammaprim1[1]*gammaprim1[1] \
    + m1[5]*gammaprim1[2]*gammaprim1[2] \
    +2.0*m1[1]*gammaprim1[0]*gammaprim1[1]  + 2.0*m1[2]*gammaprim1[0]*gammaprim1[2] \
    + 2.0*m1[4]*gammaprim1[1]*gammaprim1[2];

  if(l0 < 0) {
    printf("neg %e\n",l0);
    l0 =1;
  }
  if(l1 < 0) {
    printf("neg1 %e\n",l1);
    l1 = 1;
  }
  l0 = 0.5*(sqrt(l0) + sqrt(l1));
  return(l0);
}
Ejemplo n.º 11
0
/**
 * \param mesh pointer toward the mesh structure.
 * \param pt pointer toward the triangle structure.
 * \param pb pointer toward the computed Bezier structure.
 * \param ori triangle orientation (unused but here for compatibility
 * with the _MMG5_bezierCP interface).
 * \return 1.
 *
 * Compute Bezier control points on triangle \a pt (cf. Vlachos)
 *
 * \todo merge with the _MMG5_mmg3dBeizerCP function and remove the pointer
 * toward this functions.
 *
 */
int _MMG5_mmgsBezierCP(MMG5_pMesh mesh,MMG5_Tria *pt,_MMG5_pBezier pb,
                       char ori) {
  MMG5_pPoint    p[3];
  double         *n1,*n2,nt[3],ps,ps2,dd,ux,uy,uz,ll;
  int            ia,ib,ic;
  char           i,i1,i2;

  ia   = pt->v[0];
  ib   = pt->v[1];
  ic   = pt->v[2];
  p[0] = &mesh->point[ia];
  p[1] = &mesh->point[ib];
  p[2] = &mesh->point[ic];

  memset(pb,0,sizeof(_MMG5_Bezier));

  /* first 3 CP = vertices, normals */
  for (i=0; i<3; i++) {
    memcpy(&pb->b[i],p[i]->c,3*sizeof(double));
    pb->p[i] = p[i];

    if ( MS_SIN(p[i]->tag) ) {
      _MMG5_nortri(mesh,pt,pb->n[i]);
    }
    else if ( MG_EDG(p[i]->tag) ) {
      _MMG5_nortri(mesh,pt,nt);

      n1 = &mesh->xpoint[p[i]->ig].n1[0];
      n2 = &mesh->xpoint[p[i]->ig].n2[0];

      ps  = n1[0]*nt[0] + n1[1]*nt[1] + n1[2]*nt[2];
      ps2 = n2[0]*nt[0] + n2[1]*nt[1] + n2[2]*nt[2];
      if ( fabs(ps) > fabs(ps2) )
        memcpy(&pb->n[i],n1,3*sizeof(double));
      else
        memcpy(&pb->n[i],n2,3*sizeof(double));
      memcpy(&pb->t[i],p[i]->n,3*sizeof(double));
    }
    else
      memcpy(&pb->n[i],p[i]->n,3*sizeof(double));
  }

  /* compute control points along edges */
  for (i=0; i<3; i++) {
    i1 = _MMG5_inxt2[i];
    i2 = _MMG5_iprv2[i];

    ux = p[i2]->c[0] - p[i1]->c[0];
    uy = p[i2]->c[1] - p[i1]->c[1];
    uz = p[i2]->c[2] - p[i1]->c[2];

    ll = ux*ux + uy*uy + uz*uz;   // A PROTEGER !!!!

    /* choose normals */
    n1 = pb->n[i1];
    n2 = pb->n[i2];

    /* check for boundary curve */
    if ( MG_EDG(pt->tag[i]) ) {
      if ( MS_SIN(p[i1]->tag) ) {
        dd = 1.0 / 3.0;
        pb->b[2*i+3][0] = p[i1]->c[0] + dd * ux;
        pb->b[2*i+3][1] = p[i1]->c[1] + dd * uy;
        pb->b[2*i+3][2] = p[i1]->c[2] + dd * uz;
      }
      else {
        dd = (ux*pb->t[i1][0] + uy*pb->t[i1][1] + uz*pb->t[i1][2]) / 3.0;
        pb->b[2*i+3][0] = p[i1]->c[0] + dd * pb->t[i1][0];
        pb->b[2*i+3][1] = p[i1]->c[1] + dd * pb->t[i1][1];
        pb->b[2*i+3][2] = p[i1]->c[2] + dd * pb->t[i1][2];
      }
      if ( MS_SIN(p[i2]->tag) ) {
        dd = 1.0 / 3.0;
        pb->b[2*i+4][0] = p[i2]->c[0] - dd * ux;
        pb->b[2*i+4][1] = p[i2]->c[1] - dd * uy;
        pb->b[2*i+4][2] = p[i2]->c[2] - dd * uz;
      }
      else {
        dd = -(ux*pb->t[i2][0] + uy*pb->t[i2][1] + uz*pb->t[i2][2]) / 3.0;
        pb->b[2*i+4][0] = p[i2]->c[0] + dd * pb->t[i2][0];
        pb->b[2*i+4][1] = p[i2]->c[1] + dd * pb->t[i2][1];
        pb->b[2*i+4][2] = p[i2]->c[2] + dd * pb->t[i2][2];
      }

      /* tangent evaluation */
      ps = ux*(pb->t[i1][0]+pb->t[i2][0]) + uy*(pb->t[i1][1]+pb->t[i2][1]) + uz*(pb->t[i1][2]+pb->t[i2][2]);
      ps = 2.0 * ps / ll;
      pb->t[i+3][0] = pb->t[i1][0] + pb->t[i2][0] - ps*ux;
      pb->t[i+3][1] = pb->t[i1][1] + pb->t[i2][1] - ps*uy;
      pb->t[i+3][2] = pb->t[i1][2] + pb->t[i2][2] - ps*uz;
      dd = pb->t[i+3][0]*pb->t[i+3][0] + pb->t[i+3][1]*pb->t[i+3][1] + pb->t[i+3][2]*pb->t[i+3][2];
      if ( dd > _MMG5_EPSD2 ) {
        dd = 1.0 / sqrt(dd);
        pb->t[i+3][0] *= dd;
        pb->t[i+3][1] *= dd;
        pb->t[i+3][2] *= dd;
      }
    }

    else { /* internal edge */
      ps = ux*n1[0] + uy*n1[1] + uz*n1[2];
      pb->b[2*i+3][0] = (2.0*p[i1]->c[0] + p[i2]->c[0] - ps*n1[0]) / 3.0;
      pb->b[2*i+3][1] = (2.0*p[i1]->c[1] + p[i2]->c[1] - ps*n1[1]) / 3.0;
      pb->b[2*i+3][2] = (2.0*p[i1]->c[2] + p[i2]->c[2] - ps*n1[2]) / 3.0;

      ps = -(ux*n2[0] + uy*n2[1] + uz*n2[2]);
      pb->b[2*i+4][0] = (2.0*p[i2]->c[0] + p[i1]->c[0] - ps*n2[0]) / 3.0;
      pb->b[2*i+4][1] = (2.0*p[i2]->c[1] + p[i1]->c[1] - ps*n2[1]) / 3.0;
      pb->b[2*i+4][2] = (2.0*p[i2]->c[2] + p[i1]->c[2] - ps*n2[2]) / 3.0;
    }

    /* normal evaluation */
    ps = ux*(n1[0]+n2[0]) + uy*(n1[1]+n2[1]) + uz*(n1[2]+n2[2]);
    ps = 2.0*ps / ll;
    pb->n[i+3][0] = n1[0] + n2[0] - ps*ux;
    pb->n[i+3][1] = n1[1] + n2[1] - ps*uy;
    pb->n[i+3][2] = n1[2] + n2[2] - ps*uz;
    dd = pb->n[i+3][0]*pb->n[i+3][0] + pb->n[i+3][1]*pb->n[i+3][1] + pb->n[i+3][2]*pb->n[i+3][2];
    if ( dd > _MMG5_EPSD2 ) {
      dd = 1.0 / sqrt(dd);
      pb->n[i+3][0] *= dd;
      pb->n[i+3][1] *= dd;
      pb->n[i+3][2] *= dd;
    }
  }

  /* Central Bezier coefficient */
  for (i=0; i<3; i++) {
    dd = 0.5 / 3.0;
    pb->b[9][0] -= dd * pb->b[i][0];
    pb->b[9][1] -= dd * pb->b[i][1];
    pb->b[9][2] -= dd * pb->b[i][2];
  }
  for (i=0; i<3; i++) {
    pb->b[9][0] += 0.25 * (pb->b[2*i+3][0] + pb->b[2*i+4][0]);
    pb->b[9][1] += 0.25 * (pb->b[2*i+3][1] + pb->b[2*i+4][1]);
    pb->b[9][2] += 0.25 * (pb->b[2*i+3][2] + pb->b[2*i+4][2]);
  }

  return(1);
}
Ejemplo n.º 12
0
/**
 * \param mesh pointer toward the mesh structure.
 * \param met pointer toward the meric structure.
 * \param ptt pointer toward the triangle structure.
 * \return The computed area.
 *
 * Compute the area of the surface triangle \a ptt with respect to
 * the anisotropic metric \a met.
 *
 */
double _MMG5_surftri_ani(MMG5_pMesh mesh,MMG5_pSol met,MMG5_pTria ptt) {
  MMG5_pPoint    p[3];
  _MMG5_Bezier    b;
  int       np[3];
  double    surf,ux,uy,uz,dens,m[3][6],J[3][2],mJ[3][2],tJmJ[2][2];
  char      i,i1,i2;

  surf = 0.0;

  for (i=0; i<3; i++) {
    np[i] = ptt->v[i];
    p[i]  = &mesh->point[np[i]];
  }
  if ( !_MMG5_bezierCP(mesh,ptt,&b,1) ) return(0.0);

  /* Set metric tensors at vertices of tria iel */
  for(i=0; i<3; i++) {
    i1 = _MMG5_inxt2[i];
    i2 = _MMG5_iprv2[i];
    ux = 0.5*(p[i1]->c[0]+p[i2]->c[0]) - p[i]->c[0];
    uy = 0.5*(p[i1]->c[1]+p[i2]->c[1]) - p[i]->c[1];
    uz = 0.5*(p[i1]->c[2]+p[i2]->c[2]) - p[i]->c[2];

    if ( MS_SIN(p[i]->tag) ) {
      memcpy(&m[i][0],&met->m[6*np[i]+1],6*sizeof(double));
    }
    else if ( p[i]->tag & MG_GEO ) {
      if ( !_MMG5_buildridmet(mesh,met,np[i],ux,uy,uz,&m[i][0]) )  return(0.0);
    }
    else {
      memcpy(&m[i][0],&met->m[6*np[i]+1],6*sizeof(double));
    }
  }

  /* Compute density integrand of volume at the 3 vertices of T */
  for (i=0; i<3; i++) {
    if ( i == 0 ) {
      J[0][0] = 3.0*( b.b[7][0] - b.b[0][0] ) ; J[0][1] = 3.0*( b.b[6][0] - b.b[0][0] );
      J[1][0] = 3.0*( b.b[7][1] - b.b[0][1] ) ; J[1][1] = 3.0*( b.b[6][1] - b.b[0][1] );
      J[2][0] = 3.0*( b.b[7][2] - b.b[0][2] ) ; J[2][1] = 3.0*( b.b[6][2] - b.b[0][2] );
    }
    else if ( i == 1 ) {
      J[0][0] = 3.0*( b.b[1][0] - b.b[8][0] ) ; J[0][1] = 3.0*( b.b[3][0] - b.b[8][0] );
      J[1][0] = 3.0*( b.b[1][1] - b.b[8][1] ) ; J[1][1] = 3.0*( b.b[3][1] - b.b[8][1] );
      J[2][0] = 3.0*( b.b[1][2] - b.b[8][2] ) ; J[2][1] = 3.0*( b.b[3][2] - b.b[8][2] );
    }
    else {
      J[0][0] = 3.0*( b.b[4][0] - b.b[5][0] ) ; J[0][1] = 3.0*( b.b[2][0] - b.b[5][0] );
      J[1][0] = 3.0*( b.b[4][1] - b.b[5][1] ) ; J[1][1] = 3.0*( b.b[2][1] - b.b[5][1] );
      J[2][0] = 3.0*( b.b[4][2] - b.b[5][2] ) ; J[2][1] = 3.0*( b.b[2][2] - b.b[5][2] );
    }

    mJ[0][0] = m[i][0]*J[0][0] + m[i][1]*J[1][0] + m[i][2]*J[2][0];
    mJ[1][0] = m[i][1]*J[0][0] + m[i][3]*J[1][0] + m[i][4]*J[2][0];
    mJ[2][0] = m[i][2]*J[0][0] + m[i][4]*J[1][0] + m[i][5]*J[2][0];

    mJ[0][1] = m[i][0]*J[0][1] + m[i][1]*J[1][1] + m[i][2]*J[2][1];
    mJ[1][1] = m[i][1]*J[0][1] + m[i][3]*J[1][1] + m[i][4]*J[2][1];
    mJ[2][1] = m[i][2]*J[0][1] + m[i][4]*J[1][1] + m[i][5]*J[2][1];

    /* dens = sqrt(tJacsigma * M * Jacsigma )*/
    tJmJ[0][0] = J[0][0]*mJ[0][0] + J[1][0]*mJ[1][0] + J[2][0]*mJ[2][0];
    tJmJ[0][1] = J[0][0]*mJ[0][1] + J[1][0]*mJ[1][1] + J[2][0]*mJ[2][1];
    tJmJ[1][0] = J[0][1]*mJ[0][0] + J[1][1]*mJ[1][0] + J[2][1]*mJ[2][0];
    tJmJ[1][1] = J[0][1]*mJ[0][1] + J[1][1]*mJ[1][1] + J[2][1]*mJ[2][1];

    dens = tJmJ[0][0]*tJmJ[1][1] - tJmJ[1][0]*tJmJ[0][1];
    if ( dens < 0.0 ) {
      //fprintf(stdout,"  ## Density should be positive : %E for elt %d %d %d \n",dens,ptt->v[0],ptt->v[1],ptt->v[2]);
      //return(0.0);
    }
    surf += sqrt(fabs(dens));
  }

  surf *= _MMG5_ATHIRD;
  return(surf);
}
Ejemplo n.º 13
0
/* collapse edge i of k, i1->i2 */
int litcol(MMG5_pMesh mesh,int k,char i,double kali) {
  MMG5_pTria     pt,pt0,pt1;
  MMG5_pPoint    p1,p2;
  double         kal,ps,cosnold,cosnnew,n0old[3],n0new[3],n1old[3],n1new[3],n00old[3],n00new[3];
  int            *adja,list[_MMG5_LMAX+2],jel,ip2,l,ilist;
  char           i1,i2,j,jj,j2,open;

  pt0 = &mesh->tria[0];
  pt  = &mesh->tria[k];
  i1  = _MMG5_inxt2[i];
  i2  = _MMG5_iprv2[i];
  ip2 = pt->v[i2];

  /* collect all triangles around vertex i1 */
  ilist = boulet(mesh,k,i1,list);

  /* check for open ball */
  adja = &mesh->adja[3*(k-1)+1];
  open = adja[i] == 0;

  if ( ilist > 3 ) {
    /* check references */
    jel = list[1] / 3;
    pt1 = &mesh->tria[jel];
    if ( abs(pt->ref) != abs(pt1->ref) )  return(0);

    /* analyze ball */
    for (l=1; l<ilist-1+open; l++) {
      jel = list[l] / 3;
      j   = list[l] % 3;
      jj  = _MMG5_inxt2[j];
      j2  = _MMG5_iprv2[j];
      pt1 = &mesh->tria[jel];

      /* check normal flipping */
      if ( !_MMG5_nortri(mesh,pt1,n1old) )  return(0);
      memcpy(pt0,pt1,sizeof(MMG5_Tria));
      pt0->v[j] = ip2;
      if ( !_MMG5_nortri(mesh,pt0,n1new) )  return(0);
      ps = n1new[0]*n1old[0] + n1new[1]*n1old[1]  + n1new[2]*n1old[2];
      if ( ps < 0.0 )  return(0);

      /* keep normals at 1st triangles */
      if ( l == 1 && !open ) {
        memcpy(n00old,n1old,3*sizeof(double));
        memcpy(n00new,n1new,3*sizeof(double));
      }

      /* check normals deviation */
      if ( !(pt1->tag[j2] & MG_GEO) ) {
        if ( l > 1 ) {
          cosnold = n0old[0]*n1old[0] + n0old[1]*n1old[1] + n0old[2]*n1old[2];
          cosnnew = n0new[0]*n1new[0] + n0new[1]*n1new[1] + n0new[2]*n1new[2];
          if ( cosnold < _MMG5_ANGEDG ) {
            if ( cosnnew < MG_MIN(0.0,cosnold) )  return(0);
          }
          else if ( cosnnew < _MMG5_ANGEDG )  return(0);
        }

        memcpy(n0old,n1old,3*sizeof(double));
        memcpy(n0new,n1new,3*sizeof(double));
      }
      /* check quality */
      kal = ALPHAD*_MMG5_caltri_iso(mesh,NULL,pt0);
      if ( kal < NULKAL )  return(0);
    }

    /* check angle between 1st and last triangles */
    if ( !open ) {
      cosnold = n00old[0]*n1old[0] + n00old[1]*n1old[1] + n00old[2]*n1old[2];
      cosnnew = n00new[0]*n1new[0] + n00new[1]*n1new[1] + n00new[2]*n1new[2];
      if ( cosnold < _MMG5_ANGEDG ) {
        if ( cosnnew < MG_MIN(0.0,cosnold) )  return(0);
      }
      else if ( cosnnew < _MMG5_ANGEDG )  return(0);

      /* other reference checks */
      jel = list[ilist-1] / 3;
      pt  = &mesh->tria[jel];
      jel = list[ilist-2] / 3;
      pt1 = &mesh->tria[jel];
      if ( abs(pt->ref) != abs(pt1->ref) )  return(0);
    }

    return(colver(mesh,list,ilist));
  }

  /* specific test: no collapse if any interior edge is EDG */
  else if ( ilist == 3 ) {
    p1 = &mesh->point[pt->v[i1]];
    if ( MS_SIN(p1->tag) )  return(0);
    else if (  MG_EDG(pt->tag[i2]) && !MG_EDG(pt->tag[i]) )  return(0);
    else if ( !MG_EDG(pt->tag[i2]) &&  MG_EDG(pt->tag[i]) )  return(0);
    else if (  MG_EDG(pt->tag[i2]) &&  MG_EDG(pt->tag[i]) && MG_EDG(pt->tag[i1]) )  return(0);

    return(colver3(mesh,list));
  }

  /* for specific configurations along open ridge */
  else if ( ilist == 2 ) {
    if ( !open )  return(0);
    jel = list[1] / 3;
    j   = list[1] % 3;
    jj  = _MMG5_inxt2[j];
    pt1 = &mesh->tria[jel];
    if ( abs(pt->ref) != abs(pt1->ref) )  return(0);
    else if ( !(pt1->tag[jj] & MG_GEO) )  return(0);

    p1 = &mesh->point[pt->v[i1]];
    p2 = &mesh->point[pt1->v[jj]];
    if ( p2->tag > p1->tag || p2->ref != p1->ref )  return(0);

    return(colver2(mesh,list));
  }

  return(0);
}
Ejemplo n.º 14
0
/* check if geometry preserved by collapsing edge i */
int chkcol(MMG5_pMesh mesh,MMG5_pSol met,int k,char i,int *list,char typchk) {
  MMG5_pTria     pt,pt0,pt1,pt2;
  MMG5_pPoint    p1,p2;
  double         len,lon,ps,cosnold,cosnnew,kal,n0old[3],n1old[3],n00old[3];
  double         n0new[3],n1new[3],n00new[3];
  int            *adja,jel,kel,ip1,ip2,l,ll,ilist;
  char           i1,i2,j,jj,j2,lj,open,voy;

  pt0 = &mesh->tria[0];
  pt  = &mesh->tria[k];
  i1  = _MMG5_inxt2[i];
  i2  = _MMG5_iprv2[i];
  ip1 = pt->v[i1];
  ip2 = pt->v[i2];
  if ( typchk == 2 && met->m ) {
    lon = _MMG5_lenedg(mesh,met,ip1,ip2,0);
    lon = MG_MIN(lon,LSHRT);
    lon = MG_MAX(1.0/lon,LLONG);
  }

  /* collect all triangles around vertex i1 */
  ilist = boulechknm(mesh,k,i1,list);
  if ( ilist <= 0 )  return(0);

  /* check for open ball */
  adja = &mesh->adja[3*(k-1)+1];
  open = adja[i] == 0;

  if ( ilist > 3 ) {
    /* check references */
    if ( MG_EDG(pt->tag[i2]) ) {
      jel = list[1] / 3;
      pt1 = &mesh->tria[jel];
      if ( abs(pt->ref) != abs(pt1->ref) )  return(0);
    }

    /* analyze ball */
    for (l=1; l<ilist-1+open; l++) {
      jel = list[l] / 3;
      j   = list[l] % 3;
      jj  = _MMG5_inxt2[j];
      j2  = _MMG5_iprv2[j];
      pt1 = &mesh->tria[jel];

      /* check length */
      if ( typchk == 2 && met->m && !MG_EDG(mesh->point[ip2].tag) ) {
        ip1 = pt1->v[j2];
        len = _MMG5_lenedg(mesh,met,ip1,ip2,0);
        if ( len > lon )  return(0);
      }

      /* check normal flipping */
      if ( !_MMG5_nortri(mesh,pt1,n1old) )  return(0);
      memcpy(pt0,pt1,sizeof(MMG5_Tria));
      pt0->v[j] = ip2;
      if ( !_MMG5_nortri(mesh,pt0,n1new) )  return(0);

      ps = n1new[0]*n1old[0] + n1new[1]*n1old[1]  + n1new[2]*n1old[2];
      if ( ps < 0.0 )  return(0);

      /* keep normals at 1st triangles */
      if ( l == 1 && !open ) {
        memcpy(n00old,n1old,3*sizeof(double));
        memcpy(n00new,n1new,3*sizeof(double));
      }

      /* check normals deviation */
      if ( !(pt1->tag[j2] & MG_GEO) ) {
        if ( l > 1 ) {
          cosnold = n0old[0]*n1old[0] + n0old[1]*n1old[1] + n0old[2]*n1old[2];
          cosnnew = n0new[0]*n1new[0] + n0new[1]*n1new[1] + n0new[2]*n1new[2];
          if ( cosnold < _MMG5_ANGEDG ) {
            if ( cosnnew < cosnold )  return(0);
          }
          else if ( cosnnew < _MMG5_ANGEDG )  return(0);
        }
      }

      /* check geometric support */
      if ( l == 1 ) {
        pt0->tag[j2] = MG_MAX(pt0->tag[j2],pt->tag[i1]);
      }
      else if ( l == ilist-2+open ) {
        ll = list[ilist-1+open] / 3;
        if ( ll > mesh->nt )  return(0);
        lj = list[ilist-1+open] % 3;
        pt0->tag[jj] = MG_MAX(pt0->tag[jj],mesh->tria[ll].tag[lj]);
      }
      if ( chkedg(mesh,0) )  return(0);

      /* check quality */
      if ( typchk == 2 && met->m )
        kal = ALPHAD*_MMG5_calelt(mesh,met,pt0);
      else
        kal = ALPHAD*_MMG5_caltri_iso(mesh,NULL,pt0);
      if ( kal < NULKAL )  return(0);
       
      memcpy(n0old,n1old,3*sizeof(double));
      memcpy(n0new,n1new,3*sizeof(double));
    }

    /* check angle between 1st and last triangles */
    if ( !open && !(pt->tag[i] & MG_GEO) ) {
      cosnold = n00old[0]*n1old[0] + n00old[1]*n1old[1] + n00old[2]*n1old[2];
      cosnnew = n00new[0]*n1new[0] + n00new[1]*n1new[1] + n00new[2]*n1new[2];
      if ( cosnold < _MMG5_ANGEDG ) {
        if ( cosnnew < cosnold )  return(0);
      }
      else if ( cosnnew < _MMG5_ANGEDG )  return(0);

      /* other checks for reference collapse */
      jel = list[ilist-1] / 3;
      j   = list[ilist-1] % 3;
      j   = _MMG5_iprv2[j];
      pt  = &mesh->tria[jel];
      if ( MG_EDG(pt->tag[j]) ) {
        jel = list[ilist-2] / 3;
        pt1 = &mesh->tria[jel];
        if ( abs(pt->ref) != abs(pt1->ref) )  return(0);
      }
    }
  }

  /* specific test: no collapse if any interior edge is EDG */
  else if ( ilist == 3 ) {
    p1 = &mesh->point[pt->v[i1]];
    if ( MS_SIN(p1->tag) )  return(0);
    else if ( MG_EDG(pt->tag[i2]) && !MG_EDG(pt->tag[i]) )  return(0);
    else if ( !MG_EDG(pt->tag[i2]) && MG_EDG(pt->tag[i]) )  return(0);
    else if ( MG_EDG(pt->tag[i2]) && MG_EDG(pt->tag[i]) && MG_EDG(pt->tag[i1]) )  return(0);

    /* Check geometric approximation */
    jel = list[1] / 3;
    j   = list[1] % 3;
    jj  = _MMG5_inxt2[j];
    j2  = _MMG5_iprv2[j];
    pt0 = &mesh->tria[0];
    pt1 = &mesh->tria[jel];
    memcpy(pt0,pt1,sizeof(MMG5_Tria));
    pt0->v[j] = ip2;

    jel = list[2] / 3;
    j   = list[2] % 3;
    pt1 = &mesh->tria[jel];
    pt0->tag[jj] |= pt1->tag[j];
    pt0->tag[j2] |= pt1->tag[_MMG5_inxt2[j]];
    if ( chkedg(mesh,0) )  return(0);
  }

  /* for specific configurations along open ridge */
  else if ( ilist == 2 ) {
    if ( !open )  return(0);
    jel = list[1] / 3;
    j   = list[1] % 3;

    /* Topological test */
    adja = &mesh->adja[3*(jel-1)+1];
    kel = adja[j] / 3;
    voy = adja[j] % 3;
    pt2 = &mesh->tria[kel];

    if ( pt2->v[voy] == ip2) return(0);

    jj  = _MMG5_inxt2[j];
    pt1 = &mesh->tria[jel];
    if ( abs(pt->ref) != abs(pt1->ref) )  return(0);
    else if ( !(pt1->tag[jj] & MG_GEO) )  return(0);

    p1 = &mesh->point[pt->v[i1]];
    p2 = &mesh->point[pt1->v[jj]];
    if ( p2->tag > p1->tag || p2->ref != p1->ref )  return(0);

    /* Check geometric approximation */
    j2  = _MMG5_iprv2[j];
    pt0 = &mesh->tria[0];
    memcpy(pt0,pt,sizeof(MMG5_Tria));
    pt0->v[i1] = pt1->v[j2];
    if ( chkedg(mesh,0) )  return(0);
  }

  return(ilist);
}
Ejemplo n.º 15
0
Archivo: bezier.c Proyecto: XL64/mmg
/* return Bezier control points on triangle iel (cf. Vlachos) */
int bezierCP(pMesh mesh,int iel,pBezier pb) {
    pTria     pt;
    pPoint    p[3];
    double   *n1,*n2,nt[3],ps,ps2,dd,ux,uy,uz;
    char      i,i1,i2;

    pt   = &mesh->tria[iel];
    p[0] = &mesh->point[pt->v[0]];
    p[1] = &mesh->point[pt->v[1]];
    p[2] = &mesh->point[pt->v[2]];

    memset(pb,0,sizeof(Bezier));

    /* first 3 CP = vertices, normals */
    for (i=0; i<3; i++) {
        memcpy(&pb->b[i],p[i]->c,3*sizeof(double));
        pb->p[i] = p[i];

        if ( MS_SIN(p[i]->tag) ) {
            nortri(mesh,pt,pb->n[i]);
        }
        else if ( MS_EDG(p[i]->tag) ) {
            nortri(mesh,pt,nt);
            n1 = &mesh->geom[p[i]->ig].n1[0];
            n2 = &mesh->geom[p[i]->ig].n2[0];

            ps  = n1[0]*nt[0] + n1[1]*nt[1] + n1[2]*nt[2];
            ps2 = n2[0]*nt[0] + n2[1]*nt[1] + n2[2]*nt[2];
            if ( fabs(ps) > fabs(ps2) )
                memcpy(&pb->n[i],n1,3*sizeof(double));
            else
                memcpy(&pb->n[i],n2,3*sizeof(double));
            memcpy(&pb->t[i],p[i]->n,3*sizeof(double));
        }
        else
            memcpy(&pb->n[i],p[i]->n,3*sizeof(double));
    }

    /* compute control points along edges */
    for (i=0; i<3; i++) {
        i1 = inxt[i];
        i2 = inxt[i1];

        ux = p[i2]->c[0] - p[i1]->c[0];
        uy = p[i2]->c[1] - p[i1]->c[1];
        uz = p[i2]->c[2] - p[i1]->c[2];

        /* choose normals */
        n1 = pb->n[i1];
        n2 = pb->n[i2];

        /* check for boundary curve */
        if ( MS_EDG(pt->tag[i]) ) {
            if ( MS_SIN(p[i1]->tag) ) {
                dd = 1.0 / 3.0;
                pb->b[2*i+3][0] = p[i1]->c[0] + dd * ux;
                pb->b[2*i+3][1] = p[i1]->c[1] + dd * uy;
                pb->b[2*i+3][2] = p[i1]->c[2] + dd * uz;
            }
            else {
                dd = (ux*pb->t[i1][0] + uy*pb->t[i1][1] + uz*pb->t[i1][2]) / 3.0;
                pb->b[2*i+3][0] = p[i1]->c[0] + dd * pb->t[i1][0];
                pb->b[2*i+3][1] = p[i1]->c[1] + dd * pb->t[i1][1];
                pb->b[2*i+3][2] = p[i1]->c[2] + dd * pb->t[i1][2];
            }
            if ( MS_SIN(p[i2]->tag) ) {
                dd = 1.0 / 3.0;
                pb->b[2*i+4][0] = p[i2]->c[0] - dd * ux;
                pb->b[2*i+4][1] = p[i2]->c[1] - dd * uy;
                pb->b[2*i+4][2] = p[i2]->c[2] - dd * uz;
            }
            else {
                dd = -(ux*pb->t[i2][0] + uy*pb->t[i2][1] + uz*pb->t[i2][2]) / 3.0;
                pb->b[2*i+4][0] = p[i2]->c[0] + dd * pb->t[i2][0];
                pb->b[2*i+4][1] = p[i2]->c[1] + dd * pb->t[i2][1];
                pb->b[2*i+4][2] = p[i2]->c[2] + dd * pb->t[i2][2];
            }

            /* tangent evaluation */
            ps = ux*(pb->t[i1][0]+pb->t[i2][0]) + uy*(pb->t[i1][1]+pb->t[i2][1]) + uz*(pb->t[i1][2]+pb->t[i2][2]);
            ps = 2.0*ps / (ux*ux + uy*uy + uz*uz);
            pb->t[i+3][0] = pb->t[i1][0] + pb->t[i2][0] - ps*ux;
            pb->t[i+3][1] = pb->t[i1][1] + pb->t[i2][1] - ps*uy;
            pb->t[i+3][2] = pb->t[i1][2] + pb->t[i2][2] - ps*uz;
            dd = pb->t[i+3][0]*pb->t[i+3][0] + pb->t[i+3][1]*pb->t[i+3][1] + pb->t[i+3][2]*pb->t[i+3][2];
            if ( dd > EPSD2 ) {
                dd = 1.0 / sqrt(dd);
                pb->t[i+3][0] *= dd;
                pb->t[i+3][1] *= dd;
                pb->t[i+3][2] *= dd;
            }
        }
        else { /* internal edge */
            ps = ux*n1[0] + uy*n1[1] + uz*n1[2];
            pb->b[2*i+3][0] = (2.0*p[i1]->c[0] + p[i2]->c[0] - ps*n1[0]) / 3.0;
            pb->b[2*i+3][1] = (2.0*p[i1]->c[1] + p[i2]->c[1] - ps*n1[1]) / 3.0;
            pb->b[2*i+3][2] = (2.0*p[i1]->c[2] + p[i2]->c[2] - ps*n1[2]) / 3.0;

            ps = -(ux*n2[0] + uy*n2[1] + uz*n2[2]);
            pb->b[2*i+4][0] = (2.0*p[i2]->c[0] + p[i1]->c[0] - ps*n2[0]) / 3.0;
            pb->b[2*i+4][1] = (2.0*p[i2]->c[1] + p[i1]->c[1] - ps*n2[1]) / 3.0;
            pb->b[2*i+4][2] = (2.0*p[i2]->c[2] + p[i1]->c[2] - ps*n2[2]) / 3.0;
        }

        /* normal evaluation */
        ps = ux*(n1[0]+n2[0]) + uy*(n1[1]+n2[1]) + uz*(n1[2]+n2[2]);
        ps = 2.0*ps / (ux*ux + uy*uy + uz*uz);
        pb->n[i+3][0] = n1[0] + n2[0] - ps*ux;
        pb->n[i+3][1] = n1[1] + n2[1] - ps*uy;
        pb->n[i+3][2] = n1[2] + n2[2] - ps*uz;
        dd = pb->n[i+3][0]*pb->n[i+3][0] + pb->n[i+3][1]*pb->n[i+3][1] + pb->n[i+3][2]*pb->n[i+3][2];
        if ( dd > EPSD2 ) {
            dd = 1.0 / sqrt(dd);
            pb->n[i+3][0] *= dd;
            pb->n[i+3][1] *= dd;
            pb->n[i+3][2] *= dd;
        }
    }

    /* Central Bezier coefficient */
    for (i=0; i<3; i++) {
        pb->b[9][0] -= (0.5*ATHIRD*pb->b[i][0]);
        pb->b[9][1] -= (0.5*ATHIRD*pb->b[i][1]);
        pb->b[9][2] -= (0.5*ATHIRD*pb->b[i][2]);
    }

    for (i=0; i<3; i++) {
        pb->b[9][0] += 0.25 * (pb->b[2*i+3][0] + pb->b[2*i+4][0]);
        pb->b[9][1] += 0.25 * (pb->b[2*i+3][1] + pb->b[2*i+4][1]);
        pb->b[9][2] += 0.25 * (pb->b[2*i+3][2] + pb->b[2*i+4][2]);
    }

    return(1);
}
Ejemplo n.º 16
0
Archivo: bezier.c Proyecto: XL64/mmg
/* return point o at (u,v) in Bezier patch and normal */
int bezierInt(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 < 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 > EPSD2 ) {
            dd = 1.0 / sqrt(dd);
            ux *= dd;
            uy *= dd;
            uz *= dd;
        }

        if ( MS_SIN(pb->p[1]->tag) ) {
            pb->t[1][0] = ux;
            pb->t[1][1] = uy;
            pb->t[1][2] = uz;
        }
        if ( MS_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 < 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 > EPSD2 ) {
            dd = 1.0 / sqrt(dd);
            ux *= dd;
            uy *= dd;
            uz *= dd;
        }

        if ( MS_SIN(pb->p[0]->tag) ) {
            pb->t[0][0] = ux;
            pb->t[0][1] = uy;
            pb->t[0][2] = uz;
        }
        if ( MS_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 < 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 > EPSD2 ) {
            dd = 1.0 / sqrt(dd);
            ux *= dd;
            uy *= dd;
            uz *= dd;
        }

        if ( MS_SIN(pb->p[0]->tag) ) {
            pb->t[0][0] = ux;
            pb->t[0][1] = uy;
            pb->t[0][2] = uz;
        }
        if ( MS_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 > 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 > EPSD2 ) {
        dd = 1.0 / sqrt(dd);
        to[0] *= dd;
        to[1] *= dd;
        to[2] *= dd;
    }

    return(1);
}