Exemple #1
0
Fichier : mmgs1.c Projet : 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);
}
Exemple #2
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);
}