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)- by merging them into a single quad (thus removing one vertex and two tri faces)-
Returns number of removed Doublets Returns number of removed Doublets
*/ */
static int RemoveDoublets(MeshType &m) static int RemoveDoublets(MeshType &m, Pos *p=NULL)
{ {
int res=0; int res=0;
for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) { 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++) { for (int k=0; k<3; k++) {
if ( BQ::IsDoublet(*fi,k) ){ if ( BQ::IsDoublet(*fi,k) ){
res++; res++;
BQ::RemoveDoublet(*fi,k,m); BQ::RemoveDoublet(*fi,k,m,p);
if (fi->IsD()) break; // break wedge circle, if face disappeard 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 (vertex rotations which make edge shorter
*/ */
template <bool perform> template <bool perform>
static int MarkVertexRotations(MeshType &m) static int MarkVertexRotations(MeshType &m, Pos *p=NULL)
{ {
int res=0; int res=0;
for (VertexIterator vi = m.vert.begin(); vi!=m.vert.end(); vi++) if (!vi->IsD()) vi->ClearV(); 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; res++; MarkVertex(&*fi, k, m); //fi->Q()=0;
} }
else { else {
if (BQ::RotateVertex(*fi, k)) res++; //fi->Q()=0; if (BQ::RotateVertex(*fi, k, p)) res++; //fi->Q()=0;
//if (res>1) return res; // uncomment for only one rotation 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 // mark (and count) all edges that are worth rotating
// if perform == true, actually rotate them // if perform == true, actually rotate them
template <bool perform> template <bool perform>
static int MarkEdgeRotations(MeshType &m) static int MarkEdgeRotations(MeshType &m, Pos *p=NULL)
{ {
int count = 0; 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 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); int best = BQ::TestEdgeRotation(*fi, k);
if (perform) { if (perform) {
if (best==+1) if (BQ::template RotateEdge< true>(*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)) count++; if (best==-1) if (BQ::template RotateEdge<false>(*fi, k, p)) count++;
if (p) if (count>0) return count;
} }
else { else {
if (best!=0) { fi->Q()=0; fi->FFp(k)->Q()=0; count++; } 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 deletes singlets, reutrns number of
*/ */
static int RemoveSinglets(MeshType &m) static int RemoveSinglets(MeshType &m, Pos *p=NULL)
{ {
int res=0; int res=0;
for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) { for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) {
for (int k=0; k<3; k++) { for (int k=0; k<3; k++) {
if ( BQ::IsSinglet(*fi,k) ){ if ( BQ::IsSinglet(*fi,k) ){
res++; res++;
BQ::RemoveSinglet(*fi,k,m); BQ::RemoveSinglet(*fi,k,m, p);
return res; if (p) return res;
break; break;
} }
} }

View File

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