Added working valency in flags computations (and used to detect singlets/doublets quicker)
This commit is contained in:
parent
6fb6cfbb24
commit
2c3a92242b
|
@ -5,6 +5,7 @@ template <class BQ>
|
||||||
class BitQuadOptimization{
|
class BitQuadOptimization{
|
||||||
|
|
||||||
typedef typename BQ::MeshType MeshType;
|
typedef typename BQ::MeshType MeshType;
|
||||||
|
typedef typename BQ::Pos Pos;
|
||||||
|
|
||||||
typedef typename MeshType::ScalarType ScalarType;
|
typedef typename MeshType::ScalarType ScalarType;
|
||||||
typedef typename MeshType::CoordType CoordType;
|
typedef typename MeshType::CoordType CoordType;
|
||||||
|
@ -82,7 +83,7 @@ static bool MarkSmallestEdge(MeshType &m, bool perform)
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns: 0 if fail. 1 if edge. 2 if diag.
|
// returns: 0 if fail. 1 if edge. 2 if diag.
|
||||||
static int MarkSmallestEdgeOrDiag(MeshType &m, ScalarType edgeMult, bool perform)
|
static int MarkSmallestEdgeOrDiag(MeshType &m, ScalarType edgeMult, bool perform, Pos* affected=NULL)
|
||||||
{
|
{
|
||||||
ScalarType min = std::numeric_limits<ScalarType>::max();
|
ScalarType min = std::numeric_limits<ScalarType>::max();
|
||||||
|
|
||||||
|
@ -123,12 +124,12 @@ static int MarkSmallestEdgeOrDiag(MeshType &m, ScalarType edgeMult, bool perform
|
||||||
if (perform) {
|
if (perform) {
|
||||||
if (fa->IsF(w)) {
|
if (fa->IsF(w)) {
|
||||||
if (counterDiag) {
|
if (counterDiag) {
|
||||||
if (BQ::CollapseCounterDiag(*fa, BQ::PosOnDiag(*fa,true), m )) return 2;
|
if (BQ::CollapseCounterDiag(*fa, BQ::PosOnDiag(*fa,true), m , affected)) return 2;
|
||||||
} else {
|
} else {
|
||||||
if (BQ::CollapseDiag(*fa, BQ::PosOnDiag(*fa,false), m )) return 2;
|
if (BQ::CollapseDiag(*fa, BQ::PosOnDiag(*fa,false), m ,affected)) return 2;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (BQ::CollapseEdge(*fa,w,m)) return 1;
|
if (BQ::CollapseEdge(*fa,w,m, affected)) return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fa->Q()=0.0;
|
fa->Q()=0.0;
|
||||||
|
|
|
@ -66,6 +66,7 @@ public:
|
||||||
static void Apply( const VertexType &a, const VertexType &b, ScalarType t, VertexType &res){
|
static void Apply( const VertexType &a, const VertexType &b, ScalarType t, VertexType &res){
|
||||||
/*assert (&a != &b);*/
|
/*assert (&a != &b);*/
|
||||||
res.P() = a.P()*(1-t) + b.P()*(t);
|
res.P() = a.P()*(1-t) + b.P()*(t);
|
||||||
|
if (a.IsB()||b.IsB()) res.SetB();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -271,8 +272,6 @@ static bool RotateVertex(FaceType &f, int w0)
|
||||||
FlipDiag(*lastF);
|
FlipDiag(*lastF);
|
||||||
}
|
}
|
||||||
MarkFaceF(pf);
|
MarkFaceF(pf);
|
||||||
|
|
||||||
|
|
||||||
} while (pf != stopA && pf!= stopB);
|
} while (pf != stopA && pf!= stopB);
|
||||||
|
|
||||||
// last pass: rotate arund vertex again, changing faux status
|
// last pass: rotate arund vertex again, changing faux status
|
||||||
|
@ -280,9 +279,9 @@ static bool RotateVertex(FaceType &f, int w0)
|
||||||
do {
|
do {
|
||||||
int j = pi;
|
int j = pi;
|
||||||
if (pf->IsF(j))
|
if (pf->IsF(j))
|
||||||
{ pf->ClearF(j); IncreaseValency(pf->V(j)); }
|
{ pf->ClearF(j); IncreaseValency(pf->V1(j)); }
|
||||||
else
|
else
|
||||||
{ pf->SetF(j); DecreaseValency(pf->V(j)); }
|
{ pf->SetF(j); DecreaseValency(pf->V1(j)); }
|
||||||
|
|
||||||
j = (j+2)%3;
|
j = (j+2)%3;
|
||||||
if (pf->IsF(j)) pf->ClearF(j); else pf->SetF(j);
|
if (pf->IsF(j)) pf->ClearF(j); else pf->SetF(j);
|
||||||
|
@ -386,7 +385,7 @@ static void _CollapseDiagHalf(FaceType &f, int faux, MeshType& m)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RemoveDoublet(FaceType &f, int wedge, MeshType& m){
|
static void RemoveDoublet(FaceType &f, int wedge, MeshType& m, Pos* affected=NULL){
|
||||||
if (f.IsF((wedge+1)%3) ) {
|
if (f.IsF((wedge+1)%3) ) {
|
||||||
VertexType *v = f.V(wedge);
|
VertexType *v = f.V(wedge);
|
||||||
FlipDiag(f);
|
FlipDiag(f);
|
||||||
|
@ -399,11 +398,12 @@ static void RemoveDoublet(FaceType &f, int wedge, MeshType& m){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ScalarType k=(f.IsF(wedge))?1:0;
|
ScalarType k=(f.IsF(wedge))?1:0;
|
||||||
CollapseDiag(f, k, m);
|
CollapseDiag(f, k, m, affected);
|
||||||
VertexType *v = f.V(wedge);
|
VertexType *v = f.V(wedge);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RemoveSinglet(FaceType &f, int wedge, MeshType& m){
|
static void RemoveSinglet(FaceType &f, int wedge, MeshType& m, Pos* affected=NULL){
|
||||||
|
if (affected) affected->F() = NULL; // 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;
|
||||||
|
@ -484,7 +484,7 @@ static int CountBitPolygonInternalValency(const FaceType& f, int wedge){
|
||||||
|
|
||||||
// given a face and a wedge, returns if it host a doubet
|
// given a face and a wedge, returns if it host a doubet
|
||||||
// assumes tri and quad only. uses FF topology only.
|
// assumes tri and quad only. uses FF topology only.
|
||||||
static bool IsDoublet(const FaceType& f, int wedge){
|
static bool IsDoubletFF(const FaceType& f, int wedge){
|
||||||
const FaceType* pf = &f;
|
const FaceType* pf = &f;
|
||||||
int pi = wedge;
|
int pi = wedge;
|
||||||
int res = 0, guard=0;
|
int res = 0, guard=0;
|
||||||
|
@ -503,13 +503,24 @@ static bool IsDoublet(const FaceType& f, int wedge){
|
||||||
}
|
}
|
||||||
|
|
||||||
// version that uses vertex valency
|
// version that uses vertex valency
|
||||||
static bool IsDoubletVal(const FaceType& f, int wedge){
|
static bool IsDoublet(const FaceType& f, int wedge){
|
||||||
return (GetValency( f.V(wedge)) == 2) && (!f.V(wedge)->IsB() ) ;
|
return (GetValency( f.V(wedge)) == 2) && (!f.V(wedge)->IsB() ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsDoubletOrSinglet(const FaceType& f, int wedge){
|
||||||
|
return (GetValency( f.V(wedge)) <= 2) && (!f.V(wedge)->IsB() ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool RemoveDoubletOrSinglet(FaceType& f, int wedge, MeshType& m, Pos* affected=NULL){
|
||||||
|
if (GetValency( f.V(wedge)) == 2) { RemoveDoublet(f,wedge,m,affected) ; return true; }
|
||||||
|
assert (GetValency( f.V(wedge)) == 1) ;
|
||||||
|
RemoveSinglet(f,wedge,m,affected) ;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// given a face and a wedge, returns if it host a singlets
|
// given a face and a wedge, returns if it host a singlets
|
||||||
// assumes tri and quad only. uses FF topology only.
|
// assumes tri and quad only. uses FF topology only.
|
||||||
static bool IsSinglet(const FaceType& f, int wedge){
|
static bool IsSingletFF(const FaceType& f, int wedge){
|
||||||
const FaceType* pf = &f;
|
const FaceType* pf = &f;
|
||||||
int pi = wedge;
|
int pi = wedge;
|
||||||
int res = 0, guard=0;
|
int res = 0, guard=0;
|
||||||
|
@ -528,7 +539,7 @@ static bool IsSinglet(const FaceType& f, int wedge){
|
||||||
}
|
}
|
||||||
|
|
||||||
// version that uses vertex valency
|
// version that uses vertex valency
|
||||||
static bool IsSingletVal(const FaceType& f, int wedge){
|
static bool IsSinglet(const FaceType& f, int wedge){
|
||||||
return (GetValency( f.V(wedge) ) == 1) && (!f.V(wedge)->IsB() ) ;
|
return (GetValency( f.V(wedge) ) == 1) && (!f.V(wedge)->IsB() ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,20 +563,21 @@ static bool CollapseEdgeDirect(FaceType &f, int w0, MeshType& m){
|
||||||
assert( f0->V1(w0) == v1 );
|
assert( f0->V1(w0) == v1 );
|
||||||
assert( f0->IsF(w0) );
|
assert( f0->IsF(w0) );
|
||||||
|
|
||||||
CollapseDiag(*f0,PosOnDiag(*f0,false), m);
|
return CollapseDiag(*f0,PosOnDiag(*f0,false), m);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// collapses an edge. Optional output pos can be iterated around to find affected faces
|
// collapses an edge. Optional output pos can be iterated around to find affected faces
|
||||||
static bool CollapseEdge(FaceType &f, int w0, MeshType& m, Pos *affected =NULL){
|
static bool CollapseEdge(FaceType &f, int w0, MeshType& m, Pos *affected=NULL){
|
||||||
FaceTypeP f0 = &f;
|
FaceTypeP f0 = &f;
|
||||||
assert(!f0->IsF(w0)); // don't use this method to collapse diag.
|
assert(!f0->IsF(w0)); // don't use this method to collapse diag.
|
||||||
|
|
||||||
|
if (IsDoubletOrSinglet(f,w0)) { RemoveDoubletOrSinglet(f,w0,m, affected); return true;}
|
||||||
|
if (IsDoubletOrSinglet(f,(w0+1)%3)) { RemoveDoubletOrSinglet(f,(w0+1)%3,m, affected); return true;}
|
||||||
|
|
||||||
if (affected) {
|
if (affected) {
|
||||||
VertexType *p = f0->V(w0);
|
|
||||||
int w1 = 3-w0-FauxIndex(f0); // the edge whihc is not the collapsed one nor the faux
|
int w1 = 3-w0-FauxIndex(f0); // the edge whihc is not the collapsed one nor the faux
|
||||||
affected->F() = f0->FFp(w1);
|
affected->F() = f0->FFp(w1);
|
||||||
affected->E() = (f0->FFi(w1)+4+w1-FauxIndex(f0))%3;
|
affected->E() = (f0->FFi(w1)+2+w1-FauxIndex(f0))%3;
|
||||||
}
|
}
|
||||||
|
|
||||||
FaceTypeP f1 = f0->FFp(w0);
|
FaceTypeP f1 = f0->FFp(w0);
|
||||||
|
@ -603,15 +615,16 @@ private:
|
||||||
bool over;
|
bool over;
|
||||||
public:
|
public:
|
||||||
Iterator(Pos& pos){
|
Iterator(Pos& pos){
|
||||||
|
if (pos.F()==NULL) {over = true; return; }
|
||||||
start =Pos(pos.F(), pos.E());
|
start =Pos(pos.F(), pos.E());
|
||||||
|
assert(!start.F()->IsD());
|
||||||
while((start.F()->IsD())||(start.F()->IsF((start.E()+1)%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+2)%3;
|
start.E() = (i+1)%3;
|
||||||
}
|
}
|
||||||
cur=start;
|
cur=start;
|
||||||
over = false;
|
over = false;
|
||||||
}
|
}
|
||||||
bool End() const {
|
bool End() const {
|
||||||
|
@ -622,12 +635,12 @@ public:
|
||||||
// jump over faux diag
|
// jump over faux diag
|
||||||
int i = cur.F()->FFi( cur.E() );
|
int i = cur.F()->FFi( cur.E() );
|
||||||
cur.F() = cur.F()->FFp( cur.E() );
|
cur.F() = cur.F()->FFp( cur.E() );
|
||||||
cur.E() = (i+2)%3;
|
cur.E() = (i+1)%3;
|
||||||
}
|
}
|
||||||
// jump over real edge
|
// jump over real edge
|
||||||
FaceType *f =cur.F()->FFp( cur.E() );
|
FaceType *f =cur.F()->FFp( cur.E() );
|
||||||
if (f==cur.F()) over=true; // border found
|
if (f==cur.F()) over=true; // border found
|
||||||
cur.E() = (cur.F()->FFi( cur.E() ) +2 )%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;
|
||||||
|
@ -639,14 +652,27 @@ 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;
|
||||||
|
|
||||||
|
|
||||||
int fauxa = FauxIndex(fa);
|
int fauxa = FauxIndex(fa);
|
||||||
|
|
||||||
|
//if (IsDoubletOrSinglet(f,fauxa)) { RemoveDoubletOrSinglet(f,fauxa,m, affected); return true;}
|
||||||
|
// if (IsDoubletOrSinglet(f,(fauxa+2)%3)) { RemoveDoubletOrSinglet(f,(fauxa+2)%3,m, affected); return true;}
|
||||||
|
if (IsDoubletOrSinglet(f,(fauxa+2)%3)) return false;
|
||||||
|
if (IsDoubletOrSinglet(*(f.FFp(fauxa)),(f.FFi(fauxa)+2)%3)) return false;
|
||||||
|
|
||||||
if (affected) {
|
if (affected) {
|
||||||
int w1 = (fauxa+1)%3; // any edge but not the faux
|
int w1 = (fauxa+2)%3; // any edge but not the faux
|
||||||
affected->F() = fa->FFp(w1);
|
affected->F() = fa->FFp(w1);
|
||||||
affected->E() = fa->FFi(w1);
|
affected->E() = fa->FFi(w1);
|
||||||
|
if (affected->F() == fa){
|
||||||
|
int w1 = (fauxa+1)%3; // any edge but not the faux
|
||||||
|
affected->F() = fa->FFp(w1);
|
||||||
|
affected->E() = (fa->FFi(w1)+2)%3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
FaceType* fb = fa->FFp(fauxa);
|
FaceType* fb = fa->FFp(fauxa);
|
||||||
assert (fb!=fa);
|
assert (fb!=fa);
|
||||||
|
@ -732,9 +758,9 @@ typedef enum { VALENCY_FLAGS = 24 } ___; // this bit and the 4 successive one ar
|
||||||
|
|
||||||
static void SetValency(VertexType *v, int n){
|
static void SetValency(VertexType *v, int n){
|
||||||
//v->Q() = n;
|
//v->Q() = n;
|
||||||
/* assert(n>=0 && n<=31);
|
assert(n>=0 && n<=31);
|
||||||
v->Flags()&= ~(31<<VALENCY_FLAGS);
|
v->Flags()&= ~(31<<VALENCY_FLAGS);
|
||||||
v->Flags()|= n<<VALENCY_FLAGS;*/
|
v->Flags()|= n<<VALENCY_FLAGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int GetValency(const VertexType *v){
|
static int GetValency(const VertexType *v){
|
||||||
|
@ -743,19 +769,19 @@ static int GetValency(const VertexType *v){
|
||||||
}
|
}
|
||||||
|
|
||||||
static void IncreaseValency(VertexType *v, int dv=1){
|
static void IncreaseValency(VertexType *v, int dv=1){
|
||||||
//#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
// v->Flags() += dv<<VALENCY_FLAGS;
|
v->Flags() += dv<<VALENCY_FLAGS;
|
||||||
//#else
|
#else
|
||||||
// SetValency( v, GetValency(v)+dv );
|
SetValency( v, GetValency(v)+dv );
|
||||||
//#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DecreaseValency(VertexType *v, int dv=1){
|
static void DecreaseValency(VertexType *v, int dv=1){
|
||||||
//#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
// v->Flags() -= dv<<VALENCY_FLAGS;
|
v->Flags() -= dv<<VALENCY_FLAGS;
|
||||||
//#else
|
#else
|
||||||
// SetValency( v, GetValency(v)-dv );
|
SetValency( v, GetValency(v)-dv );
|
||||||
//#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UpdateValencyInFlags(MeshType& m){
|
static void UpdateValencyInFlags(MeshType& m){
|
||||||
|
@ -781,10 +807,11 @@ static void UpdateValencyInQuality(MeshType& m){
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool HasConsistentValencyFlag(MeshType &m) {
|
static bool HasConsistentValencyFlag(MeshType &m) {
|
||||||
//UpdateValencyInFlags(m);
|
//(m);
|
||||||
UpdateValencyInQuality(m);
|
UpdateValencyInQuality(m);
|
||||||
for (VertexIterator vi = m.vert.begin(); vi!=m.vert.end(); vi++) if (!vi->IsD()) {
|
for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) {
|
||||||
if (GetValency(&*vi)!=vi->Q()) return false;
|
for (int k=0; k<3; k++)
|
||||||
|
if (GetValency(fi->V(k))!=fi->V(k)->Q()) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue