Commit 3bf59b68 authored by Kenneth Vanhoey's avatar Kenneth Vanhoey

up

parent a517c887
......@@ -182,6 +182,97 @@ public:
}
} ;
/*****************************************************************************************************************
* HALF-EDGE QEMextColorNormal METRIC *
*****************************************************************************************************************/
template <typename PFP>
class HalfEdgeSelector_QEMextColorNormal : public Selector<PFP>
{
public:
typedef typename PFP::MAP MAP ;
typedef typename PFP::REAL REAL ;
typedef typename PFP::VEC3 VEC3 ;
typedef typename Geom::Vector<9,REAL> VEC9 ;
private:
typedef struct
{
typename std::multimap<float,Dart>::iterator it ;
bool valid ;
static std::string CGoGNnameOfType() { return "QEMextColorNormalHalfEdgeInfo" ; }
} QEMextColorNormalHalfEdgeInfo ;
typedef NoTypeNameAttribute<QEMextColorNormalHalfEdgeInfo> HalfEdgeInfo ;
DartAttribute<HalfEdgeInfo> halfEdgeInfo ;
VertexAttribute<Utils::QuadricNd<REAL,9> > m_quadric ;
VertexAttribute<VEC3> m_pos, m_color, m_normal ;
int m_approxindex_pos, m_attrindex_pos ;
int m_approxindex_color, m_attrindex_color ;
int m_approxindex_normal, m_attrindex_normal ;
std::vector<Approximator<PFP, typename PFP::VEC3,DART>* > m_approx ;
std::multimap<float,Dart> halfEdges ;
typename std::multimap<float,Dart>::iterator cur ;
void initHalfEdgeInfo(Dart d) ;
void updateHalfEdgeInfo(Dart d, bool recompute) ;
void computeHalfEdgeInfo(Dart d, HalfEdgeInfo& einfo) ;
void recomputeQuadric(const Dart d, const bool recomputeNeighbors = false) ;
public:
HalfEdgeSelector_QEMextColorNormal(MAP& m, VertexAttribute<typename PFP::VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx) :
Selector<PFP>(m, pos, approx),
m_approxindex_pos(-1),
m_attrindex_pos(-1),
m_approxindex_color(-1),
m_attrindex_color(-1),
m_approxindex_normal(-1),
m_attrindex_normal(-1)
{
halfEdgeInfo = m.template addAttribute<HalfEdgeInfo, DART>("halfEdgeInfo") ;
m_quadric = m.template addAttribute<Utils::QuadricNd<REAL,9>, VERTEX>("hQEMextNormal-quadric") ;
}
~HalfEdgeSelector_QEMextColorNormal()
{
this->m_map.removeAttribute(m_quadric) ;
this->m_map.removeAttribute(halfEdgeInfo) ;
}
SelectorType getType() { return S_hQEMextColorNormal ; }
bool init() ;
bool nextEdge(Dart& d) const ;
void updateBeforeCollapse(Dart d) ;
void updateAfterCollapse(Dart d2, Dart dd2) ;
void updateWithoutCollapse() { }
void getEdgeErrors(EdgeAttribute<typename PFP::REAL> *errors) const
{
assert(errors != NULL || !"EdgeSelector::setColorMap requires non null vertexattribute argument") ;
if (!errors->isValid())
std::cerr << "EdgeSelector::setColorMap requires valid edgeattribute argument" << std::endl ;
assert(halfEdgeInfo.isValid()) ;
TraversorE<typename PFP::MAP> travE(this->m_map) ;
for(Dart d = travE.begin() ; d != travE.end() ; d = travE.next())
{
Dart dd = this->m_map.phi2(d) ;
if (halfEdgeInfo[d].valid)
{
(*errors)[d] = halfEdgeInfo[d].it->first ;
}
if (halfEdgeInfo[dd].valid && halfEdgeInfo[dd].it->first < (*errors)[d])
{
(*errors)[d] = halfEdgeInfo[dd].it->first ;
}
if (!(halfEdgeInfo[d].valid || halfEdgeInfo[dd].valid))
(*errors)[d] = -1 ;
}
}
} ;
/*****************************************************************************************************************
* HALF-EDGE COLOR GRADIENT ERR *
*****************************************************************************************************************/
......
......@@ -580,6 +580,341 @@ void HalfEdgeSelector_QEMextColor<PFP>::computeHalfEdgeInfo(Dart d, HalfEdgeInfo
}
}
/*****************************************************************************************************************
* HALF-EDGE QEMextColorNormal METRIC *
*****************************************************************************************************************/
template <typename PFP>
bool HalfEdgeSelector_QEMextColorNormal<PFP>::init()
{
MAP& m = this->m_map ;
// Verify availability of required approximators
unsigned int ok = 0 ;
for (unsigned int approxindex = 0 ; approxindex < this->m_approximators.size() ; ++approxindex)
{
assert(this->m_approximators[approxindex]->getType() == A_hQEM
|| this->m_approximators[approxindex]->getType() == A_hHalfCollapse
|| !"Approximator for selector (HalfEdgeSelector_QEMextColorNormal) must be of a half-edge approximator") ;
bool saved = false ;
for (unsigned int attrindex = 0 ; attrindex < this->m_approximators[approxindex]->getNbApproximated() ; ++ attrindex)
{
// constraint : 2 approximators in specific order
if(ok == 0 && this->m_approximators[approxindex]->getApproximatedAttributeName(attrindex) == "position")
{
++ok ;
m_approxindex_pos = approxindex ;
m_attrindex_pos = attrindex ;
m_pos = this->m_position ;
if (!saved)
{
m_approx.push_back(reinterpret_cast<Approximator<PFP, VEC3, DART>* >(this->m_approximators[approxindex])) ;
saved = true ;
}
}
else if(ok == 1 && this->m_approximators[approxindex]->getApproximatedAttributeName(attrindex) == "color")
{
++ok ;
m_approxindex_color = approxindex ;
m_attrindex_color = attrindex ;
m_color = m.template getAttribute<typename PFP::VEC3, VERTEX>("color") ;
assert(m_color.isValid() || !"EdgeSelector_QEMextColor: color attribute is not valid") ;
if (!saved)
{
m_approx.push_back(reinterpret_cast<Approximator<PFP, VEC3, DART>* >(this->m_approximators[approxindex])) ;
saved = true ;
}
}
else if(ok == 2 && this->m_approximators[approxindex]->getApproximatedAttributeName(attrindex) == "normal")
{
++ok ;
m_approxindex_normal = approxindex ;
m_attrindex_normal = attrindex ;
m_normal = m.template getAttribute<typename PFP::VEC3, VERTEX>("normal") ;
assert(m_normal.isValid() || !"EdgeSelector_QEMextColorNormal: normal attribute is not valid") ;
if (!saved)
{
m_approx.push_back(reinterpret_cast<Approximator<PFP, VEC3, DART>* >(this->m_approximators[approxindex])) ;
saved = true ;
}
}
}
}
if(ok != 3)
return false ;
TraversorV<MAP> travV(m);
for(Dart dit = travV.begin() ; dit != travV.end() ; dit = travV.next())
{
Utils::QuadricNd<REAL,9> q ; // create one quadric
m_quadric[dit] = q ; // per vertex
}
// Compute quadric per vertex
TraversorF<MAP> travF(m) ;
for(Dart dit = travF.begin() ; dit != travF.end() ; dit = travF.next()) // init QEM quadrics
{
Dart d1 = m.phi1(dit) ; // for each triangle,
Dart d_1 = m.phi_1(dit) ; // initialize the quadric of the triangle
VEC9 p0, p1, p2 ;
for (unsigned int i = 0 ; i < 3 ; ++i)
{
p0[i] = this->m_position[dit][i] ;
p0[i+3] = this->m_color[dit][i] ;
p0[i+6] = this->m_normal[dit][i] ;
p1[i] = this->m_position[d1][i] ;
p1[i+3] = this->m_color[d1][i] ;
p1[i+6] = this->m_normal[d1][i] ;
p2[i] = this->m_position[d_1][i] ;
p2[i+3] = this->m_color[d_1][i] ;
p2[i+6] = this->m_normal[d_1][i] ;
}
Utils::QuadricNd<REAL,9> q(p0,p1,p2) ;
m_quadric[dit] += q ; // and add the contribution of
m_quadric[d1] += q ; // this quadric to the ones
m_quadric[d_1] += q ; // of the 3 incident vertices
}
// Init multimap for each Half-edge
halfEdges.clear() ;
for(Dart d = m.begin(); d != m.end(); m.next(d))
{
initHalfEdgeInfo(d) ; // init the edges with their optimal info
} // and insert them in the multimap according to their error
cur = halfEdges.begin() ; // init the current edge to the first one
return true ;
}
template <typename PFP>
bool HalfEdgeSelector_QEMextColorNormal<PFP>::nextEdge(Dart& d) const
{
if(cur == halfEdges.end() || halfEdges.empty())
return false ;
d = (*cur).second ;
return true ;
}
template <typename PFP>
void HalfEdgeSelector_QEMextColorNormal<PFP>::updateBeforeCollapse(Dart d)
{
MAP& m = this->m_map ;
HalfEdgeInfo* edgeE = &(halfEdgeInfo[d]) ;
if(edgeE->valid)
halfEdges.erase(edgeE->it) ;
edgeE = &(halfEdgeInfo[m.phi1(d)]) ;
if(edgeE->valid) // remove all
halfEdges.erase(edgeE->it) ;
edgeE = &(halfEdgeInfo[m.phi_1(d)]) ; // the halfedges that will disappear
if(edgeE->valid)
halfEdges.erase(edgeE->it) ;
// from the multimap
Dart dd = m.phi2(d) ;
assert(dd != d) ;
if(dd != d)
{
edgeE = &(halfEdgeInfo[dd]) ;
if(edgeE->valid)
halfEdges.erase(edgeE->it) ;
edgeE = &(halfEdgeInfo[m.phi1(dd)]) ;
if(edgeE->valid)
halfEdges.erase(edgeE->it) ;
edgeE = &(halfEdgeInfo[m.phi_1(dd)]) ;
if(edgeE->valid)
halfEdges.erase(edgeE->it) ;
}
}
template <typename PFP>
void HalfEdgeSelector_QEMextColorNormal<PFP>::recomputeQuadric(const Dart d, const bool recomputeNeighbors) {
Dart dFront,dBack ;
Dart dInit = d ;
// Init Front
dFront = dInit ;
m_quadric[d].zero() ;
do
{
// Make step
dBack = this->m_map.phi2(dFront) ;
dFront = this->m_map.phi2_1(dFront) ;
if (dBack != dFront)
{ // if dFront is no border
Dart d2 = this->m_map.phi2(dFront) ;
VEC9 p0, p1, p2 ;
for (unsigned int i = 0 ; i < 3 ; ++i)
{
p0[i] = this->m_position[d][i] ;
p0[i+3] = this->m_color[d][i] ;
p0[i+6] = this->m_normal[d][i] ;
p1[i] = this->m_position[d2][i] ;
p1[i+3] = this->m_color[d2][i] ;
p1[i+6] = this->m_normal[d2][i] ;
p2[i] = this->m_position[dBack][i] ;
p2[i+3] = this->m_color[dBack][i] ;
p2[i+6] = this->m_normal[dBack][i] ;
}
m_quadric[d] += Utils::QuadricNd<REAL,9>(p0,p1,p2) ;
}
if (recomputeNeighbors)
recomputeQuadric(dBack, false) ;
} while(dFront != dInit) ;
}
template <typename PFP>
void HalfEdgeSelector_QEMextColorNormal<PFP>::updateAfterCollapse(Dart d2, Dart /*dd2*/)
{
MAP& m = this->m_map ;
recomputeQuadric(d2, true) ;
Dart vit = d2 ;
do
{
updateHalfEdgeInfo(vit, true) ;
Dart d = m.phi2(vit) ;
if (d != vit)
updateHalfEdgeInfo(d, true) ;
updateHalfEdgeInfo(m.phi1(vit), true) ;
d = m.phi2(m.phi1(vit)) ;
if (d != m.phi1(vit))
updateHalfEdgeInfo(d, true) ;
Dart stop = m.phi2(vit) ;
assert (stop != vit) ;
Dart vit2 = m.phi12(m.phi1(vit)) ;
do {
updateHalfEdgeInfo(vit2, true) ;
d = m.phi2(vit2) ;
if (d != vit2)
updateHalfEdgeInfo(d, true) ;
updateHalfEdgeInfo(m.phi1(vit2), false) ;
d = m.phi2(m.phi1(vit2)) ;
if (d != m.phi1(vit2))
updateHalfEdgeInfo(d, false) ;
vit2 = m.phi12(vit2) ;
} while (stop != vit2) ;
vit = m.phi2_1(vit) ;
} while(vit != d2) ;
cur = halfEdges.begin() ; // set the current edge to the first one
}
template <typename PFP>
void HalfEdgeSelector_QEMextColorNormal<PFP>::initHalfEdgeInfo(Dart d)
{
MAP& m = this->m_map ;
HalfEdgeInfo heinfo ;
if(m.edgeCanCollapse(d))
computeHalfEdgeInfo(d, heinfo) ;
else
heinfo.valid = false ;
halfEdgeInfo[d] = heinfo ;
}
template <typename PFP>
void HalfEdgeSelector_QEMextColorNormal<PFP>::updateHalfEdgeInfo(Dart d, bool recompute)
{
MAP& m = this->m_map ;
HalfEdgeInfo& heinfo = halfEdgeInfo[d] ;
if(recompute)
{
if(heinfo.valid)
halfEdges.erase(heinfo.it) ; // remove the edge from the multimap
if(m.edgeCanCollapse(d))
computeHalfEdgeInfo(d, heinfo) ;
else
heinfo.valid = false ;
}
else
{
if(m.edgeCanCollapse(d))
{ // if the edge can be collapsed now
if(!heinfo.valid) // but it was not before
computeHalfEdgeInfo(d, heinfo) ;
}
else
{ // if the edge cannot be collapsed now
if(heinfo.valid) // and it was before
{
halfEdges.erase(heinfo.it) ;
heinfo.valid = false ;
}
}
}
}
template <typename PFP>
void HalfEdgeSelector_QEMextColorNormal<PFP>::computeHalfEdgeInfo(Dart d, HalfEdgeInfo& heinfo)
{
MAP& m = this->m_map ;
Dart dd = m.phi1(d) ;
// New position
Utils::QuadricNd<REAL,9> quad ;
quad += m_quadric[d] ; // compute the sum of the
quad += m_quadric[dd] ; // two vertices quadrics
// compute all approximated attributes
for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = this->m_approximators.begin() ;
it != this->m_approximators.end() ;
++it)
{
(*it)->approximate(d) ;
}
// get pos
const VEC3& newPos = this->m_approx[m_approxindex_pos]->getApprox(d,m_attrindex_pos) ; // get newPos
// get col
const VEC3& newCol = this->m_approx[m_approxindex_color]->getApprox(d,m_attrindex_color) ; // get newCol
// get normal
const VEC3& newN = this->m_approx[m_approxindex_normal]->getApprox(d,m_attrindex_normal) ; // get newN
// compute error
VEC9 newEmb ;
for (unsigned int i = 0 ; i < 3 ; ++i)
{
newEmb[i] = newPos[i] ;
newEmb[i+3] = newCol[i] ;
newEmb[i+6] = newN[i] ;
}
const REAL& err = quad(newEmb) ;
// Check if errated values appear
if (err < -1e-6)
heinfo.valid = false ;
else
{
heinfo.it = this->halfEdges.insert(std::make_pair(std::max(err,REAL(0)), d)) ;
heinfo.valid = true ;
}
}
/*****************************************************************************************************************
* HALF-EDGE COLOR GRADIENT ERR *
*****************************************************************************************************************/
......
......@@ -62,6 +62,8 @@ enum SelectorType
// Geom + color criteria
S_hQEMextColor = 13, /**< Prioritizes half-edges by the quadric error metric (QEM) error extended in R^6 (x,y,z,R,G,B) [GH98]. Requires a geometry approximator. Requires a color approximator. */
S_hColorGradient = 14, /**< EXPERIMENTAL Prioritizes half-edges according to the sum of the quadric error metric (QEM) for geometry and the gradient color deviation metric of [Vanhoey,Sauvage]. Requires a geometry approximator. Requires a color approximator. */
// Geom + color + normal criteria
S_hQEMextColorNormal = 15, /**< Prioritizes half-edges by the quadric error metric (QEM) error extended in R^9 (x,y,z,R,G,B,nx,ny,nz) [GH98]. Requires a geometry approximator. Requires a color approximator. Requires a normal approximator */
S_OTHER /**< Can be used for extensions. */
} ;
......
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