示例#1
0
文件: tools.c 项目: XL64/mmg
/** compute iso size map */
int _MMG5_DoSol(MMG5_pMesh mesh,MMG5_pSol met) {
    MMG5_pTetra     pt;
    MMG5_pPoint     p1,p2;
    double     ux,uy,uz,dd;
    int        i,k,ia,ib,ipa,ipb;
    int       *mark;

    _MMG5_SAFE_CALLOC(mark,mesh->np+1,int);

    /* Memory alloc */
    met->np     = mesh->np;
    met->npmax  = mesh->npmax;
    met->size   = 1;
    met->dim    = mesh->dim;

    _MMG5_ADD_MEM(mesh,(met->npmax*met->size+1)*sizeof(double),"solution",return(0));
    _MMG5_SAFE_CALLOC(met->m,met->npmax*met->size+1,double);

    /* internal edges */
    for (k=1; k<=mesh->ne; k++) {
        pt = &mesh->tetra[k];
        if ( !pt->v[0] )  continue;

        /* internal edges */
        for (i=0; i<6; i++) {
            ia  = _MMG5_iare[i][0];
            ib  = _MMG5_iare[i][1];
            ipa = pt->v[ia];
            ipb = pt->v[ib];
            p1  = &mesh->point[ipa];
            p2  = &mesh->point[ipb];

            ux  = p1->c[0] - p2->c[0];
            uy  = p1->c[1] - p2->c[1];
            uz  = p1->c[2] - p2->c[2];
            dd  = sqrt(ux*ux + uy*uy + uz*uz);

            met->m[ipa] += dd;
            mark[ipa]++;
            met->m[ipb] += dd;
            mark[ipb]++;
        }
    }

    /* vertex size */
    for (k=1; k<=mesh->np; k++) {
        p1 = &mesh->point[k];
        if ( !mark[k] ) {
            met->m[k] = mesh->info.hmax;
            continue;
        }
        else
            met->m[k] = MG_MIN(mesh->info.hmax,MG_MAX(mesh->info.hmin,met->m[k] / (double)mark[k]));
    }
    _MMG5_SAFE_FREE(mark);
    return(1);
}
示例#2
0
文件: gentools.c 项目: arthurlevy/mmg
/* Compute the intersected (2 x 2) metric between metrics m and n, PRESERVING the directions
   of m. Result is stored in mr*/
int intmetsavedir(MMG5_pMesh mesh, double *m,double *n,double *mr) {
  int    i;
  double lambda[2],vp[2][2],siz,isqhmin;

  isqhmin = 1.0 / (mesh->info.hmin * mesh->info.hmin);
  _MMG5_eigensym(m,lambda,vp);

  for (i=0; i<2; i++) {
    siz = n[0]*vp[i][0]*vp[i][0] + 2.0*n[1]*vp[i][0]*vp[i][1] + n[2]*vp[i][1]*vp[i][1];
    lambda[i] = MG_MAX(lambda[i],siz);
    lambda[i] = MG_MIN(lambda[i],isqhmin);
  }
  mr[0] = lambda[0]*vp[0][0]*vp[0][0] + lambda[1]*vp[1][0]*vp[1][0];
  mr[1] = lambda[0]*vp[0][0]*vp[0][1] + lambda[1]*vp[1][0]*vp[1][1];
  mr[2] = lambda[0]*vp[0][1]*vp[0][1] + lambda[1]*vp[1][1]*vp[1][1];

  return(1);
}
示例#3
0
/**
 * \param n pointer toward the vector that we want to send on the third vector
 * of canonical basis.
 * \param r computed rotation matrix.
 *
 * Compute rotation matrix that sends vector \a n to the third vector of
 * canonical basis.
 *
 */
inline int _MMG5_rotmatrix(double n[3],double r[3][3]) {
  double aa,bb,ab,ll,l,cosalpha,sinalpha;

  aa = n[0]*n[0];
  bb = n[1]*n[1];
  ab = n[0]*n[1];
  ll = aa+bb;
  cosalpha = n[2];
  sinalpha = sqrt(1.0- MG_MIN(1.0,cosalpha*cosalpha));

  /* No rotation needed in this case */
  if ( ll < _MMG5_EPS ) {
    if ( n[2] > 0.0 ) {
      r[0][0] = 1.0 ; r[0][1] = 0.0 ; r[0][2] = 0.0;
      r[1][0] = 0.0 ; r[1][1] = 1.0 ; r[1][2] = 0.0;
      r[2][0] = 0.0 ; r[2][1] = 0.0 ; r[2][2] = 1.0;
    }
    else {
      r[0][0] = -1.0 ; r[0][1] = 0.0 ; r[0][2] = 0.0;
      r[1][0] = 0.0 ; r[1][1] = 1.0 ; r[1][2] = 0.0;
      r[2][0] = 0.0 ; r[2][1] = 0.0 ; r[2][2] = -1.0;
    }
  }
  else {
    l = sqrt(ll);

    r[0][0] = (aa*cosalpha + bb)/ll;
    r[0][1] = ab*(cosalpha-1)/ll;
    r[0][2] = -n[0]*sinalpha/l;
    r[1][0] = r[0][1];
    r[1][1] = (bb*cosalpha + aa)/ll;
    r[1][2] = -n[1]*sinalpha/l;
    r[2][0] = n[0]*sinalpha/l;
    r[2][1] = n[1]*sinalpha/l;
    r[2][2] = cosalpha;
  }
  return(1);
}
示例#4
0
/**
 * \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);
}
示例#5
0
文件: colver.c 项目: arthurlevy/mmg
/* 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);
}
示例#6
0
文件: colver.c 项目: arthurlevy/mmg
/* 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);
}
示例#7
0
文件: swapgen.c 项目: arthurlevy/mmg
/**
 * \param mesh pointer toward the mesh structure
 * \param start tetrahedra in which the swap should be performed
 * \param ia edge that we want to swap
 * \param ilist pointer to store the size of the shell of the edge
 * \param list pointer to store the shell of the edge
 * \param crit improvment coefficient
 * \return 0 if fail, the index of point corresponding to the swapped
 * configuration otherwise (\f$4*k+i\f$).
 *
 * Check whether swap of edge \a ia in \a start should be performed, and
 * return \f$4*k+i\f$ the index of point corresponding to the swapped
 * configuration. The shell of edge is built during the process.
 *
 */
int _MMG5_chkswpgen(MMG5_pMesh mesh,int start,int ia,int *ilist,int *list,double crit) {
  MMG5_pTetra    pt,pt0;
  MMG5_pPoint    p0;
  double    calold,calnew,caltmp;
  int       na,nb,np,adj,piv,npol,refdom,k,l,iel;
  int       *adja,pol[_MMG5_LMAX+2];
  char      i,ipa,ipb,ip,ier;

  pt  = &mesh->tetra[start];
  refdom = pt->ref;

  pt0 = &mesh->tetra[0];
  na  = pt->v[_MMG5_iare[ia][0]];
  nb  = pt->v[_MMG5_iare[ia][1]];
  calold = pt->qual;


  /* Store shell of ia in list, and associated pseudo polygon in pol */
  (*ilist) = 0;
  npol = 0;
  list[(*ilist)] = 6*start+ia;
  (*ilist)++;
  adja = &mesh->adja[4*(start-1)+1];
  adj  = adja[_MMG5_ifar[ia][0]] / 4;      // start travelling by face (ia,0)
  piv  = pt->v[_MMG5_ifar[ia][1]];
  pol[npol] = 4*start + _MMG5_ifar[ia][1];
  npol++;

  while ( adj && adj != start ) {
    pt = &mesh->tetra[adj];
    if ( pt->tag & MG_REQ ) return(0);

    /* Edge is on a boundary between two different domains */
    if ( pt->ref != refdom )  return(0);
    calold = MG_MIN(calold, pt->qual);
    /* identification of edge number in tetra adj */
    for (i=0; i<6; i++) {
      ipa = _MMG5_iare[i][0];
      ipb = _MMG5_iare[i][1];
      if ( (pt->v[ipa] == na && pt->v[ipb] == nb) ||
           (pt->v[ipa] == nb && pt->v[ipb] == na))  break;
    }
    assert(i<6);
    list[(*ilist)] = 6*adj +i;
    (*ilist)++;
    /* overflow */
    if ( (*ilist) > _MMG5_LMAX-3 )  return(0);

    /* set new triangle for travel */
    adja = &mesh->adja[4*(adj-1)+1];
    if ( pt->v[ _MMG5_ifar[i][0] ] == piv ) {
      pol[npol] = 4*adj + _MMG5_ifar[i][1];
      npol++;
      adj = adja[ _MMG5_ifar[i][0] ] / 4;
      piv = pt->v[ _MMG5_ifar[i][1] ];
    }
    else {
      assert(pt->v[ _MMG5_ifar[i][1] ] == piv);
      pol[npol] = 4*adj + _MMG5_ifar[i][0];
      npol++;
      adj = adja[ _MMG5_ifar[i][1] ] /4;
      piv = pt->v[ _MMG5_ifar[i][0] ];
    }
  }
  //CECILE : je vois pas pourquoi ca ameliore de faire ce test
  //plus rapide mais du coup on elimine des swap...
  //4/01/14 commentaire
  //if ( calold*_MMG5_ALPHAD > 0.5 )  return(0);

  /* Prevent swap of an external boundary edge */
  if ( !adj )  return(0);

  assert(npol == (*ilist)); // du coup, apres on pourra virer npol

  /* Find a configuration that enhances the worst quality within the shell */
  for (k=0; k<npol; k++) {
    iel = pol[k] / 4;
    ip  = pol[k] % 4;
    np  = mesh->tetra[iel].v[ip];
    calnew = 1.0;
    ier = 1;

    if ( mesh->info.fem ) {
      p0 = &mesh->point[np];
      if ( p0->tag & MG_BDY ) {
        for (l=0; l<npol;l++) {
          if ( k < npol-1 ) {
            if ( l == k || l == k+1 )  continue;
          }
          else {
            if ( l == npol-1 || l == 0 )  continue;
          }
          iel = pol[l] / 4;
          ip  = pol[l] % 4;
          pt = &mesh->tetra[iel];
          p0 = &mesh->point[pt->v[ip]];
          if ( p0->tag & MG_BDY ) {
            ier = 0;
            break;
          }
        }
      }
      if ( !ier )  continue;
      ier = 1;
    }

    for (l=0; l<(*ilist); l++) {
      /* Do not consider tets of the shell of collapsed edge */
      if ( k < npol-1 ) {
        if ( l == k || l == k+1 )  continue;
      }
      else {
        if ( l == npol-1 || l == 0 )  continue;
      }
      iel = list[l] / 6;
      i   = list[l] % 6;
      pt  = &mesh->tetra[iel];

      /* First tetra obtained from iel */
      memcpy(pt0,pt,sizeof(MMG5_Tetra));
      pt0->v[_MMG5_iare[i][0]] = np;
      caltmp = _MMG5_orcal(mesh,0);
      calnew = MG_MIN(calnew,caltmp);
      /* Second tetra obtained from iel */
      memcpy(pt0,pt,sizeof(MMG5_Tetra));
      pt0->v[_MMG5_iare[i][1]] = np;
      caltmp = _MMG5_orcal(mesh,0);
      calnew = MG_MIN(calnew,caltmp);
      ier = (calnew > crit*calold);
      if ( !ier )  break;
    }
    if ( ier )  return(pol[k]);
  }
  return(0);
}