Esempio n. 1
0
/* Start from triangle start, and pile up triangles by adjacency, till a GEO or REF curve is met ;
   pass all references of travelled faces to ref ; putreq = 1 if boundary edges met must
   be set to MG_REQ, 0 otherwise. */
int setref(MMG5_pMesh mesh,int start,int ref,int putreq) {
  MMG5_pTria      pt,pt1;
  int        *list,*adja,cur,base,k,iel,jel,ilist;
  char       j,voy;

  ilist = cur = 0;
  _MMG5_SAFE_CALLOC(list,mesh->nt+1,int);
  base = ++mesh->base;

  /* Pile up triangles from start, till a GEO boundary is met */
  pt = &mesh->tria[start];
  list[ilist] = start;
  ilist++;
  assert( ilist <= mesh->nt );
  pt->flag = base;

  do {
    iel = list[cur];
    pt = &mesh->tria[iel];
    adja = &mesh->adja[3*(iel-1)+1];

    for(j=0; j<3; j++) {
      if( MG_EDG(pt->tag[j]) ) {
        if( putreq ) {
          pt->tag[j] |= MG_REQ;
          jel = adja[j] / 3;
          voy = adja[j] % 3;
          if( !jel ) continue;
          pt1 = &mesh->tria[jel];
          pt1->tag[voy] |= MG_REQ;
        }
        continue;
      }
      jel = adja[j] / 3;
      assert(jel);
      pt1 = &mesh->tria[jel];
      if ( pt1->flag == base )  continue;

      list[ilist] = jel;
      ilist++;
      assert( ilist <= mesh->nt );
      pt1->flag = base;
    }
    cur++;
  }
  while( cur < ilist );

  /* Set all references of triangles of list to ref */
  for (k=0; k<ilist; k++) {
    iel = list[k];
    pt  = &mesh->tria[iel];
    pt->ref = ref;
    printf("Le tria %d passe a %d \n",k,ref);
  }

  return(1);
}
Esempio n. 2
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);
}
Esempio n. 3
0
/**
 * \param mesh pointer toward the mesh structure.
 * \param met pointer toward the metric structure.
 * \param *warn \a warn is set to 1 if we don't have enough memory to complete mesh.
 * \return -1 if failed.
 * \return number of new points.
 *
 * Split edges of length bigger than _MMG5_LOPTL.
 *
 */
static int _MMG5_adpspl(MMG5_pMesh mesh,MMG5_pSol met, int* warn) {
    MMG5_pTetra     pt;
    MMG5_pxTetra    pxt;
    MMG5_Tria       ptt;
    MMG5_pPoint     p0,p1,ppt;
    MMG5_pxPoint    pxp;
    double     dd,len,lmax,o[3],to[3],ro[3],no1[3],no2[3],v[3];
    int        k,ip,ip1,ip2,list[_MMG5_LMAX+2],ilist,ns,ref,ier;
    char       imax,tag,j,i,i1,i2,ifa0,ifa1;

    *warn=0;
    ns = 0;
    for (k=1; k<=mesh->ne; k++) {
        pt = &mesh->tetra[k];
        if ( !MG_EOK(pt) || (pt->tag & MG_REQ) )   continue;
        pxt = pt->xt ? &mesh->xtetra[pt->xt] : 0;

        /* find longest edge */
        imax = -1; lmax = 0.0;
        for (i=0; i<6; i++) {
            if ( pt->xt && (pxt->tag[i] & MG_REQ) )  continue;
            ip1  = _MMG5_iare[i][0];
            ip2  = _MMG5_iare[i][1];
            len = _MMG5_lenedg(mesh,met,pt->v[ip1],pt->v[ip2]);
            if ( len > lmax ) {
                lmax = len;
                imax = i;
            }
        }
        if ( imax==-1 )
            fprintf(stdout,"%s:%d: Warning: all edges of tetra %d are required or of length null.\n",
                    __FILE__,__LINE__,k);
        if ( lmax < _MMG5_LOPTL )  continue;

        /* proceed edges according to lengths */
        ifa0 = _MMG5_ifar[imax][0];
        ifa1 = _MMG5_ifar[imax][1];
        i  = (pt->xt && (pxt->ftag[ifa1] & MG_BDY)) ? ifa1 : ifa0;
        j  = _MMG5_iarfinv[i][imax];
        i1 = _MMG5_idir[i][_MMG5_inxt2[j]];
        i2 = _MMG5_idir[i][_MMG5_iprv2[j]];
        ip1 = pt->v[i1];
        ip2 = pt->v[i2];
        p0  = &mesh->point[ip1];
        p1  = &mesh->point[ip2];

        /* Case of a boundary face */
        if ( pt->xt && (pxt->ftag[i] & MG_BDY) ) {
            if ( !(MG_GET(pxt->ori,i)) ) continue;
            ref = pxt->edg[_MMG5_iarf[i][j]];
            tag = pxt->tag[_MMG5_iarf[i][j]];
            if ( tag & MG_REQ )  continue;
            tag |= MG_BDY;
            ilist = _MMG5_coquil(mesh,k,imax,list);
            if ( !ilist )  continue;
            else if ( ilist < 0 )
                return(-1);
            if ( tag & MG_NOM ){
                if( !_MMG5_BezierNom(mesh,ip1,ip2,0.5,o,no1,to) )
                    continue;
                else if ( MG_SIN(p0->tag) && MG_SIN(p1->tag) ) {
                    _MMG5_tet2tri(mesh,k,i,&ptt);
                    _MMG5_nortri(mesh,&ptt,no1);
                    if ( !MG_GET(pxt->ori,i) ) {
                        no1[0] *= -1.0;
                        no1[1] *= -1.0;
                        no1[2] *= -1.0;
                    }
                }
            }
            else if ( tag & MG_GEO ) {
                if ( !_MMG5_BezierRidge(mesh,ip1,ip2,0.5,o,no1,no2,to) )
                    continue;
                if ( MG_SIN(p0->tag) && MG_SIN(p1->tag) ) {
                    _MMG5_tet2tri(mesh,k,i,&ptt);
                    _MMG5_nortri(mesh,&ptt,no1);
                    no2[0] = to[1]*no1[2] - to[2]*no1[1];
                    no2[1] = to[2]*no1[0] - to[0]*no1[2];
                    no2[2] = to[0]*no1[1] - to[1]*no1[0];
                    dd = no2[0]*no2[0] + no2[1]*no2[1] + no2[2]*no2[2];
                    if ( dd > _MMG5_EPSD2 ) {
                        dd = 1.0 / sqrt(dd);
                        no2[0] *= dd;
                        no2[1] *= dd;
                        no2[2] *= dd;
                    }
                }
            }
            else if ( tag & MG_REF ) {
                if ( !_MMG5_BezierRef(mesh,ip1,ip2,0.5,o,no1,to) )
                    continue;
            }
            else {
                if ( !_MMG5_norface(mesh,k,i,v) )  continue;
                if ( !_MMG5_BezierReg(mesh,ip1,ip2,0.5,v,o,no1) )
                    continue;
            }
            ier = _MMG5_simbulgept(mesh,list,ilist,o);
            if ( !ier ) {
                ier = _MMG5_dichoto1b(mesh,list,ilist,o,ro);
                memcpy(o,ro,3*sizeof(double));
            }
            ip = _MMG5_newPt(mesh,o,tag);
            if ( !ip ) {
                /* reallocation of point table */
                _MMG5_POINT_REALLOC(mesh,met,ip,mesh->gap,
                              *warn=1;
                              break
                              ,o,tag);
            }
            //CECILE
            if ( met->m )
                met->m[ip] = 0.5 * (met->m[ip1]+met->m[ip2]);
            //CECILE
            ier = _MMG5_split1b(mesh,met,list,ilist,ip,1);
            /* if we realloc memory in _MMG5_split1b pt and pxt pointers are not valid */
            pt = &mesh->tetra[k];
            pxt = pt->xt ? &mesh->xtetra[pt->xt] : 0;

            if ( ier < 0 ) {
                fprintf(stdout," ## Error: unable to split.\n");
                return(-1);
            }
            else if ( !ier ) {
                _MMG5_delPt(mesh,ip);
                continue;
            }
            ns++;
            ppt = &mesh->point[ip];
            if ( MG_EDG(tag) || (tag & MG_NOM) )
                ppt->ref = ref;
            else
                ppt->ref = pxt->ref[i];
            if ( met->m )
                met->m[ip] = 0.5 * (met->m[ip1]+met->m[ip2]);

            pxp = &mesh->xpoint[ppt->xp];
            if ( tag & MG_NOM ){
                memcpy(pxp->n1,no1,3*sizeof(double));
                memcpy(pxp->t,to,3*sizeof(double));
            }
            else if ( tag & MG_GEO ) {
                memcpy(pxp->n1,no1,3*sizeof(double));
                memcpy(pxp->n2,no2,3*sizeof(double));
                memcpy(pxp->t,to,3*sizeof(double));
            }
            else if ( tag & MG_REF ) {
                memcpy(pxp->n1,no1,3*sizeof(double));
                memcpy(pxp->t,to,3*sizeof(double));
            }
            else
                memcpy(pxp->n1,no1,3*sizeof(double));
        }

        /* Case of an internal face */
        else {
            if ( (p0->tag & MG_BDY) && (p1->tag & MG_BDY) ) continue;
Esempio n. 4
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);
}
Esempio n. 5
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);
}
Esempio n. 6
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);
}
Esempio n. 7
0
File: analys.c Progetto: XL64/mmg
/**
 * \param mesh pointer towarad the mesh structure.
 * \return 0 if fail, 1 otherwise.
 *
 * topology: set adjacent, detect Moebius, flip faces, count connected comp.
 *
 */
static int _MMG5_setadj(MMG5_pMesh mesh){
    MMG5_pTria   pt,pt1;
    MMG5_pPoint  ppt;
    int    *adja,*adjb,adji1,adji2,*pile,iad,ipil,ip1,ip2,gen;
    int     k,kk,iel,jel,nf,np,nr,nt,nre,nreq,ncc,ned,nvf,edg;
    char    i,ii,i1,i2,ii1,ii2,voy,tag;

    nvf = nf = ncc = ned = 0;
    _MMG5_SAFE_MALLOC(pile,mesh->nt+1,int);

    pile[1] = 1;
    ipil    = 1;
    pt = &mesh->tria[1];
    pt->flag = 1;

    while ( ipil > 0 ) {
        ncc++;
        do {
            k  = pile[ipil--];
            pt = &mesh->tria[k];
            if ( !MG_EOK(pt) )  continue;
            adja = &mesh->adjt[3*(k-1)+1];
            for (i=0; i<3; i++) {
                i1  = _MMG5_inxt2[i];
                i2  = _MMG5_iprv2[i];
                ip1 = pt->v[i1];
                ip2 = pt->v[i2];
                if ( !mesh->point[ip1].tmp )  mesh->point[ip1].tmp = ++nvf;
                if ( !mesh->point[ip2].tmp )  mesh->point[ip2].tmp = ++nvf;
                if ( MG_EDG(pt->tag[i]) || pt->tag[i] & MG_REQ ) {
                    mesh->point[ip1].tag |= pt->tag[i];
                    mesh->point[ip2].tag |= pt->tag[i];
                }

                /* open boundary */
                if ( !adja[i] ) {
                    pt->tag[i] |= MG_GEO;
                    mesh->point[ip1].tag |= MG_GEO;
                    mesh->point[ip2].tag |= MG_GEO;
                    ned++;
                    continue;
                }
                kk = adja[i] / 3;
                ii = adja[i] % 3;
                if ( kk > k )  ned++;

                /* non manifold edge */
                if ( pt->tag[i] & MG_NOM ) {
                    mesh->point[ip1].tag |= MG_NOM;
                    mesh->point[ip2].tag |= MG_NOM;
                    continue;
                }

                /* store adjacent */
                pt1 = &mesh->tria[kk];
                if ( abs(pt1->ref) != abs(pt->ref) ) {
                    pt->tag[i]   |= MG_REF;
                    if ( !(pt->tag[i] & MG_NOM) )  pt1->tag[ii] |= MG_REF;
                    mesh->point[ip1].tag |= MG_REF;
                    mesh->point[ip2].tag |= MG_REF;
                }

                if ( pt1->flag == 0 ) {
                    pt1->flag    = ncc;
                    pile[++ipil] = kk;
                }

                /* check orientation */
                ii1 = _MMG5_inxt2[ii];
                ii2 = _MMG5_iprv2[ii];
                if ( pt1->v[ii1] == ip1 ) {
                    /* Moebius strip */
                    if ( pt1->base < 0 ) {
                        fprintf(stdout,"  ## Orientation problem (1).\n");
                        return(0);
                    }
                    /* flip orientation */
                    else {
                        pt1->base   = -pt1->base;
                        pt1->v[ii1] = ip2;
                        pt1->v[ii2] = ip1;

                        /* update adj */
                        iad   = 3*(kk-1)+1;
                        adjb  = &mesh->adjt[iad];
                        adji1 = mesh->adjt[iad+ii1];
                        adji2 = mesh->adjt[iad+ii2];
                        adjb[ii1] = adji2;
                        adjb[ii2] = adji1;
                        tag = pt1->tag[ii1];
                        pt1->tag[ii1] = pt1->tag[ii2];
                        pt1->tag[ii2] = tag;
                        edg = pt1->edg[ii1];
                        pt1->edg[ii1] = pt1->edg[ii2];
                        pt1->edg[ii2] = edg;

                        /* modif voyeurs */
                        if ( adjb[ii1] ) {
                            iel = adjb[ii1] / 3;
                            voy = adjb[ii1] % 3;
                            mesh->adjt[3*(iel-1)+1+voy] = 3*kk + ii1;
                        }
                        if ( adjb[ii2] ) {
                            iel = adjb[ii2] / 3;
                            voy = adjb[ii2] % 3;
                            mesh->adjt[3*(iel-1)+1+voy] = 3*kk + ii2;
                        }
                        nf++;
                    }
                }
            }
        }
        while ( ipil > 0 );

        /* find next unmarked triangle */
        ipil = 0;
        for (kk=1; kk<=mesh->nt; kk++) {
            pt = &mesh->tria[kk];
            if ( MG_EOK(pt) && (pt->flag == 0) ) {
                ipil = 1;
                pile[ipil] = kk;
                pt->flag   = ncc+1;
                break;
            }
        }
    }

    /* bilan */
    np = nr = nre = nreq = nt = 0;
    for (k=1; k<=mesh->nt; k++) {
        pt = &mesh->tria[k];
        if ( !MG_EOK(pt) )  continue;
        nt++;
        adja = &mesh->adjt[3*(k-1)+1];
        for (i=0; i<3; i++) {
            ppt = &mesh->point[pt->v[i]];
            if ( !ppt->tmp ) {
                ppt->tmp = 1;
                np++;
            }
            if ( ( !MG_EDG(pt->tag[i]) ) && ( !(pt->tag[i] & MG_REQ) ) )  continue;
            jel  = adja[i] / 3;
            if ( !jel || jel > k ) {
                if ( pt->tag[i] & MG_GEO )  nr++;
                if ( pt->tag[i] & MG_REF )  nre++;
                if ( pt->tag[i] & MG_REQ )  nreq++;
            }
        }
    }
    if ( mesh->info.ddebug ) {
        fprintf(stdout,"  a- ridges: %d found.\n",nr);
        fprintf(stdout,"  a- requir: %d found.\n",nreq);
        fprintf(stdout,"  a- connex: %d connected component(s)\n",ncc);
        fprintf(stdout,"  a- orient: %d flipped\n",nf);
    }
    else if ( abs(mesh->info.imprim) > 3 ) {
        gen = (2 - nvf + ned - nt) / 2;
        fprintf(stdout,"     Connected component: %d,  genus: %d,   reoriented: %d\n",ncc,gen,nf);
        fprintf(stdout,"     Edges: %d,  tagged: %d,  ridges: %d, required: %d, refs: %d\n",
                ned,nr+nre+nreq,nr,nreq,nre);
    }
    _MMG5_SAFE_FREE(pile);
    return(1);
}
Esempio n. 8
0
File: analys.c Progetto: XL64/mmg
/** compute normals at C1 vertices, for C0: tangents */
static int _MMG5_norver(MMG5_pMesh mesh) {
    MMG5_pTria     pt;
    MMG5_pPoint    ppt;
    MMG5_xPoint   *pxp;
    double    n[3],dd;
    int      *adja,k,kk,ng,nn,nt,nf;
    char      i,ii,i1;
    /* recomputation of normals only if mesh->xpoint has been freed */
    if ( mesh->xpoint ) {
        if ( abs(mesh->info.imprim) > 3 || mesh->info.ddebug ) {
            fprintf(stdout,"  ## Warning: no research of boundary points");
            fprintf(stdout," and normals of mesh. ");
            fprintf(stdout,"mesh->xpoint must be freed to enforce analysis.\n");
        }
        return(1);
    }

    /* identify boundary points */
    ++mesh->base;
    mesh->xp = 0;
    for (k=1; k<=mesh->nt; k++) {
        pt = &mesh->tria[k];
        if ( !MG_EOK(pt) )  continue;

        for (i=0; i<3; i++) {
            ppt = &mesh->point[pt->v[i]];
            if ( ppt->flag == mesh->base )  continue;
            else {
                ++mesh->xp;
                ppt->flag = mesh->base;
            }
        }
    }

    /* memory to store normals for boundary points */
    mesh->xpmax  = MG_MAX( (long long)(1.5*mesh->xp),mesh->npmax);

    _MMG5_ADD_MEM(mesh,(mesh->xpmax+1)*sizeof(MMG5_xPoint),"boundary points",return(0));
    _MMG5_SAFE_CALLOC(mesh->xpoint,mesh->xpmax+1,MMG5_xPoint);

    /* compute normals + tangents */
    nn = ng = nt = nf = 0;
    mesh->xp = 0;
    ++mesh->base;
    for (k=1; k<=mesh->nt; k++) {
        pt = &mesh->tria[k];
        if ( !MG_EOK(pt) )  continue;

        adja = &mesh->adjt[3*(k-1)+1];
        for (i=0; i<3; i++) {
            ppt = &mesh->point[pt->v[i]];
            if ( ppt->tag & MG_CRN || ppt->tag & MG_NOM || ppt->flag == mesh->base )  continue;

            /* C1 point */
            if ( !MG_EDG(ppt->tag) ) {
                if ( !_MMG5_boulen(mesh,k,i,n) ) {
                    ++nf;
                    continue;
                }
                else {
                    ++mesh->xp;
                    if(mesh->xp > mesh->xpmax){
                        _MMG5_TAB_RECALLOC(mesh,mesh->xpoint,mesh->xpmax,0.2,MMG5_xPoint,
                                     "larger xpoint table",
                                     mesh->xp--;
                                     return(0));
                    }
                    ppt->xp = mesh->xp;
                    pxp = &mesh->xpoint[ppt->xp];
                    memcpy(pxp->n1,n,3*sizeof(double));
                    ppt->flag = mesh->base;
                    nn++;
                }
            }

            /* along ridge-curve */
            i1  = _MMG5_inxt2[i];
            if ( !MG_EDG(pt->tag[i1]) )  continue;
            else if ( !_MMG5_boulen(mesh,k,i,n) ) {
                ++nf;
                continue;
            }
            ++mesh->xp;
            if(mesh->xp > mesh->xpmax){
                _MMG5_TAB_RECALLOC(mesh,mesh->xpoint,mesh->xpmax,0.2,MMG5_xPoint,
                             "larger xpoint table",
                             mesh->xp--;
                             return(0));
            }
            ppt->xp = mesh->xp;
            pxp = &mesh->xpoint[ppt->xp];
            memcpy(pxp->n1,n,3*sizeof(double));

            if ( pt->tag[i1] & MG_GEO && adja[i1] > 0 ) {
                kk = adja[i1] / 3;
                ii = adja[i1] % 3;
                ii = _MMG5_inxt2[ii];
                if ( !_MMG5_boulen(mesh,kk,ii,n) ) {
                    ++nf;
                    continue;
                }
                memcpy(pxp->n2,n,3*sizeof(double));

                /* compute tangent as intersection of n1 + n2 */
                pxp->t[0] = pxp->n1[1]*pxp->n2[2] - pxp->n1[2]*pxp->n2[1];
                pxp->t[1] = pxp->n1[2]*pxp->n2[0] - pxp->n1[0]*pxp->n2[2];
                pxp->t[2] = pxp->n1[0]*pxp->n2[1] - pxp->n1[1]*pxp->n2[0];
                dd = pxp->t[0]*pxp->t[0] + pxp->t[1]*pxp->t[1] + pxp->t[2]*pxp->t[2];
                if ( dd > _MMG5_EPSD2 ) {
                    dd = 1.0 / sqrt(dd);
                    pxp->t[0] *= dd;
                    pxp->t[1] *= dd;
                    pxp->t[2] *= dd;
                }
                ppt->flag = mesh->base;
                ++nt;
                continue;
            }

            /* compute tgte */
            ppt->flag = mesh->base;
            ++nt;
            if ( !_MMG5_boulec(mesh,k,i,pxp->t) ) {
                ++nf;
                continue;
            }
            dd = pxp->n1[0]*pxp->t[0] + pxp->n1[1]*pxp->t[1] + pxp->n1[2]*pxp->t[2];
            pxp->t[0] -= dd*pxp->n1[0];
            pxp->t[1] -= dd*pxp->n1[1];
            pxp->t[2] -= dd*pxp->n1[2];
            dd = pxp->t[0]*pxp->t[0] + pxp->t[1]*pxp->t[1] + pxp->t[2]*pxp->t[2];
            if ( dd > _MMG5_EPSD2 ) {
                dd = 1.0 / sqrt(dd);
                pxp->t[0] *= dd;
                pxp->t[1] *= dd;
                pxp->t[2] *= dd;
            }
        }
Esempio n. 9
0
File: analys.c Progetto: XL64/mmg
/** check for singularities */
static int _MMG5_singul(MMG5_pMesh mesh) {
    MMG5_pTria     pt;
    MMG5_pPoint    ppt,p1,p2;
    double    ux,uy,uz,vx,vy,vz,dd;
    int       list[_MMG5_LMAX+2],k,nc,ng,nr,ns,nre;
    char      i;

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

        for (i=0; i<3; i++) {
            ppt = &mesh->point[pt->v[i]];
            if ( !MG_VOK(ppt) || MG_SIN(ppt->tag) || ppt->tag & MG_NOM ) continue;
            else if ( MG_EDG(ppt->tag) ) {
                ns = _MMG5_bouler(mesh,k,i,list,&ng,&nr);

                if ( !ns )  continue;
                if ( (ng+nr) > 2 ) {
                    ppt->tag |= MG_CRN + MG_REQ;
                    nre++;
                    nc++;
                }
                else if ( (ng == 1) && (nr == 1) ) {
                    ppt->tag |= MG_REQ;
                    nre++;
                }
                else if ( ng == 1 && !nr ){
                    ppt->tag |= MG_CRN + MG_REQ;
                    nre++;
                    nc++;
                }
                else if ( nr == 1 && !ng ){
                    ppt->tag |= MG_CRN + MG_REQ;
                    nre++;
                    nc++;
                }
                /* check ridge angle */
                else {
                    p1 = &mesh->point[list[1]];
                    p2 = &mesh->point[list[2]];
                    ux = p1->c[0] - ppt->c[0];
                    uy = p1->c[1] - ppt->c[1];
                    uz = p1->c[2] - ppt->c[2];
                    vx = p2->c[0] - ppt->c[0];
                    vy = p2->c[1] - ppt->c[1];
                    vz = p2->c[2] - ppt->c[2];
                    dd = (ux*ux + uy*uy + uz*uz) * (vx*vx + vy*vy + vz*vz);
                    if ( fabs(dd) > _MMG5_EPSD ) {
                        dd = (ux*vx + uy*vy + uz*vz) / sqrt(dd);
                        if ( dd > -mesh->info.dhd ) {
                            ppt->tag |= MG_CRN;
                            nc++;
                        }
                    }
                }
            }
        }
    }

    if ( abs(mesh->info.imprim) > 3 && nre > 0 )
        fprintf(stdout,"     %d corners, %d singular points detected\n",nc,nre);
    return(1);
}