Commit 5f30ced1 authored by Kenneth Vanhoey's avatar Kenneth Vanhoey

Decimation with QEM extended to color (6d QEM).

parent c7299489
...@@ -127,7 +127,7 @@ void Approximator_ColorQEMext<PFP>::approximate(Dart d) ...@@ -127,7 +127,7 @@ void Approximator_ColorQEMext<PFP>::approximate(Dart d)
quad += q2 ; // two vertices quadrics quad += q2 ; // two vertices quadrics
VEC6 res ; VEC6 res ;
bool opt = quad.findOptimizedPos(res) ; // try to compute an optimized position for the contraction of this edge bool opt = quad.findOptimizedVec(res) ; // try to compute an optimized position for the contraction of this edge
if(!opt) if(!opt)
{ {
VEC6 p1, p2 ; VEC6 p1, p2 ;
...@@ -155,8 +155,8 @@ void Approximator_ColorQEMext<PFP>::approximate(Dart d) ...@@ -155,8 +155,8 @@ void Approximator_ColorQEMext<PFP>::approximate(Dart d)
// copy res into m_approx // copy res into m_approx
for (unsigned int i = 0 ; i < 3 ; ++i) for (unsigned int i = 0 ; i < 3 ; ++i)
{ {
this->m_approx[0][d] = res[i] ; this->m_approx[0][d][i] = res[i] ;
this->m_approx[1][d] = res[i+3] ; this->m_approx[1][d][i] = res[i+3] ;
} }
} }
......
...@@ -1357,7 +1357,7 @@ bool EdgeSelector_QEMextColor<PFP>::init() ...@@ -1357,7 +1357,7 @@ bool EdgeSelector_QEMextColor<PFP>::init()
++it) ++it)
{ {
// constraint : 2 approximators in specific order // constraint : 2 approximators in specific order
if(ok == 0 && (*it)->getApproximatedAttributeName(0) == "position" && (*it)->getApproximatedAttributeName(1) == "color") if((*it)->getApproximatedAttributeName(0) == "position" && (*it)->getApproximatedAttributeName(1) == "color")
{ {
m_poscolApproximator = reinterpret_cast<Approximator<PFP, VEC3>* >(*it) ; // pos + col m_poscolApproximator = reinterpret_cast<Approximator<PFP, VEC3>* >(*it) ; // pos + col
// check incompatibilities // check incompatibilities
...@@ -1478,10 +1478,11 @@ void EdgeSelector_QEMextColor<PFP>::recomputeQuadric(const Dart d, const bool re ...@@ -1478,10 +1478,11 @@ void EdgeSelector_QEMextColor<PFP>::recomputeQuadric(const Dart d, const bool re
if (dBack != dFront) if (dBack != dFront)
{ // if dFront is no border { // if dFront is no border
Dart d2 = this->m_map.phi2(dFront) ;
VEC6 p0, p1, p2 ; VEC6 p0, p1, p2 ;
for (unsigned int i = 0 ; i < 3 ; ++i) for (unsigned int i = 0 ; i < 3 ; ++i)
{ {
Dart d2 = this->m_map.phi2(dFront) ;
p0[i] = this->m_position[d][i] ; p0[i] = this->m_position[d][i] ;
p0[i+3] = this->m_color[d][i] ; p0[i+3] = this->m_color[d][i] ;
...@@ -1596,8 +1597,14 @@ void EdgeSelector_QEMextColor<PFP>::computeEdgeInfo(Dart d, EdgeInfo& einfo) ...@@ -1596,8 +1597,14 @@ void EdgeSelector_QEMextColor<PFP>::computeEdgeInfo(Dart d, EdgeInfo& einfo)
const REAL& err = quad(newEmb) ; const REAL& err = quad(newEmb) ;
einfo.it = edges.insert(std::make_pair(err, d)) ; // Check if errated values appear
einfo.valid = true ; if (err < -1e-6)
einfo.valid = false ;
else
{
einfo.it = edges.insert(std::make_pair(std::max(err,0.), d)) ;
einfo.valid = true ;
}
} }
......
...@@ -173,17 +173,19 @@ public: ...@@ -173,17 +173,19 @@ public:
typedef Geom::Vector<N,REAL> VECN ; typedef Geom::Vector<N,REAL> VECN ;
typedef Geom::Vector<N+1,REAL> VECNp ; typedef Geom::Vector<N+1,REAL> VECNp ;
typedef Geom::Matrix<N,N,double> MATRIXNN ; // double is crucial here !
typedef Geom::Matrix<N+1,N+1,double> MATRIXNpNp ; // double is crucial here !
QuadricNd() QuadricNd()
{ {
Q.zero() ; A.zero() ;
b.zero() ;
c = 0 ;
} }
QuadricNd(int i) QuadricNd(int i)
{ {
Q.zero() ; A.zero() ;
b.zero() ;
c = 0 ;
} }
QuadricNd(const VECN& p1_r, const VECN& p2_r, const VECN& p3_r) QuadricNd(const VECN& p1_r, const VECN& p2_r, const VECN& p3_r)
...@@ -193,133 +195,123 @@ public: ...@@ -193,133 +195,123 @@ public:
const Geom::Vector<N,double>& p3 = p3_r ; const Geom::Vector<N,double>& p3 = p3_r ;
Geom::Vector<N,double> e1 = p2 - p1 ; e1.normalize() ; Geom::Vector<N,double> e1 = p2 - p1 ; e1.normalize() ;
Geom::Vector<N,double> e2 = p3 - p1 - (e1*(p3-p1))*e1 ; e2.normalize() ; Geom::Vector<N,double> e2 = (p3 - p1) - (e1*(p3-p1))*e1 ; e2.normalize() ;
MATRIXNN A ;
A.identity() ; A.identity() ;
A -= (Geom::transposed_vectors_mult(e1,e1) + Geom::transposed_vectors_mult(e2,e2)) ; A -= Geom::transposed_vectors_mult(e1,e1) + Geom::transposed_vectors_mult(e2,e2) ;
const Geom::Vector<N,double>& b = (p1*e1)*e1 + (p1*e2)*e2 - p1 ; b = (p1*e1)*e1 + (p1*e2)*e2 - p1 ;
const REAL& c = p1*p1 - pow((p1*e1),2) - pow((p1*e2),2) ; c = p1*p1 - pow((p1*e1),2) - pow((p1*e2),2) ;
/*
* Build Q
* |-----------|
* Q = |- A - b -|
* |-----------|
* |- b^T - c -|
*/
Q.setSubMatrix(0,0,A) ;
Q.setSubVectorH(N,0,b) ;
Q.setSubVectorV(N,0,b) ;
Q(N,N) = c ;
} }
void zero() void zero()
{ {
Q.zero() ; A.zero() ;
b.zero() ;
c = 0 ;
} }
void operator= (const QuadricNd<REAL,N>& q) void operator= (const QuadricNd<REAL,N>& q)
{ {
Q = q.Q ; A = q.A ;
b = q.b ;
c = q.c ;
} }
QuadricNd& operator+= (const QuadricNd<REAL,N>& q) QuadricNd& operator+= (const QuadricNd<REAL,N>& q)
{ {
Q += q.Q ; A += q.A ;
b += q.b ;
c += q.c ;
return *this ; return *this ;
} }
QuadricNd& operator -= (const QuadricNd<REAL,N>& q) QuadricNd& operator -= (const QuadricNd<REAL,N>& q)
{ {
Q -= q.Q ; A -= q.A ;
b -= q.b ;
c -= q.c ;
return *this ; return *this ;
} }
QuadricNd& operator *= (REAL v) QuadricNd& operator *= (REAL v)
{ {
Q *= v ; A *= v ;
b *= v ;
c *= v ;
return *this ; return *this ;
} }
QuadricNd& operator /= (REAL v) QuadricNd& operator /= (REAL v)
{ {
Q /= v ; A /= v ;
b /= v ;
c /= v ;
return *this ; return *this ;
} }
REAL operator() (const VECNp& v) const REAL operator() (const VECNp& v) const
{ {
VECN hv ;
for (unsigned int i = 0 ; i < N ; ++i)
hv[i] = v[i] ;
return evaluate(v) ; return evaluate(v) ;
} }
REAL operator() (const VECN& v) const REAL operator() (const VECN& v) const
{ {
VECNp hv ; return evaluate(v) ;
for (unsigned int i = 0 ; i < N ; ++i)
hv[i] = v[i] ;
hv[N] = 1.0f ;
return evaluate(hv) ;
} }
friend std::ostream& operator<<(std::ostream& out, const QuadricNd<REAL,N>& q) friend std::ostream& operator<<(std::ostream& out, const QuadricNd<REAL,N>& q)
{ {
out << q.Q ; out << "(" << q.A << ", " << q.b << ", " << q.c << ")" ;
return out ; return out ;
} }
friend std::istream& operator>>(std::istream& in, QuadricNd<REAL,N>& q) friend std::istream& operator>>(std::istream& in, QuadricNd<REAL,N>& q)
{ {
in >> q.Q ; in >> q.A ;
in >> q.b ;
in >> q.c ;
return in ; return in ;
} }
bool findOptimizedPos(VECN& v) bool findOptimizedVec(VECN& v)
{ {
VECNp hv ; return optimize(v) ;
bool b = optimize(hv) ;
if(b)
{
for (unsigned int i = 0 ; i < N ; ++i)
v[i] = hv[i] ;
}
return b ;
} }
private: private:
MATRIXNpNp Q ; // Double computation is crucial for stability
Geom::Matrix<N,N,double> A ;
Geom::Vector<N,double> b ;
double c ;
REAL evaluate(const VECNp& v) const REAL evaluate(const VECN& v) const
{ {
// Double computation is crucial for stability Geom::Vector<N, double> v_d = v ;
Geom::Vector<N+1, double> Qv = Q * v ; return v_d*A*v_d + 2.*(b*v_d) + c ;
return v * Qv ;
} }
bool optimize(VECNp& v) const bool optimize(VECN& v) const
{ {
if (std::isnan(Q(0,0))) if (std::isnan(A(0,0)))
return false ; return false ;
MATRIXNpNp Q2(Q) ; Geom::Matrix<N,N,double> Ainv ;
for(unsigned int i = 0; i < N; ++i) double det = A.invert(Ainv) ;
Q2(N,i) = 0.0f ;
Q2(N,N) = 1.0f ;
MATRIXNpNp Qinv ;
REAL det = Q2.invert(Qinv) ;
if(det > -1e-6 && det < 1e-6) if(det > -1e-6 && det < 1e-6)
return false ; return false ;
VECNp right(0) ; v.zero() ;
right[N] = 1 ; // last element v -= Ainv * b ;
v = Qinv * right ;
return true; return true ;
} }
} ; } ;
//} // Utils //} // Utils
} // CGOGN } // CGOGN
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment