Example #1
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;
Example #2
0
/* check if geometry preserved by collapsing edge i */
int chkcol(MMG5_pMesh mesh,MMG5_pSol met,int k,char i,int *list,char typchk) {
  MMG5_pTria     pt,pt0,pt1,pt2;
  MMG5_pPoint    p1,p2;
  double         len,lon,ps,cosnold,cosnnew,kal,n0old[3],n1old[3],n00old[3];
  double         n0new[3],n1new[3],n00new[3];
  int            *adja,jel,kel,ip1,ip2,l,ll,ilist;
  char           i1,i2,j,jj,j2,lj,open,voy;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return(ilist);
}