Commit b780824b authored by untereiner's avatar untereiner

- adding multilevel extrusion to importMeshExtrud

- volumetric decimation
parent 6a57cabf
......@@ -621,7 +621,7 @@ void MyQT::cb_keyPress(int keycode)
// Sélectionne des faces
case 'f':
d_faces.clear();
Algo::Selection:: facesRaySelection<PFP>(myMap, position, SelectorTrue(), rayA, AB, d_faces);
Algo::Selection::facesRaySelection<PFP>(myMap, position, SelectorTrue(), rayA, AB, d_faces);
if (!d_faces.empty())
{
......
......@@ -126,7 +126,7 @@ void decimate(
selector = new EdgeSelector_Curvature<PFP>(map, position, approximators, selected) ;
break ;
case S_MinDetail :
selector = new EdgeSelector_Random<PFP>(map, position, approximators, selected) ;
selector = new EdgeSelector_MinDetail<PFP>(map, position, approximators, selected) ;
break ;
case S_hLightfield :
selector = new HalfEdgeSelector_Lightfield<PFP>(map, position, approximators, selected) ;
......
......@@ -946,14 +946,10 @@ bool EdgeSelector_MinDetail<PFP>::init()
edges.clear() ;
CellMarker<EDGE> eMark(m) ;
for(Dart d = m.begin(); d != m.end(); m.next(d))
TraversorE<MAP> travE(m);
for(Dart dit = travE.begin() ; dit != travE.end() ; dit = travE.next())
{
if(!eMark.isMarked(d))
{
initEdgeInfo(d) ; // init the edges with their optimal position
eMark.mark(d) ; // and insert them in the multimap according to their error
}
initEdgeInfo(dit);
}
cur = edges.begin() ; // init the current edge to the first one
......
......@@ -26,6 +26,7 @@
#define __APPROXIMATOR_VOLUMES_H__
#include "Algo/DecimationVolumes/operator.h"
#include "Algo/DecimationVolumes/predictor.h"
namespace CGoGN
{
......@@ -38,7 +39,7 @@ namespace DecimationVolumes
enum ApproximatorType
{
A_Centroid //barycenter of the n-cells
A_QEM
};
template <typename PFP>
......@@ -60,9 +61,12 @@ public:
virtual const std::string& getApproximatedAttributeName() const = 0 ;
virtual ApproximatorType getType() const = 0 ;
virtual bool init() = 0 ;
virtual const PredictorGen<PFP>* getPredictor() const = 0 ;
virtual void approximate(Operator<PFP>* op) = 0 ;
virtual void saveApprox(Operator<PFP>* op) = 0 ;
virtual void affectApprox(Operator<PFP>* op) = 0 ;
virtual void approximate(Dart d) = 0;
} ;
......@@ -74,39 +78,91 @@ public:
typedef typename PFP::REAL REAL;
protected:
Predictor<PFP, T>* m_predictor ;
//TODO ajouter un predictor
VertexAttribute<T>& m_attrV; // vertex attribute to be approximated
//TODO Attribute to store approximation result
//TODO attribute to store detail information for reconstruction
//Vertex attribute to be approximated
VertexAttribute<T>& m_attrV;
//Attribute to store approximation result
EdgeAttribute<T> m_approx;
// attribute to store detail information for reconstruction
EdgeAttribute<T> m_detail ;
T m_app;
public:
Approximator(MAP& m, VertexAttribute<T>& a):
ApproximatorGen<PFP>(m), m_attrV(a)
{}
Approximator(MAP& m, VertexAttribute<T>& a, Predictor<PFP, T>* predictor) :
ApproximatorGen<PFP>(m), m_predictor(predictor), m_attrV(a)
{
std::stringstream aname ;
aname << "approx_" << m_attrV.name() ;
m_approx = this->m_map.template addAttribute<T, EDGE>(aname.str()) ;
if(m_predictor) // if a predictor is associated to the approximator
{ // create an attribute to store the detail needed for reconstruction
std::stringstream dname ;
dname << "detail_" << m_attrV.name() ;
m_detail = this->m_map.template addAttribute<T, EDGE>(dname.str()) ;
}
}
//virtual ~Approximator();
virtual ~Approximator()
{
this->m_map.template removeAttribute(m_approx) ;
if(m_predictor)
this->m_map.template removeAttribute(m_detail) ;
}
const std::string& getApproximatedAttributeName() const
{
return m_attrV.name() ;
}
void saveApprox(Operator<PFP>* op)
const T& getApprox(Dart d) const
{
Dart d = op->getEdge();
//m_app = m_approx[d] ;
return m_approx[d] ;
}
const Predictor<PFP, T>* getPredictor() const
{
return m_predictor ;
}
void affectApprox(Operator<PFP>* op)
const T& getDetail(Dart d) const
{
assert(m_predictor || !"Trying to get detail on a non-predictive scheme") ;
return m_detail[d] ;
}
void setDetail(Dart d, T& val)
{
assert(m_predictor || !"Trying to set detail on a non-predictive scheme") ;
m_detail[d] = val ;
}
virtual void saveApprox(Operator<PFP>* op)
{
Dart d = op->getEdge();
m_attrV[d] = m_app ;
m_app = m_approx[d];
}
virtual void affectApprox(Operator<PFP>* op)
{
Dart d = op->getEdge();
m_attrV[d] = m_app;
}
// void saveApprox(Dart d)
// {
// m_app = m_approx[d] ;
// }
//
// void affectApprox(Dart d)
// {
// m_attrV[d] = m_app ;
// }
};
......
......@@ -38,13 +38,13 @@ void decimate(
)
{
std::vector<ApproximatorGen<PFP>*> approximators ;
Selector<PFP>* selector = NULL ;
EdgeSelector<PFP>* selector = NULL ;
//choose the Approximator
switch(a)
{
case A_Centroid :
approximators.push_back(new Approximator_Centroid<PFP>(map, position)) ;
case A_QEM :
approximators.push_back(new Approximator_QEM<PFP>(map, position)) ;
break ;
default :
CGoGNout << "not yet implemented" << CGoGNendl;
......@@ -54,11 +54,8 @@ void decimate(
//choose the Selector
switch(s)
{
case S_MapOrder :
selector = new EdgeSelector_MapOrder<PFP>(map, position, approximators, selected);
break ;
case S_Random :
//selector = new EdgeSelector_Random<PFP>(map, position, approximators, selected);
case S_QEM :
selector = new EdgeSelector_QEM<PFP>(map, position, approximators, selected) ;
break ;
default:
CGoGNout << "not yet implemented" << CGoGNendl;
......@@ -77,33 +74,38 @@ void decimate(
CGoGNout << " decimate (" << nbVertices << " vertices).." << /* flush */ CGoGNendl ;
bool finished = false ;
Dart d;
while(!finished)
{
//Next Operator to perform
Operator<PFP> *op;
if(!selector->nextOperator(&op))
//if(!selector->nextOperator(&op))
if((op = selector->nextOperator()) == NULL)
break;
// compute approximated attributes
for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = approximators.begin(); it != approximators.end(); ++it)
{
(*it)->approximate(op) ;
(*it)->saveApprox(op) ;
}
//Update the selector before performing operation
selector->updateBeforeOperation(&op);
if(!selector->updateBeforeOperation(op))
break;
//Perform the topological operation and
//compute the number of resulting cells
nbVertices -= op->perform(map, position);
//for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = approximators.begin(); it != approximators.end(); ++it)
// (*it)->affectApprox(op); // affect data to the resulting vertex
for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = approximators.begin(); it != approximators.end(); ++it)
(*it)->affectApprox(op); // affect data to the resulting vertex
//Update the embedded position and
//search the next operation to perform
selector->updateAfterOperation(&op);
selector->updateAfterOperation(op);
if(nbVertices <= nbWantedVertices)
finished = true ;
......@@ -126,3 +128,35 @@ void decimate(
} //namespace Algo
} //namespace CGoGN
// if(!selector->nextEdge(d))
// break ;
//
//
// Dart d2 = map.phi2(map.phi_1(d)) ;
// Dart dd2 = map.phi2(map.phi_1(map.phi2(d))) ;
//
// std::cout << "bin a contracter : " << d << std::endl;
// std::cout << "voisin d2 : " << d2 << std::endl;
// std::cout << "voisin dd2 : " << dd2 << std::endl;
//
// --nbVertices ;
//
// for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = approximators.begin(); it != approximators.end(); ++it)
// {
// (*it)->approximate(d) ; // compute approximated attributes
// (*it)->saveApprox(d) ;
// }
//
// selector->updateBeforeCollapse(d) ; // update selector
//
// map.collapseEdge(d) ; // collapse edge
//
// for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = approximators.begin(); it != approximators.end(); ++it)
// (*it)->affectApprox(d2); // affect data to the resulting vertex
//
// selector->updateAfterCollapse(d2, dd2) ;// update selector
//
// if(nbVertices <= nbWantedVertices)
// finished = true ;
......@@ -4,6 +4,8 @@
#include "Container/fakeAttribute.h"
#include "Algo/DecimationVolumes/selector.h"
#include "Algo/DecimationVolumes/operator.h"
#include "Utils/qem.h"
#include "Topology/generic/traversorCell.h"
namespace CGoGN
{
......@@ -35,140 +37,62 @@ public:
};
/********************************************************************************
* Map Order Edge Selector *
********************************************************************************/
template <typename PFP>
class EdgeSelector_MapOrder : public EdgeSelector<PFP>
class EdgeSelector_QEM : public EdgeSelector<PFP>
{
public:
typedef typename PFP::MAP MAP ;
typedef typename PFP::VEC3 VEC3 ;
typedef typename PFP::MAP MAP;
typedef typename PFP::VEC3 VEC3;
typedef typename PFP::REAL REAL;
private:
Dart cur;
typedef struct
{
typename std::multimap<float, Dart>::iterator it;
bool valid;
static std::string CGoGNnameOfType() { return "QEMedgeInfo" ; }
} QEMedgeInfo;
public:
EdgeSelector_MapOrder(MAP& m, VertexAttribute<typename PFP::VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select) :
EdgeSelector<PFP>(m, pos, approx, select)
{}
typedef NoMathIOAttribute<QEMedgeInfo> EdgeInfo;
~EdgeSelector_MapOrder()
{}
EdgeAttribute<EdgeInfo> edgeInfo;
VertexAttribute<Quadric<REAL> > quadric;
Quadric<REAL> tmpQ;
SelectorType getType() { return S_MapOrder; }
Dart nextCell() { return cur; }
std::multimap<float, Dart> edges;
typename std::multimap<float, Dart>::iterator cur;
bool init();
bool nextOperator(Operator<PFP>** op);
void updateBeforeOperation(Operator<PFP>** op)
{ }
void updateAfterOperation(Operator<PFP>** op);
void finish()
{ }
Approximator<PFP, typename PFP::VEC3>* m_positionApproximator;
void initEdgeInfo(Dart d);
void updateEdgeInfo(Dart d, bool recompute);
void computeEdgeInfo(Dart d, EdgeInfo& einfo);
public:
EdgeSelector_QEM(MAP& m, VertexAttribute<typename PFP::VEC3>& pos,
std::vector<ApproximatorGen<PFP>* >& approx, const FunctorSelect& select) :
EdgeSelector<PFP>(m, pos, approx, select)
{
edgeInfo = m.template addAttribute<EdgeInfo, EDGE>("edgeInfo");
quadric = m.template addAttribute<Quadric<REAL>, VERTEX>("QEMquadric");
}
~EdgeSelector_QEM()
{
this->m_map.removeAttribute(quadric);
this->m_map.removeAttribute(edgeInfo);
}
SelectorType getType() { return S_QEM; }
bool init();
Operator<PFP>* nextOperator();
bool updateBeforeOperation(Operator<PFP>* op);
void updateAfterOperation(Operator<PFP>* op);
void finish() { }
};
/********************************************************************************
* Random Selector *
********************************************************************************/
//template <typename PFP>
//class EdgeSelector_Random : public EdgeSelector<PFP>
//{
//public:
// typedef typename PFP::MAP MAP ;
// typedef typename PFP::VEC3 VEC3 ;
// typedef typename PFP::REAL REAL ;
//
//private:
// std::vector<Dart> darts ;
// unsigned int cur ;
// bool allSkipped ;
//
//public:
// EdgeSelector_Random(MAP& m, VertexAttribute<typename PFP::VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select) :
// EdgeSelector<PFP>(m, pos, approx, select)
// {}
//
// ~EdgeSelector_Random()
// {}
//
// SelectorType getType() { return S_Random; }
//// Dart nextCell() { return darts[cur]; }
//
// bool init();
// bool nextOperator(Operator<PFP>** op);
// void updateBeforeOperation(Operator<PFP>* op)
// { }
// void updateAfterOperation(Operator<PFP>* op);
// void finish()
// { }
//
//} ;
///********************************************************************************
// * Length Edge Selector *
// ********************************************************************************/
//template <typename PFP>
//class EdgeSelector_Length : public EdgeSelector<PFP>
//{
//public:
// typedef typename PFP::MAP MAP;
// typedef typename PFP::VEC3 VEC3;
// typedef typename PFP::REAL REAL;
//
//protected:
// /*
// * Update the Edge Informations
// */
// void updateEdgeInfo(Dart d, typename PFP::VEC3 e);
// /*
// * Init the Edge informations
// */
// void initEdgeInfo(Dart d);
// /*
// * Erase The Edge informations
// */
// void eraseEdgeInfo(Dart d);
//
//private:
// //New embedding type for storing informations
// typedef struct {
// typename std::multimap<float,Dart>::iterator it ;
// bool valid ;
// } LengthEdgeInfo ;
//
// typedef NoMathIOAttribute<LengthEdgeInfo> EdgeInfo ;
//
// EdgeAttribute<EdgeInfo> edgeInfo ;
//
// std::multimap<float,Dart> edges ;
// typename std::multimap<float,Dart>::iterator cur ;
//
//
//public:
// EdgeSelector_Length(MAP& m, VertexAttribute<typename PFP::VEC3>& pos) :
// EdgeSelector<PFP>(m, pos)
// {
// edgeInfo = m.template addAttribute<EdgeInfo>(EDGE, "edgeInfo") ;
// }
//
// ~EdgeSelector_Length()
// {
// this->m_map.removeAttribute(edgeInfo) ;
// }
//
// SelectorType getType() { return S_EdgeLength; }
// Dart nexCell() { return (*cur).second; }
//
// void init(Algo::DecimationVolumique::Approximator<PFP>* approx);
// bool nextOperator();
// void updateBeforeOperation(Algo::DecimationVolumique::Operator<PFP>* op);
// void updateAfterOperation(Algo::DecimationVolumique::Operator<PFP>* op);
// void finish()
// { }
//};
} //end namespace DecimationVolumes
......
......@@ -35,179 +35,222 @@ namespace DecimationVolumes
{
/************************************************************************************
* Map Order Edge Selector *
* QUADRIC ERROR METRIC *
************************************************************************************/
template <typename PFP>
bool EdgeSelector_MapOrder<PFP>::init()
bool EdgeSelector_QEM<PFP>::init()
{
cur = this->m_map.begin() ;
MAP& m = this->m_map ;
//searching the Geometry Approximator
bool ok = false ;
for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = this->m_approximators.begin();
it != this->m_approximators.end() && !ok;
++it)
{
if((*it)->getApproximatedAttributeName() == "position")
{
m_positionApproximator = reinterpret_cast<Approximator<PFP, VEC3>* >(*it) ;
ok = true ;
}
}
if(!ok)
return false ;
// init the Quadric error metric for cells
edges.clear();
TraversorV<MAP> travV(m);
for(Dart dit = travV.begin() ; dit != travV.end() ; dit = travV.next())
{
//create one quadric per vertex
Quadric<REAL> q;
quadric[dit] = q;
}
// init the quadric for each boundary triangle
TraversorF<MAP> travF(m);
for(Dart dit = travF.begin() ; dit != travF.end() ; dit = travF.next())
{
Dart d1 = m.phi1(dit) ; // for each triangle,
Dart d_1 = m.phi_1(dit) ; // initialize the quadric of the triangle
Quadric<REAL> q(this->m_position[dit], this->m_position[d1], this->m_position[d_1]) ;
quadric[dit] += q ; // and add the contribution of
quadric[d1] += q ; // this quadric to the ones
quadric[d_1] += q ; // of the 3 incident vertices
}
// init the edges with their optimal position
// and insert them in the multimap according to their error
TraversorE<MAP> travE(m);
for(Dart dit = travE.begin() ; dit != travE.end() ; dit = travE.next())
{
initEdgeInfo(dit);
}
//TODO Choix de nextOperator
//this->nextOp = Algo::DecimationVolumique::O_CEdge;
// init the current edge to the first one
cur = edges.begin();
return true;
}
template <typename PFP>
bool EdgeSelector_MapOrder<PFP>::nextOperator(Operator<PFP>** op)
Operator<PFP>* EdgeSelector_QEM<PFP>::nextOperator()
{
if(cur == this->m_map.end())
return false ;
MAP& m = this->m_map ;
Operator<PFP>* op = NULL;
if(cur != edges.end() && !edges.empty())
{
op = new CollapseEdgeOperator<PFP>((*cur).second);
*op = new CollapseEdgeOperator<PFP>(cur);
op->setFirstIncidentEdge(m.phi2(m.phi_1((*cur).second)));
op->setSecondIncidentEdge(m.phi2(m.phi_1(m.phi2((*cur).second))));
}
return true ;
return op ;
}
template <typename PFP>
void EdgeSelector_MapOrder<PFP>::updateAfterOperation(Operator<PFP>** op)
bool EdgeSelector_QEM<PFP>::updateBeforeOperation(Operator<PFP>* op)
{
MAP& m = this->m_map ;
Dart d = op->getEdge();
//Mise à jour de nextOperator
EdgeInfo& edgeE = edgeInfo[d] ;
if(edgeE.valid)
edges.erase(edgeE.it) ;
cur = m.begin() ;
edgeE = edgeInfo[m.phi1(d)] ;
if(edgeE.valid) // remove all
edges.erase(edgeE.it) ;
while(!(*op)->canPerform(m,cur,this->m_position))
edgeE = edgeInfo[m.phi_1(d)] ; // the concerned edges
if(edgeE.valid)
edges.erase(edgeE.it) ;
// from the multimap
Dart dd = m.phi2(d) ;
if(dd != d)
{
//CGoGNout << "update " << cur << CGoGNendl;
m.next(cur) ;
if(cur == m.end())
break ;
edgeE = edgeInfo[m.phi1(dd)] ;
if(edgeE.valid)
edges.erase(edgeE.it) ;
edgeE = edgeInfo[m.phi_1(dd)] ;
if(edgeE.valid)
edges.erase(edgeE.it) ;
}
tmpQ.zero() ; // compute quadric for the new
tmpQ += quadric[d] ; // vertex as the sum of those
tmpQ += quadric[dd] ; // of the contracted vertices
return true;
}
/************************************************************************************
* Random Edge Selector *
************************************************************************************/
template <typename PFP>
void EdgeSelector_QEM<PFP>::updateAfterOperation(Operator<PFP>* op)
{
MAP& m = this->m_map ;
Dart d2 = op->getFirstIncidentEdge();
Dart dd2 = op->getSecondIncidentEdge();
quadric[d2] = tmpQ ;
Dart vit = d2 ;
do
{
updateEdgeInfo(m.phi1(vit), false) ; // must recompute some edge infos in the
if(vit == d2 || vit == dd2) // neighborhood of the collapsed edge
{
initEdgeInfo(vit) ; // various optimizations are applied here by
// treating differently :
Dart vit2 = m.phi1(m.phi2(m.phi1(vit))) ; // - edges for which the criteria must be recomputed
Dart stop = m.phi2(vit) ; // - edges that must be re-embedded
do // - edges for which only the collapsibility must be re-tested
{
updateEdgeInfo(vit2, false) ;
updateEdgeInfo(m.phi1(vit2), false) ;
vit2 = m.phi1(m.phi2(vit2)) ;
} while(vit2 != stop) ;
}
else
updateEdgeInfo(vit, true) ;
vit = m.phi2(m.phi_1(vit)) ;
} while(vit != d2) ;
cur = edges.begin() ; // set the current edge to the first one
}
template <typename PFP>
void EdgeSelector_QEM<PFP>::initEdgeInfo(Dart d)
{
MAP& m = this->m_map ;
EdgeInfo einfo ;
if(m.edgeCanCollapse(d))
computeEdgeInfo(d, einfo) ;
else
einfo.valid = false ;
edgeInfo[d] = einfo ;
}
template <typename PFP>
void EdgeSelector_QEM<PFP>::updateEdgeInfo(Dart d, bool recompute)
{
MAP& m = this->m_map ;
EdgeInfo& einfo = edgeInfo[d] ;
if(recompute)
{
if(einfo.valid)
edges.erase(einfo.it) ; // remove the edge from the multimap
if(m.edgeCanCollapse(d))
computeEdgeInfo(d, einfo) ;
else
einfo.valid = false ;
}
else
{
if(m.edgeCanCollapse(d))
{ // if the edge can be collapsed now
if(!einfo.valid) // but it was not before
computeEdgeInfo(d, einfo) ;
}
else
{ // if the edge cannot be collapsed now
if(einfo.valid) // and it was before
{
edges.erase(einfo.it) ;