Added a flag to choose whether to use Length based criteria or Quality based ones.

This commit is contained in:
mtarini 2009-10-14 14:35:25 +00:00
parent 7c78d81cdc
commit 2f1c77c69a
1 changed files with 78 additions and 12 deletions

View File

@ -50,10 +50,14 @@
*/ */
// this must become a parameter in the corresponding class // these should become a parameter in the corresponding class
#define DELETE_VERTICES 0 #define DELETE_VERTICES 1
// let's not remove them after all... // Reason not to delete vertices:
// since TwoManyfold is weak, the vertex could still be used elsewhere... // if not vertex TwoManyfold, the vertex could still be used elsewhere...
// if one, use length to determine if rotations are profitable
// if zero, maximize conformal quality
#define LENGTH_CRITERION 1
namespace vcg{namespace tri{ namespace vcg{namespace tri{
@ -231,6 +235,59 @@ static ScalarType EdgeLenghtVariationIfVertexRotated(const FaceType &f, int w0)
return (after-before); return (after-before);
} }
// given a vertex (i.e. a face and a wedge),
// this function tells us how the totale edge lenght around a vertex would change
// if that vertex is rotated
static ScalarType QuadQualityVariationIfVertexRotated(const FaceType &f, int w0)
{
assert(!f.IsD());
ScalarType
before=0, // sum of quad quality around v
after=0; // same after the collapse
int guard = 0;
// rotate arond vertex
const FaceType* pf = &f;
int pi = w0;
int nb = 0; // vertex valency
int na = 0;
vector<const VertexType *> s; // 1 star around v
do {
// ScalarType triEdge = (pf->P0(pi) - pf->P1(pi) ).Norm();
if (!pf->IsF(pi)) {
if ( pf->IsF((pi+1)%3)) {
s.push_back(pf->cFFp((pi+1)%3)->V2( pf->cFFi((pi+1)%3) ));
} else {
s.push_back( pf->V2(pi) );
}
s.push_back( pf->V1(pi) );
}
const FaceType *t = pf;
t = pf->FFp( pi );
if (pf == t ) return std::numeric_limits<ScalarType>::max(); // it's a mesh border! flee!
pi = pf->cFFi( pi );
pi = (pi+1)%3; // FaceType::Next( pf->FFi( pi ) );
pf = t;
assert(guard++<100);
} while (pf != &f);
assert(s.size()%2==0);
int N = s.size();
for (int i=0; i<N; i+=2) {
int h = (i+N-1)%N;
int j = (i +1)%N;
int k = (i +2)%N;
before+= quadQuality( s[i]->P(),s[j]->P(),s[k]->P(),f.P(w0) );
after+=quadQuality( s[h]->P(),s[i]->P(),s[j]->P(),f.P(w0) );
}
assert (na == nb);
return (after-before);
}
/* /*
const FaceType* pf = &f; const FaceType* pf = &f;
int pi = wedge; int pi = wedge;
@ -254,8 +311,14 @@ static ScalarType EdgeLenghtVariationIfVertexRotated(const FaceType &f, int w0)
static bool TestVertexRotation(const FaceType &f, int w0) static bool TestVertexRotation(const FaceType &f, int w0)
{ {
assert(!f.IsD()); assert(!f.IsD());
// rotate quad IFF this way edges become shorter:
#if (LENGTH_CRITERION)
// rotate vertex IFF this way edges become shorter:
return EdgeLenghtVariationIfVertexRotated(f,w0)<0; return EdgeLenghtVariationIfVertexRotated(f,w0)<0;
#else
// rotate vertex IFF overall Quality increase
#endif
return QuadQualityVariationIfVertexRotated(f,w0)<0;
} }
@ -823,14 +886,14 @@ 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<=255);
v->Flags()&= ~(31<<VALENCY_FLAGS); v->Flags()&= ~(255<<VALENCY_FLAGS);
v->Flags()|= n<<VALENCY_FLAGS; v->Flags()|= n<<VALENCY_FLAGS;
} }
static int GetValency(const VertexType *v){ static int GetValency(const VertexType *v){
//return (int)(v->cQ()); //return (int)(v->cQ());
return ( v->Flags() >> (VALENCY_FLAGS) ) & 31; return ( v->Flags() >> (VALENCY_FLAGS) ) & 255;
} }
static void IncreaseValency(VertexType *v, int dv=1){ static void IncreaseValency(VertexType *v, int dv=1){
@ -956,15 +1019,17 @@ static int TestEdgeRotation(const FaceType &f, int w0, ScalarType *gain=NULL)
v5 = fb->cFFp(w1)->V2( fb->cFFi(w1) )->P(); v5 = fb->cFFp(w1)->V2( fb->cFFi(w1) )->P();
} }
/*
// max overall quality criterion: #if (!LENGTH_CRITERION)
// max overall CONFORMAL quality criterion:
q0 = quadQuality(v0,v1,v2,v3) + quadQuality(v3,v4,v5,v0); // keep as is? q0 = quadQuality(v0,v1,v2,v3) + quadQuality(v3,v4,v5,v0); // keep as is?
q1 = quadQuality(v1,v2,v3,v4) + quadQuality(v4,v5,v0,v1); // rotate CW? q1 = quadQuality(v1,v2,v3,v4) + quadQuality(v4,v5,v0,v1); // rotate CW?
q2 = quadQuality(v5,v0,v1,v2) + quadQuality(v2,v3,v4,v5); // rotate CCW? q2 = quadQuality(v5,v0,v1,v2) + quadQuality(v2,v3,v4,v5); // rotate CCW?
if (q0>=q1 && q0>=q2) return 0; if (q0>=q1 && q0>=q2) return 0;
if (q1>=q2) return 1;*/ if (q1>=q2) return 1;
#else
// min distance (shortcut criterion) // min distance (shortcut criterion)
q0 = (v0 - v3).SquaredNorm(); q0 = (v0 - v3).SquaredNorm();
q1 = (v1 - v4).SquaredNorm(); q1 = (v1 - v4).SquaredNorm();
@ -989,7 +1054,7 @@ static int TestEdgeRotation(const FaceType &f, int w0, ScalarType *gain=NULL)
//go++; //go++;
return 1; return 1;
} }
{ {
if (gain) *gain = sqrt(q2)-sqrt(q0); if (gain) *gain = sqrt(q2)-sqrt(q0);
// diagonal test, as above: // diagonal test, as above:
@ -1003,6 +1068,7 @@ static int TestEdgeRotation(const FaceType &f, int w0, ScalarType *gain=NULL)
//go++; //go++;
return -1; return -1;
} }
#endif
} }
private: private: