Ejemplo n.º 1
0
/**
 * \param mesh pointer toward the mesh structure.
 * \param list pointer toward the ball of the point to collapse.
 * \return 1.
 *
 * Collapse edge \f$list[0]%3\f$ in tet \f$list[0]/3\f$ (\f$ ip->i1\f$ ) for a
 * ball of the collapsed point of size 3: the collapsed point is removed.
 *
 */
int colver3(MMG5_pMesh mesh,int* list) {
  MMG5_pTria   pt,pt1,pt2;
  int          *adja,iel,jel,kel,mel,ip;
  char         i,i1,j,j1,j2,k,m;

  /* update of new point for triangle list[0] */
  iel = list[0] / 3;
  i   = list[0] % 3;
  i1  = _MMG5_inxt2[i];
  pt  = &mesh->tria[iel];
  ip  = pt->v[i];

  jel = list[1] / 3;
  j   = list[1] % 3;
  j1  = _MMG5_inxt2[j];
  j2  = _MMG5_iprv2[j];
  pt1 = &mesh->tria[jel];

  kel = list[2] / 3;
  k   = list[2] % 3;
  pt2 = &mesh->tria[kel];

  /* update info */
  pt1->v[j]     = pt->v[i1];
  pt1->tag[j1] |= pt2->tag[k];
  pt1->edg[j1]  = MG_MAX(pt1->edg[j1],pt2->edg[k]);
  pt1->tag[j2] |= pt->tag[i];
  pt1->edg[j2]  = MG_MAX(pt1->edg[j2],pt->edg[i]);
  pt1->base     = mesh->base;

  /* update neighbours of new triangle */
  adja = &mesh->adja[3*(jel-1)+1];
  adja[j1] = mesh->adja[3*(kel-1)+1+k];
  adja[j2] = mesh->adja[3*(iel-1)+1+i];

  mel  = adja[j2] / 3;
  if ( mel ) {
    m    = adja[j2] % 3;
    pt   = &mesh->tria[mel];
    pt->tag[m]  = pt1->tag[j2];
    pt->edg[m]  = pt1->edg[j2];
    mesh->adja[3*(mel-1)+1+m] = 3*jel + j2;
  }

  mel = adja[j1] / 3;
  if ( mel ) {
    m    = adja[j1] % 3;
    pt   = &mesh->tria[mel];
    pt->tag[m]  = pt1->tag[j1];
    pt->edg[m]  = pt1->edg[j1];
    mesh->adja[3*(mel-1)+1+m] = 3*jel + j1;
  }

  /* remove vertex + elements */
  _MMG5_delPt(mesh,ip);
  _MMG5_delElt(mesh,iel);
  _MMG5_delElt(mesh,kel);

  return(1);
}
Ejemplo n.º 2
0
/**
 * \param mesh pointer toward the mesh structure.
 * \param np number of vertices.
 * \param nt number of triangles.
 * \param na number of edges.
 * \return 0 if failed, 1 otherwise.
 *
 * Set the number of vertices, triangles and edges of the
 * mesh and allocate the associated tables. If call twice, reset the
 * whole mesh to realloc it at the new size
 *
 */
int MMGS_Set_meshSize(MMG5_pMesh mesh, int np, int nt, int na) {
  int k;

  if ( ( (mesh->info.imprim > 5) || mesh->info.ddebug ) &&
       ( mesh->point || mesh->tria || mesh->edge) )
    fprintf(stdout,"  ## Warning: new mesh\n");

  mesh->np  = np;
  mesh->nt  = nt;
  mesh->na  = na;
  mesh->npi = mesh->np;
  mesh->nti = mesh->nt;
  mesh->nai = mesh->na;

  if ( mesh->point )
    _MMG5_DEL_MEM(mesh,mesh->point,(mesh->npmax+1)*sizeof(MMG5_Point));
  if ( mesh->tria )
    _MMG5_DEL_MEM(mesh,mesh->tria,(mesh->nt+1)*sizeof(MMG5_Tria));
  if ( mesh->edge )
    _MMG5_DEL_MEM(mesh,mesh->edge,(mesh->na+1)*sizeof(MMG5_Edge));

  /*tester si -m defini : renvoie 0 si pas ok et met la taille min dans info.mem */
  if( mesh->info.mem > 0) {
    if ( mesh->npmax < mesh->np || mesh->ntmax < mesh->nt) {
      _MMGS_memOption(mesh);
      //     printf("pas de pbs ? %d %d %d %d %d %d -- %d\n",mesh->npmax,mesh->np,
      //     mesh->ntmax,mesh->nt,mesh->nemax,mesh->ne,mesh->info.mem);
      if ( mesh->npmax < mesh->np || mesh->ntmax < mesh->nt) {
        fprintf(stdout,"not enough memory: np : %d %d nt : %d %d \n"
                ,mesh->npmax,mesh->np, mesh->ntmax,mesh->nt);
        return(0);
      }
    } else if(mesh->info.mem < 39) {
      printf("not enough memory  %d\n",mesh->info.mem);
      return(0);
    }
  } else {
    mesh->npmax = MG_MAX(1.5*mesh->np,_MMG5_NPMAX);
    mesh->ntmax = MG_MAX(1.5*mesh->nt,_MMG5_NTMAX);

  }
  _MMG5_ADD_MEM(mesh,(mesh->npmax+1)*sizeof(MMG5_Point),"initial vertices",
                printf("  Exit program.\n");
                exit(EXIT_FAILURE));
  _MMG5_SAFE_CALLOC(mesh->point,mesh->npmax+1,MMG5_Point);

  _MMG5_ADD_MEM(mesh,(mesh->ntmax+1)*sizeof(MMG5_Tria),"initial triangles",return(0));
  _MMG5_SAFE_CALLOC(mesh->tria,mesh->ntmax+1,MMG5_Tria);


  mesh->namax = mesh->na;
  if ( mesh->na ) {
    _MMG5_ADD_MEM(mesh,(mesh->na+1)*sizeof(MMG5_Edge),"initial edges",return(0));
    _MMG5_SAFE_CALLOC(mesh->edge,(mesh->na+1),MMG5_Edge);
  }
Ejemplo n.º 3
0
Archivo: tools.c Proyecto: 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);
}
Ejemplo n.º 4
0
/* 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);
}
Ejemplo n.º 5
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);
}
Ejemplo 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);
}
Ejemplo n.º 7
0
/* collapse edge i of k, i1->i2 */
int colver(MMG5_pMesh mesh,int *list,int ilist) {
  MMG5_pTria    pt,pt1,pt2;
  int     *adja,k,iel,jel,kel,ip1,ip2;
  char     i,i1,i2,j,jj,open;

  iel = list[0] / 3;
  i1  = list[0] % 3;
  i   = _MMG5_iprv2[i1];
  i2  = _MMG5_inxt2[i1];
  pt  = &mesh->tria[iel];
  ip1 = pt->v[i1];
  ip2 = pt->v[i2];

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

  /* update vertex ip1 -> ip2 */
  for (k=1; k<ilist-1+open; k++) {
    jel = list[k] / 3;
    jj  = list[k] % 3;
    pt1 = &mesh->tria[jel];
    pt1->v[jj] = ip2;
    pt1->base  = mesh->base;
  }

  /* update adjacent with 1st elt */
  jel = list[1] / 3;
  jj  = list[1] % 3;
  j   = _MMG5_iprv2[jj];
  pt1 = &mesh->tria[jel];
  pt1->tag[j] = MG_MAX(pt->tag[i1],pt1->tag[j]);
  pt1->edg[j] = MG_MAX(pt->edg[i1],pt1->edg[j]);
  if ( adja[i1] ) {
    kel = adja[i1] / 3;
    k   = adja[i1] % 3;
    mesh->adja[3*(kel-1)+1+k] = 3*jel + j;
    mesh->adja[3*(jel-1)+1+j] = 3*kel + k;
    pt2 = &mesh->tria[kel];
    pt2->tag[k] = MG_MAX(pt1->tag[j],pt2->tag[k]);
    pt2->edg[k] = MG_MAX(pt1->edg[j],pt2->edg[k]);
  }
  else
    mesh->adja[3*(jel-1)+1+j] = 0;

  /* adjacent with last elt */
  if ( !open ) {
    iel = list[ilist-1] / 3;
    i1  = list[ilist-1] % 3;
    pt  = &mesh->tria[iel];

    jel = list[ilist-2] / 3;
    jj  = list[ilist-2] % 3;
    j   = _MMG5_inxt2[jj];
    pt1 = &mesh->tria[jel];
    pt1->tag[j] = MG_MAX(pt->tag[i1],pt1->tag[j]);
    pt1->edg[j] = MG_MAX(pt->edg[i1],pt1->edg[j]);
    adja = &mesh->adja[3*(iel-1)+1];
    if ( adja[i1] ) {
      kel = adja[i1] / 3;
      k   = adja[i1] % 3;
      mesh->adja[3*(kel-1)+1+k] = 3*jel + j;
      mesh->adja[3*(jel-1)+1+j] = 3*kel + k;
      pt2 = &mesh->tria[kel];
      pt2->tag[k] = MG_MAX(pt1->tag[j],pt2->tag[k]);
      pt2->edg[k] = MG_MAX(pt1->edg[j],pt2->edg[k]);
    }
    else
      mesh->adja[3*(jel-1)+1+j] = 0;
  }

  _MMG5_delPt(mesh,ip1);
  _MMG5_delElt(mesh,list[0] / 3);
  if ( !open )  _MMG5_delElt(mesh,list[ilist-1] / 3);

  return(1);
}
Ejemplo n.º 8
0
Archivo: analys.c Proyecto: 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;
            }
        }