/* attempt to collapse small edges */ static int colelt(pMesh mesh,pSol met,char typchk) { pTria pt; pPoint p1,p2; double ll,ux,uy,uz; int ier,list[LMAX+2],ilist,k,nc; char i,i1,i2; nc = 0; for (k=1; k<=mesh->nt; k++) { pt = &mesh->tria[k]; if ( !MS_EOK(pt) || pt->ref < 0 ) continue; /* check edge length */ pt->flag = 0; ier = 0; for (i=0; i<3; i++) { if ( MS_SIN(pt->tag[i]) ) continue; i1 = inxt[i]; i2 = iprv[i]; p1 = &mesh->point[pt->v[i1]]; p2 = &mesh->point[pt->v[i2]]; if ( p1->tag & MS_NOM || p2->tag & MS_NOM ) continue; else if ( MS_SIN(p1->tag) ) continue; else if ( p1->tag > p2->tag || p1->tag > pt->tag[i] ) continue; /* check length */ if ( typchk == 1 ) { ux = p2->c[0] - p1->c[0]; uy = p2->c[1] - p1->c[1]; uz = p2->c[2] - p1->c[2]; ll = ux*ux + uy*uy + uz*uz; if ( ll > info.hmin*info.hmin ) continue; } else { ll = lenedg(mesh,met,pt->v[i1],pt->v[i2],0); if ( ll > LSHRT ) continue; } /* check if geometry preserved */ ilist = chkcol(mesh,met,k,i,list,typchk); if ( ilist > 3 ) { nc += colver(mesh,list,ilist); break; } else if ( ilist == 3 ) { nc += colver3(mesh,list); break; } else if ( ilist == 2 ) { nc += colver2(mesh,list); break; } } } if ( nc > 0 && (abs(info.imprim) > 5 || info.ddebug) ) fprintf(stdout," %8d vertices removed\n",nc); return(nc); }
/* analyze triangles and split or collapse to match gradation */ static int adpcol(pMesh mesh,pSol met) { pTria pt; pPoint p1,p2; double len; int k,list[LMAX+2],ilist,nc; char i,i1,i2; nc = 0; for (k=1; k<=mesh->nt; k++) { pt = &mesh->tria[k]; if ( !MS_EOK(pt) || pt->ref < 0 ) continue; /* check edge length */ pt->flag = 0; for (i=0; i<3; i++) { if ( MS_SIN(pt->tag[i]) ) continue; /* check length */ i1 = inxt[i]; i2 = iprv[i]; p1 = &mesh->point[pt->v[i1]]; p2 = &mesh->point[pt->v[i2]]; if ( p1->tag & MS_NOM || p2->tag & MS_NOM ) continue; len = lenedg(mesh,met,pt->v[i1],pt->v[i2],0); if ( len > LOPTS ) continue; p1 = &mesh->point[pt->v[i1]]; p2 = &mesh->point[pt->v[i2]]; if ( MS_SIN(p1->tag) ) continue; else if ( p1->tag > p2->tag || p1->tag > pt->tag[i] ) continue; /* check if geometry preserved */ ilist = chkcol(mesh,met,k,i,list,2); if ( ilist > 3 ) { nc += colver(mesh,list,ilist); break; } else if ( ilist == 3 ) { nc += colver3(mesh,list); break; } else if ( ilist == 2 ) { nc += colver2(mesh,list); break; } } } return(nc); }
/* 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); }