This commit is contained in:
mtarini 2009-09-04 16:49:41 +00:00
parent 5846e9a86d
commit a2e777fd9a
2 changed files with 101 additions and 57 deletions

View File

@ -226,7 +226,7 @@ seeks and removes all doublets (a pair of quads sharing two consecutive edges)
by merging them into a single quad (thus removing one vertex and two tri faces)-
Returns number of removed Doublets
*/
static int RemoveDoublets(MeshType &m)
static int RemoveDoublets(MeshType &m, Pos *p=NULL)
{
int res=0;
for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) {
@ -234,8 +234,9 @@ static int RemoveDoublets(MeshType &m)
for (int k=0; k<3; k++) {
if ( BQ::IsDoublet(*fi,k) ){
res++;
BQ::RemoveDoublet(*fi,k,m);
BQ::RemoveDoublet(*fi,k,m,p);
if (fi->IsD()) break; // break wedge circle, if face disappeard
if (p) return res;
}
}
}
@ -247,7 +248,7 @@ marks (Quality=0) and approx. counts profitable vertex rotations
(vertex rotations which make edge shorter
*/
template <bool perform>
static int MarkVertexRotations(MeshType &m)
static int MarkVertexRotations(MeshType &m, Pos *p=NULL)
{
int res=0;
for (VertexIterator vi = m.vert.begin(); vi!=m.vert.end(); vi++) if (!vi->IsD()) vi->ClearV();
@ -265,8 +266,8 @@ static int MarkVertexRotations(MeshType &m)
res++; MarkVertex(&*fi, k, m); //fi->Q()=0;
}
else {
if (BQ::RotateVertex(*fi, k)) res++; //fi->Q()=0;
//if (res>1) return res; // uncomment for only one rotation
if (BQ::RotateVertex(*fi, k, p)) res++; //fi->Q()=0;
if (p) return res; // uncomment for only one rotation
}
}
}
@ -277,7 +278,7 @@ static int MarkVertexRotations(MeshType &m)
// mark (and count) all edges that are worth rotating
// if perform == true, actually rotate them
template <bool perform>
static int MarkEdgeRotations(MeshType &m)
static int MarkEdgeRotations(MeshType &m, Pos *p=NULL)
{
int count = 0;
@ -290,8 +291,9 @@ static int MarkEdgeRotations(MeshType &m)
if (fi->FFp(k)<= &*fi) continue; // only once per real (non faux) edge, and only for non border ones
int best = BQ::TestEdgeRotation(*fi, k);
if (perform) {
if (best==+1) if (BQ::template RotateEdge< true>(*fi, k)) count++;
if (best==-1) if (BQ::template RotateEdge<false>(*fi, k)) count++;
if (best==+1) if (BQ::template RotateEdge< true>(*fi, k, p)) count++;
if (best==-1) if (BQ::template RotateEdge<false>(*fi, k, p)) count++;
if (p) if (count>0) return count;
}
else {
if (best!=0) { fi->Q()=0; fi->FFp(k)->Q()=0; count++; }
@ -344,15 +346,15 @@ static int MarkSinglets(MeshType &m)
/*
deletes singlets, reutrns number of
*/
static int RemoveSinglets(MeshType &m)
static int RemoveSinglets(MeshType &m, Pos *p=NULL)
{
int res=0;
for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) {
for (int k=0; k<3; k++) {
if ( BQ::IsSinglet(*fi,k) ){
res++;
BQ::RemoveSinglet(*fi,k,m);
return res;
BQ::RemoveSinglet(*fi,k,m, p);
if (p) return res;
break;
}
}

View File

@ -87,7 +87,21 @@ typedef typename MeshType::FaceType* FaceTypeP;
typedef typename MeshType::VertexType VertexType;
typedef typename MeshType::FaceIterator FaceIterator;
typedef typename MeshType::VertexIterator VertexIterator;
typedef typename face::Pos<FaceType> Pos;
class Pos{
FaceType *f;
int e;
public:
enum{ PAIR, AROUND , NOTHING } mode;
FaceType* &F(){return f;}
FaceType* F() const {return f;}
int& E(){return e;}
int E() const {return e;}
VertexType* V() {return f->V(e);}
Pos(){ f=NULL; e=0; mode=AROUND;}
};
static void MarkFaceF(FaceType *f){
f->V(0)->SetS();
@ -103,7 +117,7 @@ static void MarkFaceF(FaceType *f){
template <bool verse>
static bool RotateEdge(FaceType& f, int w0a){
static bool RotateEdge(FaceType& f, int w0a, Pos *affected=NULL){
FaceType *fa = &f;
assert(! fa->IsF(w0a) );
@ -141,6 +155,11 @@ static bool RotateEdge(FaceType& f, int w0a){
if (!CheckFlipEdge(*fa,w0a)) return false;
FlipEdge(*fa,w0a);
if (affected) {
affected->F() = fa;
affected->E() = (FauxIndex(fa)+2)%3;
affected->mode = Pos::PAIR;
}
return true;
}
@ -233,7 +252,7 @@ static bool TestVertexRotation(const FaceType &f, int w0)
}
static bool RotateVertex(FaceType &f, int w0)
static bool RotateVertex(FaceType &f, int w0, Pos *affected=NULL)
{
int guard = 0;
@ -288,6 +307,10 @@ static bool RotateVertex(FaceType &f, int w0)
int tmp = (pf->FFi(pi)+1)%3; pf = pf->FFp(pi); pi = tmp; // flipF flipV
} while (pf != stopA );
if (affected) {
affected->F() = pf;
affected->E()=pi;
}
return true;
}
@ -351,8 +374,6 @@ static void _CollapseDiagHalf(FaceType &f, int faux, MeshType& m)
int faux1 = (faux+1)%3;
int faux2 = (faux+2)%3;
DecreaseValency(f.V2(faux)); // update valency
FaceType* fA = f.FFp( faux1 );
FaceType* fB = f.FFp( faux2 );
@ -364,9 +385,8 @@ static void _CollapseDiagHalf(FaceType &f, int faux, MeshType& m)
if (fA==&f && fB==&f) {
// both non-faux edges are borders: tri-face disappears, just remove the vertex
if (DELETE_VERTICES)
if (GetValency(f.V(faux2))==0)
Allocator<MeshType>::DeleteVertex(m,*(f.V(faux2)));
//if (DELETE_VERTICES)
//if (GetValency(f.V(faux2))==0) Allocator<MeshType>::DeleteVertex(m,*(f.V(faux2)));
} else {
if (fA==&f) {
fB->FFp(iB) = fB; fB->FFi(iB) = iB;
@ -381,6 +401,8 @@ static void _CollapseDiagHalf(FaceType &f, int faux, MeshType& m)
}
}
DecreaseValencyMaybeRemove(f.V(faux2),1,m); // update valency
Allocator<MeshType>::DeleteFace(m,f);
}
@ -403,7 +425,7 @@ static void RemoveDoublet(FaceType &f, int wedge, MeshType& m, Pos* affected=NUL
}
static void RemoveSinglet(FaceType &f, int wedge, MeshType& m, Pos* affected=NULL){
if (affected) affected->F() = NULL; // singlets leave nothing to update behind
if (affected) affected->mode = Pos::NOTHING; // singlets leave nothing to update behind
FaceType *fa, *fb; // these will die
FaceType *fc, *fd; // their former neight
fa = & f;
@ -442,9 +464,9 @@ static void RemoveSinglet(FaceType &f, int wedge, MeshType& m, Pos* affected=NUL
Allocator<MeshType>::DeleteFace( m,*fa );
Allocator<MeshType>::DeleteFace( m,*fb );
DecreaseValency(fa->V(wedge) );
if (DELETE_VERTICES)
if (GetValency(fa->V(wedge))==0) Allocator<MeshType>::DeleteVertex( m,*fa->V(wedge) );
DecreaseValencyMaybeRemove(fa->V(wedge),1,m );
//if (DELETE_VERTICES)
//if (GetValency(fa->V(wedge))==0) Allocator<MeshType>::DeleteVertex( m,*fa->V(wedge) );
}
@ -611,18 +633,21 @@ static bool CollapseCounterDiag(FaceType &f, ScalarType interpol, MeshType& m, P
// rotates around vertex
class Iterator{
private:
typedef typename face::Pos<FaceType> FPos;
Pos start, cur;
bool over;
public:
Iterator(Pos& pos){
if (pos.F()==NULL) {over = true; return; }
start =Pos(pos.F(), pos.E());
if (pos.mode==Pos::NOTHING) {over = true; return; }
start = pos; //FPos(pos.F(), pos.E());
assert(!start.F()->IsD());
if (pos.mode==Pos::AROUND) {
if (start.F()->IsF((start.E()+2)%3))
{
int i = start.F()->FFi( start.E() );
start.F() = start.F()->FFp( start.E() );
start.E() = (i+1)%3;
}
}
cur=start;
over = false;
@ -631,6 +656,12 @@ public:
return over;
}
void operator ++ () {
if (start.mode==Pos::PAIR) {
if (cur.F()!=start.F()) over=true;
int i = (cur.E()+2)%3;
cur.E() = (cur.F()->FFi( i )+1)%3;
cur.F() = cur.F()->FFp( i );
} else {
if (cur.F()->IsF(cur.E())) {
// jump over faux diag
int i = cur.F()->FFi( cur.E() );
@ -642,9 +673,8 @@ public:
if (f==cur.F()) over=true; // border found
cur.E() = (cur.F()->FFi( cur.E() ) +1 )%3;
cur.F() = f;
if (cur.F()==start.F()) over=true;
}
}
Pos GetPos(){
@ -654,9 +684,7 @@ public:
static bool CollapseDiag(FaceType &f, ScalarType interpol, MeshType& m, Pos* affected=NULL){
FaceType* fa = &f;
FaceType* fa = &f; // fa lives
int fauxa = FauxIndex(fa);
//if (IsDoubletOrSinglet(f,fauxa)) { RemoveDoubletOrSinglet(f,fauxa,m, affected); return true;}
@ -674,8 +702,9 @@ static bool CollapseDiag(FaceType &f, ScalarType interpol, MeshType& m, Pos* aff
affected->E() = (fa->FFi(w1)+2)%3;
}
}
FaceType* fb = fa->FFp(fauxa);
assert (fb!=fa);
FaceType* fb = fa->FFp(fauxa); // fb dies
assert (fb!=fa); // otherwise, its a singlet
int fauxb = FauxIndex(fb);
VertexType* va = fa->V(fauxa); // va lives
@ -683,22 +712,26 @@ static bool CollapseDiag(FaceType &f, ScalarType interpol, MeshType& m, Pos* aff
Interpolator::Apply( *(f.V0(fauxa)), *(f.V1(fauxa)), interpol, *va);
// update FV...
bool border = false;
int pi = fauxb;
FaceType* pf = fb; /* pf, pi could be a Pos<FaceType> p(pf, pi) */
int val =0; // number of faces around vb, which dies
// update FV...
// rotate around vb, (same-sense-as-face)-wise
int pi = fauxb;
FaceType* pf = fb; /* pf, pi could be put in a Pos<FaceType> p(pb, fauxb) */
do {
pf->V(pi) = va;
pi=(pi+2)%3;
FaceType *t = pf->FFp(pi);
if (t==pf) { border= true; break; }
if (!pf->IsF(pi)) val++;
pi = pf->FFi(pi);
pf = t;
} while (pf!=fb);
// rotate around va, (counter-sense-as-face)-wise
// of found a border, also rotate around vb, (counter-sense-as-face)-wise
if (border) {
int pi = fauxa;
FaceType* pf = fa; /* pf, pi could be a Pos<FaceType> p(pf, pi) */
@ -707,6 +740,7 @@ static bool CollapseDiag(FaceType &f, ScalarType interpol, MeshType& m, Pos* aff
pf->V(pi) = va;
FaceType *t = pf->FFp(pi);
if (t==pf) break;
if (!pf->IsF(pi)) val++;
pi = pf->FFi(pi);
pf = t;
} while (pf!=fb);
@ -716,9 +750,10 @@ static bool CollapseDiag(FaceType &f, ScalarType interpol, MeshType& m, Pos* aff
_CollapseDiagHalf(*fb, fauxb, m);
_CollapseDiagHalf(*fa, fauxa, m);
SetValency(va, GetValency(vb)+GetValency(va)-2);
SetValency(vb, GetValency(vb)+GetValency(va)-2);
if (DELETE_VERTICES) Allocator<MeshType>::DeleteVertex(m,*vb);
assert(val == GetValency(vb));
SetValency(va, GetValency(va)+val-2);
DecreaseValencyMaybeRemove(vb, val, m);
//if (DELETE_VERTICES) Allocator<MeshType>::DeleteVertex(m,*vb);
return true;
}
@ -784,6 +819,13 @@ static void DecreaseValency(VertexType *v, int dv=1){
#endif
}
static void DecreaseValencyMaybeRemove(VertexType *v, int dv, MeshType &m){
int val = GetValency(v)-dv ;
SetValency( v, val );
if (DELETE_VERTICES)
if (val==0) Allocator<MeshType>::DeleteVertex(m,*v);
}
static void UpdateValencyInFlags(MeshType& m){
for (VertexIterator vi = m.vert.begin(); vi!=m.vert.end(); vi++) if (!vi->IsD()) {
SetValency(&*vi,0);