diff --git a/Apps/Tuto/tuto_oper3.cpp b/Apps/Tuto/tuto_oper3.cpp index ece4315f9a406ff827dc49e58a2a7765e97a5d6c..86b45f59c49175ce1cffb262509d345f948d159d 100644 --- a/Apps/Tuto/tuto_oper3.cpp +++ b/Apps/Tuto/tuto_oper3.cpp @@ -650,11 +650,14 @@ void MyQT::importMesh(std::string& filename) else { std::cerr << "could not import " << filename << std::endl ; + return ; } m_selected = NIL; m_selected2 = NIL; + m_render_topo->updateData(myMap, position, m_ex1,m_ex2,m_ex3, nb); + bb = Algo::Geometry::computeBoundingBox(myMap, position) ; setParamObject(bb.maxSize(), bb.center().data()) ; m_shift = bb.maxSize()/200.0f; diff --git a/include/Algo/Decimation/edgeSelector.h b/include/Algo/Decimation/edgeSelector.h index ccf91d9d9b5e1409a8156b6203489d9be1aae2c7..15493ea1b0762909a7de273d5cd5131f2ba8faf9 100644 --- a/include/Algo/Decimation/edgeSelector.h +++ b/include/Algo/Decimation/edgeSelector.h @@ -97,7 +97,7 @@ public: {} void updateAfterCollapse(Dart d2, Dart dd2) ; - void updateWithoutCollapse() { } + void updateWithoutCollapse(); } ; template @@ -142,7 +142,7 @@ public: void updateBeforeCollapse(Dart d) ; void updateAfterCollapse(Dart d2, Dart dd2) ; - void updateWithoutCollapse() { } + void updateWithoutCollapse(); } ; template @@ -246,7 +246,7 @@ public: void updateBeforeCollapse(Dart d) ; void updateAfterCollapse(Dart d2, Dart dd2) ; - void updateWithoutCollapse() { } + void updateWithoutCollapse(); } ; template @@ -344,7 +344,7 @@ public: void updateBeforeCollapse(Dart d) ; void updateAfterCollapse(Dart d2, Dart dd2) ; - void updateWithoutCollapse() { } + void updateWithoutCollapse(); } ; template @@ -392,7 +392,7 @@ public: void updateBeforeCollapse(Dart d) ; void updateAfterCollapse(Dart d2, Dart dd2) ; - void updateWithoutCollapse() { } + void updateWithoutCollapse(); } ; /***************************************************************************************************************** diff --git a/include/Algo/Decimation/edgeSelector.hpp b/include/Algo/Decimation/edgeSelector.hpp index b7c88c6fa672bf82b1a0655355825c0570ac7bc8..794747b4f8de4c86dde5a8ec96c1af3c0c0b829f 100644 --- a/include/Algo/Decimation/edgeSelector.hpp +++ b/include/Algo/Decimation/edgeSelector.hpp @@ -69,6 +69,7 @@ void EdgeSelector_MapOrder::updateAfterCollapse(Dart d2, Dart dd2) } } + /************************************************************************************ * RANDOM * ************************************************************************************/ @@ -126,6 +127,22 @@ void EdgeSelector_Random::updateAfterCollapse(Dart d2, Dart dd2) } while(!this->m_select(cur) || !m.edgeCanCollapse(darts[cur])) ; } +template +void EdgeSelector_Random::updateWithoutCollapse() +{ + MAP& m = this->m_map ; + allSkipped = false ; + do + { + ++cur ; + if(cur == darts.size()) + { + cur = 0 ; + allSkipped = true ; + } + } while(!this->m_select(cur) || !m.edgeCanCollapse(darts[cur])) ; +} + /************************************************************************************ * EDGE LENGTH * ************************************************************************************/ @@ -222,6 +239,17 @@ void EdgeSelector_Length::updateAfterCollapse(Dart d2, Dart dd2) cur = edges.begin() ; // set the current edge to the first one } +template +void EdgeSelector_Length::updateWithoutCollapse() +{ + EdgeInfo& einfo = edgeInfo[(*cur).second] ; + einfo.valid = false ; + edges.erase(einfo.it) ; + + //edges.erase(cur) ; + cur = edges.begin(); +} + template void EdgeSelector_Length::initEdgeInfo(Dart d) { @@ -417,6 +445,17 @@ void EdgeSelector_QEM::updateAfterCollapse(Dart d2, Dart dd2) cur = edges.begin() ; // set the current edge to the first one } +template +void EdgeSelector_QEM::updateWithoutCollapse() +{ + EdgeInfo& einfo = edgeInfo[(*cur).second] ; + einfo.valid = false ; + edges.erase(einfo.it) ; + + //edges.erase(cur) ; + cur = edges.begin(); +} + template void EdgeSelector_QEM::initEdgeInfo(Dart d) { @@ -479,18 +518,6 @@ void EdgeSelector_QEM::computeEdgeInfo(Dart d, EdgeInfo& einfo) einfo.valid = true ; } -template -void EdgeSelector_QEM::updateWithoutCollapse() -{ - EdgeInfo& einfo = edgeInfo[(*cur).second] ; - einfo.valid = false ; - edges.erase(einfo.it) ; - - //edges.erase(cur) ; - cur = edges.begin(); -} - - /************************************************************************************ * QUADRIC ERROR METRIC (Memoryless version) * ************************************************************************************/ @@ -660,6 +687,17 @@ void EdgeSelector_QEMml::updateAfterCollapse(Dart d2, Dart dd2) cur = edges.begin() ; // set the current edge to the first one } +template +void EdgeSelector_QEMml::updateWithoutCollapse() +{ + EdgeInfo& einfo = edgeInfo[(*cur).second] ; + einfo.valid = false ; + edges.erase(einfo.it) ; + + //edges.erase(cur) ; + cur = edges.begin(); +} + template void EdgeSelector_QEMml::initEdgeInfo(Dart d) { @@ -839,6 +877,17 @@ void EdgeSelector_Curvature::updateAfterCollapse(Dart d2, Dart dd2) cur = edges.begin() ; // set the current edge to the first one } +template +void EdgeSelector_Curvature::updateWithoutCollapse() +{ + EdgeInfo& einfo = edgeInfo[(*cur).second] ; + einfo.valid = false ; + edges.erase(einfo.it) ; + + //edges.erase(cur) ; + cur = edges.begin(); +} + template void EdgeSelector_Curvature::initEdgeInfo(Dart d) { @@ -1039,6 +1088,17 @@ void EdgeSelector_MinDetail::updateAfterCollapse(Dart d2, Dart dd2) cur = edges.begin() ; // set the current edge to the first one } +template +void EdgeSelector_MinDetail::updateWithoutCollapse() +{ + EdgeInfo& einfo = edgeInfo[(*cur).second] ; + einfo.valid = false ; + edges.erase(einfo.it) ; + + //edges.erase(cur) ; + cur = edges.begin(); +} + template void EdgeSelector_MinDetail::initEdgeInfo(Dart d) { diff --git a/include/Algo/DecimationVolumes/approximator.h b/include/Algo/DecimationVolumes/approximator.h index 92596bb6f8e7c959c5fb69d2697bdb1c8ff88d36..21c47fa669f81c4821567005a2dd524bc7cb190e 100644 --- a/include/Algo/DecimationVolumes/approximator.h +++ b/include/Algo/DecimationVolumes/approximator.h @@ -39,7 +39,8 @@ namespace DecimationVolumes enum ApproximatorType { - A_QEM + A_QEM, + A_MidEdge }; template @@ -61,12 +62,10 @@ public: virtual const std::string& getApproximatedAttributeName() const = 0 ; virtual ApproximatorType getType() const = 0 ; virtual bool init() = 0 ; + virtual void approximate(Dart d) = 0 ; + virtual void saveApprox(Dart d) = 0 ; + virtual void affectApprox(Dart d) = 0 ; virtual const PredictorGen* getPredictor() const = 0 ; - virtual void approximate(Operator* op) = 0 ; - virtual void saveApprox(Operator* op) = 0 ; - virtual void affectApprox(Operator* op) = 0 ; - - virtual void approximate(Dart d) = 0; } ; @@ -123,46 +122,21 @@ public: return m_approx[d] ; } - const Predictor* getPredictor() const + void saveApprox(Dart d) { - return m_predictor ; + m_app = m_approx[d] ; } - const T& getDetail(Dart d) const + void affectApprox(Dart d) { - assert(m_predictor || !"Trying to get detail on a non-predictive scheme") ; - return m_detail[d] ; + m_attrV[d] = m_app ; } - 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* op) - { - Dart d = op->getEdge(); - m_app = m_approx[d]; - } - virtual void affectApprox(Operator* op) + const Predictor* getPredictor() const { - Dart d = op->getEdge(); - m_attrV[d] = m_app; + return m_predictor ; } - - // void saveApprox(Dart d) - // { - // m_app = m_approx[d] ; - // } - // - // void affectApprox(Dart d) - // { - // m_attrV[d] = m_app ; - // } - - }; diff --git a/include/Algo/DecimationVolumes/decimator.hpp b/include/Algo/DecimationVolumes/decimator.hpp index 47cf97ecb356ea47f67332c2fe4c9bfc35e8b3d5..d8596b5243935ab6dad6ac9567b2defe4140624c 100644 --- a/include/Algo/DecimationVolumes/decimator.hpp +++ b/include/Algo/DecimationVolumes/decimator.hpp @@ -38,13 +38,13 @@ void decimate( ) { std::vector*> approximators ; - EdgeSelector* selector = NULL ; + Selector* selector = NULL ; //choose the Approximator switch(a) { - case A_QEM : - approximators.push_back(new Approximator_QEM(map, position)) ; + case A_MidEdge : + approximators.push_back(new Approximator_MidEdge(map, position)) ; break ; default : CGoGNout << "not yet implemented" << CGoGNendl; @@ -54,8 +54,11 @@ void decimate( //choose the Selector switch(s) { - case S_QEM : - selector = new EdgeSelector_QEM(map, position, approximators, selected) ; + case S_MapOrder : + selector = new Algo::DecimationVolumes::EdgeSelector_MapOrder(map, position, approximators, selected) ; + break ; + case S_Random : + selector = new Algo::DecimationVolumes::EdgeSelector_Random(map, position, approximators, selected) ; break ; default: CGoGNout << "not yet implemented" << CGoGNendl; @@ -78,42 +81,38 @@ void decimate( while(!finished) { - //Next Operator to perform - Operator *op; + if(!selector->nextEdge(d)) + break ; - if((op = selector->nextOperator()) == NULL) - break; + std::cout << "d = " << d << std::endl; + + --nbVertices ; + + Dart d2 = map.phi2(map.phi_1(d)) ; + Dart dd2 = map.phi2(map.phi_1(map.phi2(d))) ; - // compute approximated attributes for(typename std::vector*>::iterator it = approximators.begin(); it != approximators.end(); ++it) { - (*it)->approximate(op) ; - (*it)->saveApprox(op) ; + (*it)->approximate(d) ; // compute approximated attributes + (*it)->saveApprox(d) ; } - //Update the selector before performing operation - if(!selector->updateBeforeOperation(op)) - break; + selector->updateBeforeCollapse(d) ; // update selector + + map.collapseEdge(d) ; // collapse edge - //Perform the topological operation and - //compute the number of resulting cells - nbVertices -= op->collapse(map, position); + if(!map.check()) + finished = true; for(typename std::vector*>::iterator it = approximators.begin(); it != approximators.end(); ++it) - (*it)->affectApprox(op); // affect data to the resulting vertex + (*it)->affectApprox(d2); // affect data to the resulting vertex - //Update the embedded position and - //search the next operation to perform - selector->updateAfterOperation(op); + selector->updateAfterCollapse(d2, dd2) ;// update selector if(nbVertices <= nbWantedVertices) finished = true ; - - delete op; } - selector->finish() ; - CGoGNout << "..done (" << nbVertices << " vertices)" << CGoGNendl ; delete selector ; diff --git a/include/Algo/DecimationVolumes/edgeSelector.h b/include/Algo/DecimationVolumes/edgeSelector.h index 12a7138ccfbdb2dcf7a708c1390f2fb182db280c..729dd455ea7801eefed52f4d8bbcd824aecbbdad 100644 --- a/include/Algo/DecimationVolumes/edgeSelector.h +++ b/include/Algo/DecimationVolumes/edgeSelector.h @@ -3,7 +3,6 @@ #include "Container/fakeAttribute.h" #include "Algo/DecimationVolumes/selector.h" -#include "Algo/DecimationVolumes/operator.h" #include "Utils/qem.h" #include "Topology/generic/traversorCell.h" @@ -16,80 +15,166 @@ namespace Algo namespace DecimationVolumes { -/******************************************************************************** - * Parent Edge Selector * - ********************************************************************************/ +/* + * Map Order + */ template -class EdgeSelector : public Selector +class EdgeSelector_MapOrder : public Selector { public: typedef typename PFP::MAP MAP ; typedef typename PFP::VEC3 VEC3 ; - typedef typename PFP::REAL REAL; - -protected: + typedef typename PFP::REAL REAL ; +private: + Dart cur ; public: - EdgeSelector(MAP& m, VertexAttribute& pos, std::vector*>& approx, const FunctorSelect& select) : + EdgeSelector_MapOrder(MAP& m, VertexAttribute& pos, std::vector*>& approx, const FunctorSelect& select) : Selector(m, pos, approx, select) {} + ~EdgeSelector_MapOrder() + {} + SelectorType getType() { return S_MapOrder ; } + bool init() ; + bool nextEdge(Dart& d) ; + void updateBeforeCollapse(Dart d) + {} + void updateAfterCollapse(Dart d2, Dart dd2) ; + + void updateWithoutCollapse() { } +} ; -}; +/* + * Random + */ template -class EdgeSelector_QEM : public EdgeSelector +class EdgeSelector_Random : public Selector { public: - typedef typename PFP::MAP MAP; - typedef typename PFP::VEC3 VEC3; - typedef typename PFP::REAL REAL; + typedef typename PFP::MAP MAP ; + typedef typename PFP::VEC3 VEC3 ; + typedef typename PFP::REAL REAL ; private: - typedef struct - { - typename std::multimap::iterator it; - bool valid; - static std::string CGoGNnameOfType() { return "QEMedgeInfo" ; } - } QEMedgeInfo; + std::vector darts ; + unsigned int cur ; + bool allSkipped ; + +public: + EdgeSelector_Random(MAP& m, VertexAttribute& pos, std::vector*>& approx, const FunctorSelect& select) : + Selector(m, pos, approx, select), + cur(0), + allSkipped(false) + {} + ~EdgeSelector_Random() + {} + SelectorType getType() { return S_Random ; } + bool init() ; + bool nextEdge(Dart& d) ; + void updateBeforeCollapse(Dart d2) + {} + void updateAfterCollapse(Dart d2, Dart dd2) ; - typedef NoMathIOAttribute EdgeInfo; + void updateWithoutCollapse() { } +} ; - EdgeAttribute edgeInfo; - VertexAttribute > quadric; - Quadric tmpQ; +/* + * Edge Length + */ +template +class EdgeSelector_Length : public Selector +{ +public: + typedef typename PFP::MAP MAP ; + typedef typename PFP::VEC3 VEC3 ; + typedef typename PFP::REAL REAL ; + +private: + typedef struct + { + typename std::multimap::iterator it ; + bool valid ; + static std::string CGoGNnameOfType() { return "LengthEdgeInfo" ; } + } LengthEdgeInfo ; + typedef NoMathIOAttribute EdgeInfo ; - std::multimap edges; - typename std::multimap::iterator cur; + EdgeAttribute edgeInfo ; - Approximator* m_positionApproximator; + std::multimap edges ; + typename std::multimap::iterator cur ; - void initEdgeInfo(Dart d); - void updateEdgeInfo(Dart d, bool recompute); - void computeEdgeInfo(Dart d, EdgeInfo& einfo); + void initEdgeInfo(Dart d) ; + void updateEdgeInfo(Dart d, bool recompute) ; + void computeEdgeInfo(Dart d, EdgeInfo& einfo) ; public: - EdgeSelector_QEM(MAP& m, VertexAttribute& pos, - std::vector* >& approx, const FunctorSelect& select) : - EdgeSelector(m, pos, approx, select) + EdgeSelector_Length(MAP& m, VertexAttribute& pos, std::vector*>& approx, const FunctorSelect& select) : + Selector(m, pos, approx, select) { - edgeInfo = m.template addAttribute("edgeInfo"); - quadric = m.template addAttribute, VERTEX>("QEMquadric"); + edgeInfo = m.template addAttribute("edgeInfo") ; } - - ~EdgeSelector_QEM() + ~EdgeSelector_Length() { - this->m_map.removeAttribute(quadric); - this->m_map.removeAttribute(edgeInfo); + this->m_map.removeAttribute(edgeInfo) ; } + SelectorType getType() { return S_EdgeLength ; } + bool init() ; + bool nextEdge(Dart& d) ; + void updateBeforeCollapse(Dart d) ; + void updateAfterCollapse(Dart d2, Dart dd2) ; + + void updateWithoutCollapse() { } +} ; + + +/* + * Progressive Tetrahedralizations [SG98] + * Oliver Staadt && Markus Gross + */ +template +class EdgeSelector_SG98 : public Selector +{ +public: + typedef typename PFP::MAP MAP ; + typedef typename PFP::VEC3 VEC3 ; + typedef typename PFP::REAL REAL ; - SelectorType getType() { return S_QEM; } - bool init(); - Operator* nextOperator(); - bool updateBeforeOperation(Operator* op); - void updateAfterOperation(Operator* op); - void finish() { } -}; +private: + typedef struct + { + typename std::multimap::iterator it ; + bool valid ; + static std::string CGoGNnameOfType() { return "SG98edgeInfo" ; } + } SG98edgeInfo ; + typedef NoMathIOAttribute EdgeInfo ; + + EdgeAttribute edgeInfo ; + + std::multimap edges ; + typename std::multimap::iterator cur ; + + Approximator* m_positionApproximator ; + + void initEdgeInfo(Dart d) ; + void updateEdgeInfo(Dart d, bool recompute) ; + void computeEdgeInfo(Dart d, EdgeInfo& einfo) ; + +public: + EdgeSelector_SG98(MAP& m, VertexAttribute& pos, std::vector*>& approx, const FunctorSelect& select) : + Selector(m, pos, approx, select) + {} + ~EdgeSelector_SG98() + {} + SelectorType getType() { return S_SG98 ; } + bool init() ; + bool nextEdge(Dart& d) ; + void updateBeforeCollapse(Dart d); + void updateAfterCollapse(Dart d2, Dart dd2) ; + + void updateWithoutCollapse() { } +} ; diff --git a/include/Algo/DecimationVolumes/edgeSelector.hpp b/include/Algo/DecimationVolumes/edgeSelector.hpp index 6025e76cb7b5ad89948aad2b8b97d9b6061e547f..00da08420938f997300bdfdcb65f92a676dff4fc 100644 --- a/include/Algo/DecimationVolumes/edgeSelector.hpp +++ b/include/Algo/DecimationVolumes/edgeSelector.hpp @@ -33,21 +33,117 @@ namespace Algo namespace DecimationVolumes { +/************************************************************************************ + * MAP ORDER * + ************************************************************************************/ + +template +bool EdgeSelector_MapOrder::init() +{ + MAP& m = this->m_map ; + cur = m.begin() ; + while(!this->m_select(cur) || !m.edgeCanCollapse(cur)) + { + m.next(cur) ; + if(cur == m.end()) + return false; + } + return true ; +} + +template +bool EdgeSelector_MapOrder::nextEdge(Dart& d) +{ + MAP& m = this->m_map ; + if(cur == m.end()) + return false ; + d = cur ; + return true ; +} + +template +void EdgeSelector_MapOrder::updateAfterCollapse(Dart d2, Dart dd2) +{ + MAP& m = this->m_map ; + cur = m.begin() ; + while(!this->m_select(cur) || !m.edgeCanCollapse(cur)) + { + m.next(cur) ; + if(cur == m.end()) + break ; + } +} /************************************************************************************ - * QUADRIC ERROR METRIC * + * RANDOM * ************************************************************************************/ +template +bool EdgeSelector_Random::init() +{ + MAP& m = this->m_map ; + + darts.reserve(m.getNbDarts()) ; + darts.clear() ; + + for(Dart d = m.begin(); d != m.end(); m.next(d)) + darts.push_back(d) ; + + srand(time(NULL)) ; + int remains = darts.size() ; + for(unsigned int i = 0; i < darts.size()-1; ++i) // generate the random permutation + { + int r = (rand() % remains) + i ; + // swap ith and rth elements + Dart tmp = darts[i] ; + darts[i] = darts[r] ; + darts[r] = tmp ; + --remains ; + } + + cur = 0 ; + allSkipped = true ; + + return true ; +} template -bool EdgeSelector_QEM::init() +bool EdgeSelector_Random::nextEdge(Dart& d) +{ + if(cur == darts.size() && allSkipped) + return false ; + d = darts[cur] ; + return true ; +} + + +template +void EdgeSelector_Random::updateAfterCollapse(Dart d2, Dart dd2) +{ + MAP& m = this->m_map ; + allSkipped = false ; + do + { + ++cur ; + if(cur == darts.size()) + { + cur = 0 ; + allSkipped = true ; + } + } while(!this->m_select(cur) || !m.edgeCanCollapse(darts[cur])) ; +} + +/************************************************************************************ + * SG98 * + ************************************************************************************/ +template +bool EdgeSelector_SG98::init() { MAP& m = this->m_map ; - //searching the Geometry Approximator bool ok = false ; for(typename std::vector*>::iterator it = this->m_approximators.begin(); - it != this->m_approximators.end() && !ok; - ++it) + it != this->m_approximators.end() && !ok; + ++it) { if((*it)->getApproximatedAttributeName() == "position") { @@ -59,135 +155,58 @@ bool EdgeSelector_QEM::init() if(!ok) return false ; - // init the Quadric error metric for cells - edges.clear(); - TraversorV travV(m); - for(Dart dit = travV.begin() ; dit != travV.end() ; dit = travV.next()) - { - //create one quadric per vertex - Quadric q; - quadric[dit] = q; - } + edges.clear() ; - // init the quadric for each boundary triangle - TraversorF 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 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 travE(m); - for(Dart dit = travE.begin() ; dit != travE.end() ; dit = travE.next()) + TraversorE tE(m); + for(Dart dit = tE.begin() ; dit != tE.end() ; dit = tE.next()) { initEdgeInfo(dit); } - // init the current edge to the first one cur = edges.begin(); return true; } template -Operator* EdgeSelector_QEM::nextOperator() +bool EdgeSelector_SG98::nextEdge(Dart& d) { - MAP& m = this->m_map ; - Operator* op = NULL; - - if(cur != edges.end() && !edges.empty()) - { - op = new CollapseEdgeOperator((*cur).second); - - op->setFirstIncidentEdge(m.phi2(m.phi_1((*cur).second))); - op->setSecondIncidentEdge(m.phi2(m.phi_1(m.phi2((*cur).second)))); - } - - return op ; + if(cur == edges.end() || edges.empty()) + return false ; + d = (*cur).second ; + return true ; } template -bool EdgeSelector_QEM::updateBeforeOperation(Operator* op) +void EdgeSelector_SG98::updateBeforeCollapse(Dart d) { MAP& m = this->m_map ; - Dart d = op->getEdge(); - - EdgeInfo& edgeE = edgeInfo[d] ; - if(edgeE.valid) - edges.erase(edgeE.it) ; - edgeE = edgeInfo[m.phi1(d)] ; - if(edgeE.valid) // remove all - edges.erase(edgeE.it) ; + // remove all + // the concerned edges + // from the multimap - 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) - { - 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; } template -void EdgeSelector_QEM::updateAfterOperation(Operator* op) +void EdgeSelector_SG98::updateAfterCollapse(Dart d2, Dart dd2) { 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) ; + // must recompute some edge infos in the - vit = m.phi2(m.phi_1(vit)) ; - } while(vit != d2) ; + // various optimizations are applied here by + // treating differently : + // - edges for which the criteria must be recomputed + // - edges that must be re-embedded + // - edges for which only the collapsibility must be re-tested cur = edges.begin() ; // set the current edge to the first one - } template -void EdgeSelector_QEM::initEdgeInfo(Dart d) +void EdgeSelector_SG98::initEdgeInfo(Dart d) { MAP& m = this->m_map ; EdgeInfo einfo ; @@ -199,11 +218,10 @@ void EdgeSelector_QEM::initEdgeInfo(Dart d) } template -void EdgeSelector_QEM::updateEdgeInfo(Dart d, bool recompute) +void EdgeSelector_SG98::updateEdgeInfo(Dart d, bool recompute) { MAP& m = this->m_map ; EdgeInfo& einfo = edgeInfo[d] ; - if(recompute) { if(einfo.valid) @@ -232,26 +250,23 @@ void EdgeSelector_QEM::updateEdgeInfo(Dart d, bool recompute) } template -void EdgeSelector_QEM::computeEdgeInfo(Dart d, EdgeInfo& einfo) +void EdgeSelector_SG98::computeEdgeInfo(Dart d, EdgeInfo& einfo) { MAP& m = this->m_map ; Dart dd = m.phi2(d) ; - Quadric quad ; - quad += quadric[d] ; // compute the sum of the - quad += quadric[dd] ; // two vertices quadrics - - m_positionApproximator->approximate(d) ; - - REAL err = std::max(REAL(0),REAL(quad(m_positionApproximator->getApprox(d)))) ; - - einfo.it = edges.insert(std::make_pair(err, d)) ; - einfo.valid = true ; +// Quadric quad ; +// quad += quadric[d] ; // compute the sum of the +// quad += quadric[dd] ; // two vertices quadrics +// +// m_positionApproximator->approximate(d) ; +// +// REAL err = quad(m_positionApproximator->getApprox(d)) ; +// +// einfo.it = edges.insert(std::make_pair(err, d)) ; +// einfo.valid = true ; } - - - } //end namespace DecimationVolumique } //end namespace Algo } //end namespace CGoGN diff --git a/include/Algo/DecimationVolumes/geometryApproximator.h b/include/Algo/DecimationVolumes/geometryApproximator.h index 48dd04ceaa1e4076f784d347a161fd0eab9798f7..1bb1eefdb86e46b113a80a03bd8f09313c57e90d 100644 --- a/include/Algo/DecimationVolumes/geometryApproximator.h +++ b/include/Algo/DecimationVolumes/geometryApproximator.h @@ -37,26 +37,21 @@ namespace DecimationVolumes { template -class Approximator_QEM : public Approximator +class Approximator_MidEdge : public Approximator { public: typedef typename PFP::MAP MAP ; typedef typename PFP::VEC3 VEC3 ; typedef typename PFP::REAL REAL ; -protected: - VertexAttribute > m_quadric ; - -public: - Approximator_QEM(MAP& m, VertexAttribute& pos, Predictor* pred = NULL) : + Approximator_MidEdge(MAP& m, VertexAttribute& pos, Predictor* pred = NULL) : Approximator(m, pos, pred) {} - ~Approximator_QEM() + ~Approximator_MidEdge() {} - ApproximatorType getType() const { return A_QEM ; } + ApproximatorType getType() const { return A_MidEdge ; } bool init() ; - void approximate(Operator *op); - void approximate(Dart d); + void approximate(Dart d) ; } ; } //namespace DecimationVolumes diff --git a/include/Algo/DecimationVolumes/geometryApproximator.hpp b/include/Algo/DecimationVolumes/geometryApproximator.hpp index c1bb93ec944f81ac8fc91c331edfa214311e74bc..363ddb1743792c746dca6ef21e06550a0be7fa0c 100644 --- a/include/Algo/DecimationVolumes/geometryApproximator.hpp +++ b/include/Algo/DecimationVolumes/geometryApproximator.hpp @@ -35,86 +35,35 @@ namespace DecimationVolumes { /************************************************************************************ - * QUADRIC ERROR METRIC * + * MID EDGE * ************************************************************************************/ template -bool Approximator_QEM::init() +bool Approximator_MidEdge::init() { - m_quadric = this->m_map.template getAttribute, VERTEX>("QEMquadric") ; - - if(this->m_predictor) - { - return false ; - } return true ; } template -void Approximator_QEM::approximate(Operator *op) -{ - Dart d = op->getEdge(); - approximate(d); -} - -template -void Approximator_QEM::approximate(Dart d) +void Approximator_MidEdge::approximate(Dart d) { MAP& m = this->m_map ; // get some darts Dart dd = m.phi2(d) ; - Quadric q1, q2 ; - if(!m_quadric.isValid()) // if the selector is not QEM, compute local error quadrics - { - // compute the error quadric associated to v1 - Dart it = d ; - do - { - Quadric q(this->m_attrV[it], this->m_attrV[m.phi1(it)], this->m_attrV[m.phi_1(it)]) ; - q1 += q ; - it = m.phi2_1(it) ; - } while(it != d) ; - - // compute the error quadric associated to v2 - it = dd ; - do - { - Quadric q(this->m_attrV[it], this->m_attrV[m.phi1(it)], this->m_attrV[m.phi_1(it)]) ; - q2 += q ; - it = m.phi2_1(it) ; - } while(it != dd) ; - } - else // if the selector is QEM, use the error quadrics computed by the selector - { - q1 = m_quadric[d] ; - q2 = m_quadric[dd] ; - } + // get the contracted edge vertices positions + VEC3 v1 = this->m_attrV[d] ; + VEC3 v2 = this->m_attrV[dd] ; - Quadric quad ; - quad += q1 ; // compute the sum of the - quad += q2 ; // two vertices quadrics + // Compute the approximated position + this->m_approx[d] = (v1 + v2) / REAL(2) ; - VEC3 res ; - bool opt = quad.findOptimizedPos(res) ; // try to compute an optimized position for the contraction of this edge - if(!opt) + if(this->m_predictor) { - VEC3 p1 = this->m_attrV[d] ; // let the new vertex lie - VEC3 p2 = this->m_attrV[dd] ; // on either one of the two endpoints - VEC3 p12 = (p1 + p2) / 2.0f ; // or the middle of the edge - REAL e1 = quad(p1) ; - REAL e2 = quad(p2) ; - REAL e12 = quad(p12) ; - REAL minerr = std::min(std::min(e1, e2), e12) ; // consider only the one for - if(minerr == e12) this->m_approx[d] = p12 ; // which the error is minimal - else if(minerr == e1) this->m_approx[d] = p1 ; - else this->m_approx[d] = p2 ; + } - else - this->m_approx[d] = res ; } - } //end namespace DecimationVolumes } //end namespace Algo diff --git a/include/Algo/DecimationVolumes/selector.h b/include/Algo/DecimationVolumes/selector.h index e28dc19beb18e611232dc50781def34ba3183445..adea97d702be6056009b7b9b4429422464d1447a 100644 --- a/include/Algo/DecimationVolumes/selector.h +++ b/include/Algo/DecimationVolumes/selector.h @@ -15,12 +15,15 @@ namespace DecimationVolumes enum SelectorType { + S_MapOrder, + S_Random, + S_EdgeLength, + S_SG98, S_QEM } ; template class ApproximatorGen ; template class Approximator ; -template class Operator ; /******************************************************************************** * Parent Selector * @@ -36,75 +39,25 @@ public: typedef typename PFP::REAL REAL; protected: - /** - * - */ + MAP& m_map ; - /** - * - */ VertexAttribute& m_position ; -// /** -// * -// */ -// OperatorType nextOp; - /** - * need a pointer to the current approximator if the current selector needs - * the future result of a collapse to estimate its cost - */ std::vector*>& m_approximators ; - const FunctorSelect& m_select ; public: Selector(MAP& m, VertexAttribute& pos, std::vector*>& approx, const FunctorSelect& select) : m_map(m), m_position(pos), m_approximators(approx), m_select(select) {} - virtual ~Selector() {} - - /** - * Return the type of the selector - * @return the type of the selector - */ virtual SelectorType getType() = 0 ; - -// /** -// * -// */ -// virtual Dart nextCell() = 0; - - /** - * - */ virtual bool init() = 0 ; + virtual bool nextEdge(Dart& d) = 0 ; + virtual void updateBeforeCollapse(Dart d) = 0 ; + virtual void updateAfterCollapse(Dart d2, Dart dd2) = 0 ; - /** - * - */ - virtual Operator* nextOperator() = 0 ; - - /** - * - */ - virtual bool updateBeforeOperation(Operator* op) = 0 ; - - /** - * - */ - virtual void updateAfterOperation(Operator* op) = 0 ; - - /** - * - */ - virtual void finish() = 0 ; - -// /** -// * -// */ -// OperatorType nextOperatorType() { return nextOp; } - + virtual void updateWithoutCollapse() = 0; }; } //end namespace DecimationVolumes diff --git a/include/Algo/Multiresolution/Map2MR/Filters/catmullClark.h b/include/Algo/Multiresolution/Map2MR/Filters/catmullClark.h new file mode 100644 index 0000000000000000000000000000000000000000..30f98f41b0d757ec8e02a5c2458def51d2f7bbbe --- /dev/null +++ b/include/Algo/Multiresolution/Map2MR/Filters/catmullClark.h @@ -0,0 +1,455 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* version 0.1 * +* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef __MR_CC_FILTER__ +#define __MR_CC_FILTER__ + +#include +#include "Algo/Multiresolution/filter.h" + +namespace CGoGN +{ + +namespace Algo +{ + +namespace MR +{ + +namespace Primal +{ + +namespace Filters +{ + +/* + @article {springerlink:10.1007/s00371-006-0074-7, + author = {Wang, Huawei and Qin, Kaihuai and Tang, Kai}, + affiliation = {Hong Kong University of Science & Technology Department of Mechanical Engineering Hong Kong China}, + title = {Efficient wavelet construction with Catmull–Clark subdivision}, + journal = {The Visual Computer}, + publisher = {Springer Berlin / Heidelberg}, + issn = {0178-2789}, + keyword = {Computer Science}, + pages = {874-884}, + volume = {22}, + issue = {9}, + url = {http://dx.doi.org/10.1007/s00371-006-0074-7}, + note = {10.1007/s00371-006-0074-7}, + year = {2006} + } +*/ + +/********************************************************************************* + * Lazy Wavelet + *********************************************************************************/ +template +class CCInitEdgeSynthesisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + bool first; + +public: + CCInitEdgeSynthesisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p), first(true) + {} + + void operator() () + { + if(first) + { + TraversorE trav(m_map) ; + for (Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + m_map.incCurrentLevel() ; + m_position[m_map.phi1(d)] = typename PFP::VEC3(0.0); + m_map.decCurrentLevel() ; + } + first = false; + } + } +} ; + +template +class CCInitFaceSynthesisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + bool first; + +public: + CCInitFaceSynthesisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p), first(true) + {} + + void operator() () + { + if(first) + { + TraversorF trav(m_map) ; + for (Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + m_map.incCurrentLevel() ; + m_position[m_map.phi2(m_map.phi1(d))] = typename PFP::VEC3(0.0); // ou phi2(d) + m_map.decCurrentLevel() ; + } + first = false; + } + } +} ; + +template +class CCEdgeSynthesisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + +public: + CCEdgeSynthesisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p) + {} + + void operator() () + { + TraversorE trav(m_map) ; + for (Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + typename PFP::VEC3 ei = (m_position[d] + m_position[m_map.phi1(d)]) * typename PFP::REAL(0.5); + + m_map.incCurrentLevel() ; + Dart midV = m_map.phi1(d) ; + m_position[midV] += ei ; + m_map.decCurrentLevel() ; + } + } +} ; + +template +class CCFaceSynthesisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + +public: + CCFaceSynthesisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p) + {} + + void operator() () + { + TraversorF trav(m_map) ; + for (Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + float u = 1.0/2.0; + + typename PFP::VEC3 v(0.0); + typename PFP::VEC3 e(0.0); + unsigned int degree = 0; + + Dart dit = d; + do + { + v += m_position[dit]; + + m_map.incCurrentLevel() ; + e += m_position[m_map.phi1(dit)]; + m_map.decCurrentLevel() ; + + ++degree; + + dit = m_map.phi1(dit); + } + while(dit != d); + + v *= (1.0 - u) / degree; + e *= u / degree; + + m_map.incCurrentLevel() ; + m_position[m_map.phi2(m_map.phi1(d))] += v + e ; + m_map.decCurrentLevel() ; + } + + } +} ; + +template +class CCVertexSynthesisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + +public: + CCVertexSynthesisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p) + {} + + void operator() () + { + TraversorV trav(m_map) ; + for (Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + typename PFP::VEC3 np1(0) ; + typename PFP::VEC3 np2(0) ; + unsigned int degree1 = 0 ; + unsigned int degree2 = 0 ; + Dart it = d ; + do + { + ++degree1 ; + Dart dd = m_map.phi1(it) ; + np1 += m_position[dd] ; + Dart end = m_map.phi_1(it) ; + dd = m_map.phi1(dd) ; + do + { + ++degree2 ; + np2 += m_position[dd] ; + dd = m_map.phi1(dd) ; + } while(dd != end) ; + it = m_map.alpha1(it) ; + } while(it != d) ; + + float beta = 3.0 / (2.0 * degree1) ; + float gamma = 1.0 / (4.0 * degree2) ; + np1 *= beta / degree1 ; + np2 *= gamma / degree2 ; + + typename PFP::VEC3 vp = m_position[d] ; + vp *= 1.0 - beta - gamma ; + + m_map.incCurrentLevel() ; + m_position[d] = np1 + np2 + vp ; + m_map.decCurrentLevel() ; + } + } +} ; + +template +class CCScalingSynthesisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + +public: + CCScalingSynthesisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p) + {} + + void operator() () + { + TraversorE trav(m_map) ; + for (Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + m_map.incCurrentLevel() ; + + typename PFP::VEC3 ei = m_position[m_map.phi1(d)]; + + typename PFP::VEC3 f = m_position[m_map.phi2(m_map.phi1(d))]; + f += m_position[m_map.phi_1(m_map.phi2(d))]; + f *= 1.0 / 2.0; + + ei += f; + ei *= 1.0 / 2.0; + + m_position[m_map.phi1(d)] = ei; + m_map.decCurrentLevel() ; + } + } +} ; + +template +class CCScalingAnalysisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + +public: + CCScalingAnalysisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p) + {} + + void operator() () + { + TraversorE trav(m_map) ; + for (Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + m_map.incCurrentLevel() ; + + typename PFP::VEC3 ei = m_position[m_map.phi1(d)]; + + typename PFP::VEC3 f = m_position[m_map.phi2(m_map.phi1(d))]; + f += m_position[m_map.phi_1(m_map.phi2(d))]; + f *= 1.0 / 2.0; + + ei *= 2.0; + ei -= f; + + m_position[m_map.phi1(d)] = ei; + m_map.decCurrentLevel() ; + } + } +} ; + +template +class CCVertexAnalysisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + +public: + CCVertexAnalysisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p) + {} + + void operator() () + { + TraversorV trav(m_map) ; + for (Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + m_map.incCurrentLevel() ; + typename PFP::VEC3 np1(0) ; + typename PFP::VEC3 np2(0) ; + unsigned int degree1 = 0 ; + unsigned int degree2 = 0 ; + Dart it = d ; + do + { + ++degree1 ; + Dart dd = m_map.phi1(it) ; + np1 += m_position[dd] ; + Dart end = m_map.phi_1(it) ; + dd = m_map.phi1(dd) ; + do + { + ++degree2 ; + np2 += m_position[dd] ; + dd = m_map.phi1(dd) ; + } while(dd != end) ; + it = m_map.alpha1(it) ; + } while(it != d) ; + + float beta = 3.0 / (2.0 * degree1) ; + float gamma = 1.0 / (4.0 * degree2) ; + np1 *= beta / degree1 ; + np2 *= gamma / degree2 ; + + typename PFP::VEC3 vd = m_position[d] ; + + m_map.decCurrentLevel() ; + + m_position[d] = vd - np1 - np2; + m_position[d] /= 1.0 - beta - gamma ; + + } + } +} ; + +template +class CCFaceAnalysisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + +public: + CCFaceAnalysisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p) + {} + + void operator() () + { + TraversorF trav(m_map) ; + for (Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + + float u = 1.0/2.0; + + typename PFP::VEC3 v(0.0); + typename PFP::VEC3 e(0.0); + unsigned int degree = 0; + + Dart dit = d; + do + { + v += m_position[dit]; + + m_map.incCurrentLevel() ; + e += m_position[m_map.phi1(dit)]; + m_map.decCurrentLevel() ; + + ++degree; + + dit = m_map.phi1(dit); + } + while(dit != d); + + v *= (1.0 - u) / degree; + e *= u / degree; + + m_map.incCurrentLevel() ; + m_position[m_map.phi2(m_map.phi1(d))] -= v - e ; + m_map.decCurrentLevel() ; + } + + } +} ; + +template +class CCEdgeAnalysisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + +public: + CCEdgeAnalysisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p) + {} + + void operator() () + { + TraversorE trav(m_map) ; + for (Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + typename PFP::VEC3 ei = (m_position[d] + m_position[m_map.phi1(d)]) * typename PFP::REAL(0.5); + + m_map.incCurrentLevel() ; + Dart midV = m_map.phi1(d) ; + m_position[midV] -= ei ; + m_map.decCurrentLevel() ; + } + } +} ; + +} // namespace Filters + +} // namespace Primal + +} // namespace MR + +} // namespace Algo + +} // namespace CGoGN + +#endif + diff --git a/include/Algo/Multiresolution/Map2MR/Filters/sqrt2.h b/include/Algo/Multiresolution/Map2MR/Filters/sqrt2.h new file mode 100644 index 0000000000000000000000000000000000000000..1690213a1de80a7137109c87a596f63eceba6a21 --- /dev/null +++ b/include/Algo/Multiresolution/Map2MR/Filters/sqrt2.h @@ -0,0 +1,97 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* version 0.1 * +* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef __MR_SQRT2_FILTER__ +#define __MR_SQRT2_FILTER__ + +#include +#include "Algo/Multiresolution/filter.h" + +namespace CGoGN +{ + +namespace Algo +{ + +namespace MR +{ + +namespace Primal +{ + +namespace Filters +{ + +/********************************************************************************* + * SYNTHESIS FILTERS + *********************************************************************************/ + + +template +class Sqrt2FaceSynthesisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + +public: + Sqrt2FaceSynthesisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p) + {} + + void operator() () + { + TraversorF trav(m_map) ; + for (Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + typename PFP::VEC3 p = Algo::Geometry::faceCentroid(m_map, d, m_position); + + m_map.incCurrentLevel() ; + + Dart midF = m_map.phi2(d); + if(m_map.isBoundaryEdge(d)) + { + midF = m_map.phi1(m_map.phi2(m_map.phi_1(d))); + } + + m_position[midF] = p ; + + m_map.decCurrentLevel() ; + + } + } +} ; + + +} // namespace Filters + +} // namespace Primal + +} // namespace MR + +} // namespace Algo + +} // namespace CGoGN + +#endif + diff --git a/include/Algo/Multiresolution/Map2MR/Filters/sqrt3.h b/include/Algo/Multiresolution/Map2MR/Filters/sqrt3.h new file mode 100644 index 0000000000000000000000000000000000000000..026206588c0f93efb54a24bf7cf5dbe952709444 --- /dev/null +++ b/include/Algo/Multiresolution/Map2MR/Filters/sqrt3.h @@ -0,0 +1,324 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* version 0.1 * +* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef __MR_SQRT3_FILTER__ +#define __MR_SQRT3_FILTER__ + +#include +#include "Algo/Multiresolution/filter.h" + +namespace CGoGN +{ + +namespace Algo +{ + +namespace MR +{ + +namespace Primal +{ + +namespace Filters +{ +/* + @article{10.1109/TVCG.2007.1031, + author = {Huawei Wang and Kaihuai Qin and Hanqiu Sun}, + title = {$\sqrt{3}$-Subdivision-Based Biorthogonal Wavelets}, + journal ={IEEE Transactions on Visualization and Computer Graphics}, + volume = {13}, + issn = {1077-2626}, + year = {2007}, + pages = {914-925}, + doi = {http://doi.ieeecomputersociety.org/10.1109/TVCG.2007.1031}, + publisher = {IEEE Computer Society}, + address = {Los Alamitos, CA, USA}, + } +*/ + +inline double omega12(unsigned int n) +{ + switch(n) + { + case 3: return -0.138438 ; + case 4: return -0.193032 ; + case 5: return -0.216933 ; + case 6: return -0.229537 ; + case 7: return -0.237236 ; + case 8: return -0.242453 ; + case 9: return -0.246257 ; + case 10: return -0.249180 ; + case 15: return -0.257616 ; + case 20: return -0.261843 ; + default: return 0.0; + //find formulation ? + } +} + +inline double omega0(unsigned int n) +{ + switch(n) + { + case 3: return -0.684601 ; + case 4: return -0.403537 ; + case 5: return -0.288813 ; + case 6: return -0.229537 ; + case 7: return -0.193385 ; + case 8: return -0.168740 ; + case 9: return -0.150618 ; + case 10: return -0.136570 ; + case 15: return -0.095201 ; + case 20: return -0.073924 ; + default: return 0.0; + //find formulation ? + } +} + +/********************************************************************************* + * Lazy Wavelet + *********************************************************************************/ + +template +class Sqrt3InitVertexSynthesisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + bool first; + +public: + Sqrt3InitVertexSynthesisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p), first(true) + {} + + void operator() () + { + if(first) + { + TraversorV trav(m_map) ; + for (Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + m_map.incCurrentLevel() ; + m_position[d] = typename PFP::VEC3(0.0); // ou phi2(d) + m_map.decCurrentLevel() ; + } + first = false; + } + } +} ; + +template +class Sqrt3FaceSynthesisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + +public: + Sqrt3FaceSynthesisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p) + {} + + void operator() () + { + TraversorF trav(m_map) ; + for (Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + Dart d1 = m_map.phi1(d) ; + Dart d2 = m_map.phi1(d1) ; + + typename PFP::VEC3 p0 = m_position[d] ; + typename PFP::VEC3 p1 = m_position[d1] ; + typename PFP::VEC3 p2 = m_position[d2] ; + + p0 *= 1.0 / 3.0 ; + p1 *= 1.0 / 3.0 ; + p2 *= 1.0 / 3.0 ; + + m_map.incCurrentLevel() ; + + m_position[m_map.phi2(d)] += p0 + p1 + p2 ; + + m_map.decCurrentLevel() ; + + } + } +} ; + +template +class Sqrt3VertexSynthesisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + +public: + Sqrt3VertexSynthesisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p) + {} + + void operator() () + { + TraversorV trav(m_map) ; + for (Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + typename PFP::VEC3 nf(0) ; + unsigned int degree = 0 ; + + m_map.incCurrentLevel() ; + Dart df = m_map.phi2(m_map.phi1(d)); + + Traversor2VVaE trav(m_map, df) ; + for(Dart it = trav.begin(); it != trav.end(); it = trav.next()) + { + ++degree ; + nf += m_position[it] ; + + } + m_map.decCurrentLevel() ; + + float alpha = 1.0/9.0 * ( 4.0 - 2.0 * cos(2.0 * M_PI / degree)); + float teta = 1 - (3 * alpha) / 2; + float sigma = (3 * alpha) / (2 * degree); + + nf *= sigma; + + typename PFP::VEC3 vp = m_position[d] ; + vp *= teta ; + + m_map.incCurrentLevel() ; + + m_position[df] = vp + nf; + + m_map.decCurrentLevel() ; + + } + } +} ; + +template +class Sqrt3VertexAnalysisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + +public: + Sqrt3VertexAnalysisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p) + {} + + void operator() () + { + TraversorV trav(m_map) ; + for (Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + typename PFP::VEC3 nf(0) ; + unsigned int degree = 0 ; + + m_map.incCurrentLevel() ; + Dart df = m_map.phi2(m_map.phi1(d)); + + Traversor2VVaE trav(m_map, df) ; + for(Dart it = trav.begin(); it != trav.end(); it = trav.next()) + { + ++degree ; + nf += m_position[it] ; + + } + m_map.decCurrentLevel() ; + + float alpha = 1.0/9.0 * ( 4.0 - 2.0 * cos(2.0 * M_PI / degree)); + float teta = 1 - (3 * alpha) / 2; + float sigma = (3 * alpha) / (2 * degree); + + nf *= sigma; + + typename PFP::VEC3 vp = m_position[d] ; + vp -= nf ; + + m_map.incCurrentLevel() ; + + m_position[df] = vp * (1.0 / teta) ; + + m_map.decCurrentLevel() ; + + } + } +} ; + +template +class Sqrt3FaceAnalysisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + +public: + Sqrt3FaceAnalysisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p) + {} + + void operator() () + { + TraversorF trav(m_map) ; + for (Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + Dart d1 = m_map.phi1(d) ; + Dart d2 = m_map.phi1(d1) ; + + typename PFP::VEC3 p0 = m_position[d] ; + typename PFP::VEC3 p1 = m_position[d1] ; + typename PFP::VEC3 p2 = m_position[d2] ; + + p0 *= 1.0 / 3.0 ; + p1 *= 1.0 / 3.0 ; + p2 *= 1.0 / 3.0 ; + + m_map.incCurrentLevel() ; + + m_position[m_map.phi2(d)] -= p0 + p1 + p2 ; + + m_map.decCurrentLevel() ; + + } + } +} ; + +/********************************************************************************* + * Three-Point Orthogonalization + *********************************************************************************/ + + +/********************************************************************************* + * Six-Point Orthogonalization + *********************************************************************************/ + +} // namespace Filters + +} // namespace Primal + +} // namespace MR + +} // namespace Algo + +} // namespace CGoGN + +#endif + diff --git a/include/Algo/Multiresolution/Map2MR/Masks/sqrt3.h b/include/Algo/Multiresolution/Map2MR/Masks/sqrt3.h new file mode 100644 index 0000000000000000000000000000000000000000..f7268717789b542de98a60698d5613516c377952 --- /dev/null +++ b/include/Algo/Multiresolution/Map2MR/Masks/sqrt3.h @@ -0,0 +1,130 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* version 0.1 * +* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef __MR_SQRT3_MASK__ +#define __MR_SQRT3_MASK__ + +#include + +namespace CGoGN +{ + +namespace Algo +{ + +namespace MR +{ + +namespace Primal +{ + +namespace Masks +{ + + +template +class Sqrt3VertexVertexFunctor : public FunctorType +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + +public: + Sqrt3VertexVertexFunctor(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p) + {} + + bool operator() (Dart d) + { + m_map.decCurrentLevel() ; + + typename PFP::VEC3 np(0) ; + unsigned int degree = 0 ; + Traversor2VVaE trav(m_map, d) ; + for(Dart it = trav.begin(); it != trav.end(); it = trav.next()) + { + ++degree ; + np += m_position[it] ; + } + float alpha = 1.0/9.0 * ( 4.0 - 2.0 * cos(2.0 * M_PI / degree)); + np *= alpha / degree ; + + typename PFP::VEC3 vp = m_position[d] ; + vp *= 1.0 - alpha ; + + m_map.incCurrentLevel() ; + + m_position[d] = np + vp ; + + return false ; + } +} ; + +template +class Sqrt3FaceVertexFunctor : public FunctorType +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + +public: + Sqrt3FaceVertexFunctor(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p) + {} + + bool operator() (Dart d) + { + Dart d0 = m_map.phi1(d) ; + + m_map.decCurrentLevel() ; + + Dart d1 = m_map.phi1(d1) ; + Dart d2 = m_map.phi1(d2) ; + + typename PFP::VEC3 p0 = m_position[d0] ; + typename PFP::VEC3 p1 = m_position[d1] ; + typename PFP::VEC3 p2 = m_position[d2] ; + + p0 *= 1.0 / 3.0 ; + p1 *= 1.0 / 3.0 ; + p2 *= 1.0 / 3.0 ; + + m_map.incCurrentLevel() ; + + m_position[d] = p0 + p1 + p2; + + return false ; + } +} ; + +} // namespace Masks + +} // namespace Primal + +} // namespace MR + +} // namespace Algo + +} // namespace CGoGN + +#endif + diff --git a/include/Algo/Multiresolution/Map2MR/lerpAttributes.h b/include/Algo/Multiresolution/Map2MR/lerpAttributes.h new file mode 100644 index 0000000000000000000000000000000000000000..1878de9f4235524b9a07cff99788161b1f864aab --- /dev/null +++ b/include/Algo/Multiresolution/Map2MR/lerpAttributes.h @@ -0,0 +1,245 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* version 0.1 * +* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.unistra.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef __MR_LERPATTRIB_FILTER__ +#define __MR_LERPATTRIB_FILTER__ + +#include +#include "Algo/Multiresolution/filter.h" +#include "Topology/generic/functor.h" + +namespace CGoGN +{ + +namespace Algo +{ + +namespace MR +{ + +/********************************************************************************* + * SYNTHESIS FILTERS + *********************************************************************************/ + +template +class vertexFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_position ; + +public: + vertexFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_position(p) + {} + + void operator() () + { + TraversorV tE(m_map); + for(Dart d = tE.begin() ; d != tE.end() ; d = tE.next()) + { + Dart dit = d; + Dart dres = d; + bool found = false; + do + { + if((m_map.getDartLevel(dit) == (m_map.getCurrentLevel()-1)) && (m_map.getDartLevel(m_map.phi2(dit)) == m_map.getCurrentLevel())) + { + dres = dit; + found = true; + } + + dit = m_map.phi2(m_map.phi_1(dit)); + + }while(!found && dit!=d); + + m_map.template embedOrbit(dres, m_map.template getEmbedding(dres)); + } + +// SelectorEdgeLevel ml(m_map, m_map.getCurrentLevel()); +// +// TraversorV tV(m_map, ml, true); +// for(Dart d = tV.begin() ; d != tV.end() ; d = tV.next()) +// { +// m_map.template embedOrbit(d, m_map.template getEmbedding(d)); +// } + } +}; + +template +class LerpVertexSynthesisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_attrib ; + +public: + LerpVertexSynthesisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_attrib(p) + {} + + void operator() () + { + if(m_attrib.isValid()) + { + TraversorV tE(m_map); + for(Dart d = tE.begin() ; d != tE.end() ; d = tE.next()) + { + Dart dit = d; + Dart dres = d; + bool found = false; + //1ere boucle est-ce qu'il y a un brin de niveau i + + do + { + if((m_map.getDartLevel(dit) < m_map.getCurrentLevel()) && (m_map.getDartLevel(m_map.phi2(dit)) == m_map.getCurrentLevel())) + { + dres = dit; + found = true; + } + + dit = m_map.phi2(m_map.phi_1(dit)); + + }while(!found && dit!=d); + + + if(found) + { + m_map.decCurrentLevel(); + typename PFP::VEC3 c = m_attrib[dres]; + m_map.incCurrentLevel(); + + m_attrib[dres] = c; + } + } + } + } +} ; + + +template +class LerpVertexAnalysisFilter : public Filter +{ +protected: + typename PFP::MAP& m_map ; + VertexAttribute& m_attrib ; + +public: + LerpVertexAnalysisFilter(typename PFP::MAP& m, VertexAttribute& p) : m_map(m), m_attrib(p) + {} + + void operator() () + { + if(m_attrib.isValid()) + { + TraversorV trav(m_map) ; + for (Dart d = trav.begin(); d != trav.end(); d = trav.next()) + { + Dart dit = d; + Dart dres = d; + bool found = false; + + do + { + + m_map.incCurrentLevel(); + Dart d2_1 = m_map.phi2(dit); + m_map.decCurrentLevel(); + + if((m_map.getDartLevel(dit) == m_map.getCurrentLevel()) && m_map.phi2(dit) != d2_1) + { + dres = dit; + found = true; + } + + dit = m_map.phi2(m_map.phi_1(dit)); + + }while(!found && dit!=d); + + if(found) + { + m_map.incCurrentLevel(); + + typename PFP::VEC3 c1 = m_attrib[m_map.phi2(m_map.phi_1(dres))]; + typename PFP::VEC3 c2 = m_attrib[m_map.phi1(m_map.phi2(m_map.phi_1(m_map.phi2(dres))))]; + m_map.decCurrentLevel(); + + m_attrib[dres] = c1 + c2; + m_attrib[dres] /= 2; + } + } + } + } +} ; + +} // namespace MR + +} // namespace Algo + +} // namespace CGoGN + +#endif + +// Dart dit = d; +// Dart ds = d; +// bool found = false; +// //1ere boucle est-ce qu'il y a un brin de niveau i +// do +// { +// if((m_map.getDartLevel(dit) < m_map.getCurrentLevel()) && (m_map.getDartLevel(m_map.phi2(dit)) == m_map.getCurrentLevel())) +// { +// ds = dit; +// found = true; +// } +// +// dit = m_map.phi2(m_map.phi_1(dit)); +// +// }while(!found && dit!=d); +// +// +// if(found) +// { +// bool found2 = false; +// dit = d; +// Dart dres = dit; +// //2e boucle chercher un brin de niveau i-1 +// do +// { +// if(m_map.getDartLevel(dit) < (m_map.getCurrentLevel())) +// { +// if(m_map.getDartLevel(dit) > m_map.getDartLevel(dres)) +// dres = dit; +// +// //found2 = true; +// } +// +// dit = m_map.phi2(m_map.phi_1(dit)); +// +// }while(dit!=d); +// +// //if(!found2) +// // std::cout << "non trouve......." << std::endl; +// +// //if(dres != d) +// m_attrib[ds] = m_attrib[dres]; +// } + diff --git a/include/Algo/Multiresolution/Map2MR/map2MR_PM.h b/include/Algo/Multiresolution/Map2MR/map2MR_PM.h index ed608cc6bc28447b73a4481d2a757db47d3d359e..36b204b067570493fe1eeb74e81b41841b307ccf 100644 --- a/include/Algo/Multiresolution/Map2MR/map2MR_PM.h +++ b/include/Algo/Multiresolution/Map2MR/map2MR_PM.h @@ -37,6 +37,7 @@ #include "Algo/Decimation/geometryPredictor.h" #include "Algo/Decimation/lightfieldApproximator.h" +#include "Algo/Multiresolution/filter.h" namespace CGoGN { @@ -44,7 +45,7 @@ namespace CGoGN namespace Algo { -namespace Multiresolution +namespace MR { template @@ -67,6 +68,9 @@ private: Algo::Decimation::Approximator* m_positionApproximator ; + std::vector synthesisFilters ; + std::vector analysisFilters ; + public: Map2MR_PM(MAP& map, VertexAttribute& position); @@ -86,6 +90,23 @@ public: void refine() ; bool initOk() { return m_initOk; } + + void addSynthesisFilter(Filter* f) { synthesisFilters.push_back(f) ; } + void addAnalysisFilter(Filter* f) { analysisFilters.push_back(f) ; } + + void clearSynthesisFilters() { synthesisFilters.clear() ; } + void clearAnalysisFilters() { analysisFilters.clear() ; } + + /** + * Given the vertex of d in the current level, + * return a dart of from the vertex of the current level + */ + Dart vertexOrigin(Dart d) ; + +// /** +// * Return the level of the vertex of d in the current level map +// */ +// unsigned int vertexLevel(Dart d); } ; } // namespace Multiresolution diff --git a/include/Algo/Multiresolution/Map2MR/map2MR_PM.hpp b/include/Algo/Multiresolution/Map2MR/map2MR_PM.hpp index 90627e2d03a2f5f630a29bddb6e44ed222f6be65..4bd5edef2e0057774890abcaf9ebe79e167837e3 100644 --- a/include/Algo/Multiresolution/Map2MR/map2MR_PM.hpp +++ b/include/Algo/Multiresolution/Map2MR/map2MR_PM.hpp @@ -30,7 +30,7 @@ namespace CGoGN namespace Algo { -namespace Multiresolution +namespace MR { template @@ -133,8 +133,6 @@ void Map2MR_PM::createPM(Algo::Decimation::SelectorType s, Algo::Decimation } - - template void Map2MR_PM::addNewLevel(unsigned int percentWantedVertices) { @@ -220,12 +218,11 @@ void Map2MR_PM::addNewLevel(unsigned int percentWantedVertices) for(std::vector::iterator it = edges.begin() ; it != edges.end() ; ++it) { -// if(*it == Dart(301459)) -// break; - collapseEdge(*it); } } + + //m_map.printMR(); } @@ -240,8 +237,6 @@ void Map2MR_PM::collapseEdge(Dart d) m_map.incDartLevel(m_map.phi_1(m_map.phi2(d))); m_map.incDartLevel(m_map.phi1(m_map.phi2(d))); - //m_map.printMR(); - m_map.duplicateDartAtOneLevel(m_map.phi2(m_map.phi1(d)), 0); m_map.duplicateDartAtOneLevel(m_map.phi2(m_map.phi_1(d)), 0); m_map.duplicateDartAtOneLevel(m_map.phi2(m_map.phi1(m_map.phi2(d))), 0); @@ -254,14 +249,10 @@ void Map2MR_PM::collapseEdge(Dart d) m_map.duplicateDartAtOneLevel(m_map.phi_1(m_map.phi2(d)), 0); m_map.duplicateDartAtOneLevel(m_map.phi1(m_map.phi2(d)), 0); - //m_map.printMR(); - m_map.collapseEdge(d); - - //m_map.printMR(); } - +//analysis template void Map2MR_PM::coarsen() { @@ -269,32 +260,11 @@ void Map2MR_PM::coarsen() m_map.decCurrentLevel() ; - TraversorV tE(m_map); - for(Dart d = tE.begin() ; d != tE.end() ; d = tE.next()) - { - Dart dit = d; - Dart dres = d; - bool found = false; - do - { - //std::cout << "emb["<(dit) << std::endl; - - if(m_map.getDartLevel(dit) == m_map.getCurrentLevel()) - { - dres = dit; - found = true; - } - - dit = m_map.phi2(m_map.phi_1(dit)); - - }while(!found & dit!=d); - - //std::cout << std::endl; - - m_map.template embedOrbit(dres, m_map.template getEmbedding(dres)); - } + for(unsigned int i = 0; i < analysisFilters.size(); ++i) + (*analysisFilters[i])() ; } +//synthesis template void Map2MR_PM::refine() { @@ -302,31 +272,43 @@ void Map2MR_PM::refine() m_map.incCurrentLevel() ; - TraversorV tE(m_map); - for(Dart d = tE.begin() ; d != tE.end() ; d = tE.next()) - { - Dart dit = d; - Dart dres = d; - bool found = false; - do - { - //std::cout << "emb["<(dit) << std::endl; - - if(m_map.getDartLevel(dit) == m_map.getCurrentLevel()) - { - dres = dit; - found = true; - } - - dit = m_map.phi2(m_map.phi_1(dit)); + for(unsigned int i = 0; i < synthesisFilters.size(); ++i) + (*synthesisFilters[i])() ; +} - }while(!found & dit!=d); +template +Dart Map2MR_PM::vertexOrigin(Dart d) +{ +// Dart dit = d; +// do +// { +// if(m_map.getDartLevel(dit) == m_map.currentLevel()) +// return dit; +// +// dit = m_map.phi2(m_map.phi_1(dit)); +// } +// while(dit != d); +} - //std::cout << std::endl; +//template +//unsigned int Map2MR_PM::vertexLevel(Dart d) +//{ +// assert(m_map.getDartLevel(d) <= m_map.getCurrentLevel() || !"edgeLevel : called with a dart inserted after current level") ; +// +// Dart dit = d; +// do +// { +// unsigned int ldit = m_map.getDartLevel(dit) ; +// +// dit = m_map.phi2(m_map.phi_1(dit)); +// } +// while(dit != d); +// +// +// unsigned int ldd = m_map.getDartLevel(m_map.phi2(d)) ; // the level of an edge is the maximum of the +// return ld > ldd ? ld : ldd ; // insertion levels of its two darts +//} - m_map.template embedOrbit(dres, m_map.template getEmbedding(dres)); - } -} } // namespace Multiresolution diff --git a/include/Algo/Multiresolution/Map2MR/map2MR_PrimalRegular.h b/include/Algo/Multiresolution/Map2MR/map2MR_PrimalRegular.h index 8df08ed56d17a8c3c5ff677ef7da3756db9ca952..1976a36e17a3809e22bae05036e2fef2e72f352c 100644 --- a/include/Algo/Multiresolution/Map2MR/map2MR_PrimalRegular.h +++ b/include/Algo/Multiresolution/Map2MR/map2MR_PrimalRegular.h @@ -49,11 +49,8 @@ namespace Regular template class Map2MR { - public: typedef typename PFP::MAP MAP ; - typedef typename PFP::VEC3 VEC3 ; - typedef typename PFP::REAL REAL ; protected: MAP& m_map; @@ -65,11 +62,13 @@ protected: public: Map2MR(MAP& map) ; - + //if true : tri and quad else quad void addNewLevel(bool triQuad = true, bool embedNewVertices = true) ; void addNewLevelSqrt3(bool embedNewVertices = true); + void addNewLevelSqrt2(bool embedNewVertices = true); + void addSynthesisFilter(Filter* f) { synthesisFilters.push_back(f) ; } void addAnalysisFilter(Filter* f) { analysisFilters.push_back(f) ; } diff --git a/include/Algo/Multiresolution/Map2MR/map2MR_PrimalRegular.hpp b/include/Algo/Multiresolution/Map2MR/map2MR_PrimalRegular.hpp index 0514758ee49545713f45724e10c82ef0aa833a1e..0fd4dddddfd74245dcb84c7d54d82e1a13c8b880 100644 --- a/include/Algo/Multiresolution/Map2MR/map2MR_PrimalRegular.hpp +++ b/include/Algo/Multiresolution/Map2MR/map2MR_PrimalRegular.hpp @@ -54,14 +54,6 @@ void Map2MR::addNewLevel(bool triQuad, bool embedNewVertices) m_map.duplicateDarts(m_map.getMaxLevel()); m_map.setCurrentLevel(m_map.getMaxLevel()) ; -// for(unsigned int i = m_mrattribs.begin(); i != m_mrattribs.end(); m_mrattribs.next(i)) -// { -// unsigned int newindex = copyDartLine((*m_mrDarts[m_mrCurrentLevel])[i]) ; // duplicate all darts -// (*m_mrDarts[m_mrCurrentLevel])[i] = newindex ; // on the new max level -// if(!shareVertexEmbeddings) -// (*m_embeddings[VERTEX])[newindex] = EMBNULL ; // set vertex embedding to EMBNULL if no sharing -// } - // cut edges TraversorE travE(m_map) ; for (Dart d = travE.begin(); d != travE.end(); d = travE.next()) @@ -94,7 +86,7 @@ void Map2MR::addNewLevel(bool triQuad, bool embedNewVertices) unsigned int degree = m_map.faceDegree(old) ; m_map.incCurrentLevel() ; - if(triQuad & degree == 3) // if subdividing a triangle + if(triQuad && (degree == 3)) // if subdividing a triangle { Dart dd = m_map.phi1(old) ; Dart e = m_map.phi1(m_map.phi1(dd)) ; @@ -150,6 +142,66 @@ void Map2MR::addNewLevelSqrt3(bool embedNewVertices) m_map.duplicateDarts(m_map.getMaxLevel()); m_map.setCurrentLevel(m_map.getMaxLevel()) ; + //split faces + TraversorF t(m_map) ; + for (Dart dit = t.begin(); dit != t.end(); dit = t.next()) + { + //if it is an even level (triadic refinement) and a boundary face + if((m_map.getCurrentLevel()%2 == 0) && m_map.isBoundaryFace(dit)) + { + //find the boundary edge + //Dart df = m_map.findBoundaryEdgeOfFace(dit); + + //trisection of the boundary edge + } + else + { + Dart d1 = m_map.phi1(dit); + m_map.splitFace(dit, d1) ; + m_map.cutEdge(m_map.phi_1(dit)) ; + Dart x = m_map.phi2(m_map.phi_1(dit)) ; + Dart dd = m_map.phi1(m_map.phi1(m_map.phi1((x)))); + while(dd != x) + { + Dart next = m_map.phi1(dd) ; + m_map.splitFace(dd, m_map.phi1(x)) ; + dd = next ; + } + + Dart cd = m_map.phi2(x); + + if(embedNewVertices) + m_map.template embedNewCell(cd) ; + + Dart fit = cd ; + do + { + t.skip(fit); + fit = m_map.phi2(m_map.phi_1(fit)); + } while(fit != cd); + } + } + + //swap edges + TraversorE te(m_map) ; + for (Dart dit = te.begin(); dit != te.end(); dit = te.next()) + { + if(m_map.getDartLevel(dit) < m_map.getCurrentLevel() && !m_map.isBoundaryEdge(dit)) + m_map.flipEdge(dit); + } + + m_map.popLevel() ; +} + +template +void Map2MR::addNewLevelSqrt2(bool embedNewVertices) +{ + m_map.pushLevel() ; + + m_map.addLevelBack() ; + m_map.duplicateDarts(m_map.getMaxLevel()); + m_map.setCurrentLevel(m_map.getMaxLevel()) ; + //split faces TraversorF t(m_map) ; for (Dart dit = t.begin(); dit != t.end(); dit = t.next()) @@ -179,14 +231,6 @@ void Map2MR::addNewLevelSqrt3(bool embedNewVertices) } while(fit != cd); } - //swap edges - TraversorE te(m_map) ; - for (Dart dit = te.begin(); dit != te.end(); dit = te.next()) - { - if(m_map.getDartLevel(dit) < m_map.getCurrentLevel()) - m_map.flipEdge(dit); - } - m_map.popLevel() ; } diff --git a/include/Algo/Multiresolution/Map3MR/map3MR_PrimalRegular.hpp b/include/Algo/Multiresolution/Map3MR/map3MR_PrimalRegular.hpp index 96aab53c6f9728e1ed3300f6b70d73f31182938f..4b0f39e1d4f3c7b9925783cdd8142e93a5d6d1d2 100644 --- a/include/Algo/Multiresolution/Map3MR/map3MR_PrimalRegular.hpp +++ b/include/Algo/Multiresolution/Map3MR/map3MR_PrimalRegular.hpp @@ -169,7 +169,23 @@ void Map3MR::addNewLevelSqrt3(bool embedNewVertices) Algo::Modelisation::Tetrahedralization::flip1To3(m_map, dit); } } + + // + // edge-removal on all old boundary edges + // + TraversorE tE(m_map); + for(Dart dit = tE.begin() ; dit != tE.end() ; dit = tE.next()) + { + if(m.isMarked(dit)) + { + m.unmarkOrbit(dit); + Dart d = m_map.phi2(m_map.phi3(m_map.findBoundaryFaceOfEdge(dit))); + Algo::Modelisation::Tetrahedralization::swapGen3To2(m_map, d); + + } + } */ + m_map.setCurrentLevel(m_map.getMaxLevel()); m_map.popLevel() ; } diff --git a/include/Topology/generic/functor.h b/include/Topology/generic/functor.h index 5dc40a4f29b28d33fc1bf610c2753e8f6b53d0be..38d8483a15f511960e4f103926b4343375984d74 100644 --- a/include/Topology/generic/functor.h +++ b/include/Topology/generic/functor.h @@ -171,6 +171,33 @@ public: FunctorSelect* copy() const { return new SelectorDartNoBoundary(m_map);} }; +template +class SelectorLevel : public FunctorSelect +{ +public: +protected: + MAP& m_map; + unsigned int m_level; +public: + SelectorLevel(MAP& m, unsigned int l): m_map(m), m_level(l) {} + bool operator()(Dart d) const { return m_map.getDartLevel(d) == m_level; } + FunctorSelect* copy() const { return new SelectorLevel(m_map, m_level);} +}; + +template +class SelectorEdgeLevel : public FunctorSelect +{ +public: +protected: + MAP& m_map; + unsigned int m_level; +public: + SelectorEdgeLevel(MAP& m, unsigned int l): m_map(m), m_level(l) {} + bool operator()(Dart d) const { return (m_map.getDartLevel(d) == m_level) && (m_map.getDartLevel(m_map.phi2(d)) == m_level); } + FunctorSelect* copy() const { return new SelectorEdgeLevel(m_map, m_level);} +}; + + // //class SelectorDartMarked : public FunctorSelect //{ diff --git a/include/Topology/generic/genericmap.hpp b/include/Topology/generic/genericmap.hpp index 8395597710be6e1f3df3048c37872ae48131aae2..216f8fa019dd7d7d6b8fc3791f3d5141bdd1024b 100644 --- a/include/Topology/generic/genericmap.hpp +++ b/include/Topology/generic/genericmap.hpp @@ -133,11 +133,12 @@ inline void GenericMap::deleteDart(Dart d) // a MRdart can only be deleted on its insertion level if(getDartLevel(d) == m_mrCurrentLevel) { - if(isDartValid(d))//index)) + if(isDartValid(d)) + { deleteDartLine(index) ; - - m_mrattribs.removeLine(d.index); - m_mrNbDarts[m_mrCurrentLevel]--; + m_mrattribs.removeLine(d.index); + m_mrNbDarts[m_mrCurrentLevel]--; + } } else { diff --git a/include/Topology/map/map2.h b/include/Topology/map/map2.h index 44cee20203ea949e7e90f67b6a5bb94888ec3e07..0159d5dd331e110d59d5c4dac8d6f7d03d9f327f 100644 --- a/include/Topology/map/map2.h +++ b/include/Topology/map/map2.h @@ -216,21 +216,6 @@ public: */ void swapEdges(Dart d, Dart e); -// //! Insert an edge after a dart in the vertex orbit -// /*! \pre Dart d and e MUST be different and belong to distinct face -// * \pre Dart e must be phi2-linked with its phi_1 dart -// * @param d dart of the vertex -// * @param e dart of the edge -// */ -// virtual void insertEdgeInVertex(Dart d, Dart e); -// -// //! Remove an edge from a vertex orbit -// /*! \pre Dart d must be phi2 sewed -// * @param d the dart of the edge to remove from the vertex -// * @return true if the removal has been executed, false otherwise -// */ -// virtual bool removeEdgeFromVertex(Dart d); - //! Sew two oriented faces along oriented edges /*! \pre Edges of darts d & e MUST be boundary edges * @param d a dart of the first face @@ -334,6 +319,12 @@ public: */ Dart findBoundaryEdgeOfVertex(Dart d); + /** + * find the dart of edge that belong to the boundary + * return NIL if the face is not on the boundary + */ + Dart findBoundaryEdgeOfFace(Dart d); + //! Test if dart d and e belong to the same edge /*! @param d a dart * @param e a dart diff --git a/src/Topology/map/embeddedMap3.cpp b/src/Topology/map/embeddedMap3.cpp index 684acea29b7d02d16e54260677dea1e6905cfac1..fa449841c14c12fc981a9bfc4cbd8d55106d2eee 100644 --- a/src/Topology/map/embeddedMap3.cpp +++ b/src/Topology/map/embeddedMap3.cpp @@ -155,61 +155,35 @@ Dart EmbeddedMap3::deleteEdge(Dart d) bool EmbeddedMap3::edgeCanCollapse(Dart d) { -// //Criteres sur le bord -// if(isBoundaryEdge(d)) -// { -// //fusion de deux bords -// -// //deconnection du bord -// } -// -// return true; - -// if(Map2::isBoundaryVertex(d) || Map2::isBoundaryVertex(phi1(d))) -// return false ; - - unsigned int val_v1 = Map2::vertexDegree(d) ; - unsigned int val_v2 = Map2::vertexDegree(phi1(d)) ; - - if(val_v1 + val_v2 < 8 || val_v1 + val_v2 > 14) - return false ; + if(isBoundaryVertex(d) || isBoundaryVertex(phi1(d))) + return false; + + if(isBoundaryEdge(d)) + return false; - if(Map2::faceDegree(d) == 3) + CellMarkerStore mv(*this); + + Traversor3VVaE t3VVaE_v1(*this,d); + for(Dart dit = t3VVaE_v1.begin() ; dit != t3VVaE_v1.end() ; dit = t3VVaE_v1.next()) { - if(Map2::vertexDegree(phi_1(d)) < 4) - return false ; + mv.mark(dit); } - Dart dd = phi2(d) ; - if(Map2::faceDegree(dd) == 3) + Traversor3EW t3EW(*this,d); + for(Dart dit = t3EW.begin() ; dit != t3EW.end() ; dit = t3EW.next()) { - if(Map2::vertexDegree(phi_1(dd)) < 4) - return false ; + mv.unmark(phi_1(dit)); + mv.unmark(phi_1(phi2(dit))); } - // Check vertex sharing condition - std::vector vu1 ; - vu1.reserve(256) ; - Dart vit1 = phi2(phi_1(phi2(phi_1(d)))) ; - Dart end = phi1(dd) ; - do + Traversor3VVaE t3VVaE_v2(*this,phi2(d)); + for(Dart dit = t3VVaE_v2.begin() ; dit != t3VVaE_v2.end() ; dit = t3VVaE_v2.next()) { - unsigned int ve = getEmbedding(phi2(vit1)) ; - vu1.push_back(ve) ; - vit1 = phi2(phi_1(vit1)) ; - } while(vit1 != end) ; - end = phi1(d) ; - Dart vit2 = phi2(phi_1(phi2(phi_1(dd)))) ; - do - { - unsigned int ve = getEmbedding(phi2(vit2)) ; - std::vector::iterator it = std::find(vu1.begin(), vu1.end(), ve) ; - if(it != vu1.end()) - return false ; - vit2 = phi2(phi_1(vit2)) ; - } while(vit2 != end) ; + if(mv.isMarked(dit)) + return false; + } - return true ; + return true; } Dart EmbeddedMap3::collapseEdge(Dart d, bool delDegenerateVolumes) diff --git a/src/Topology/map/map2.cpp b/src/Topology/map/map2.cpp index edfcca778ec27068fd08c23574613ef6e6e9d657..a6ad808af49571d3fa7346e988b9d80a3d68b26c 100644 --- a/src/Topology/map/map2.cpp +++ b/src/Topology/map/map2.cpp @@ -340,22 +340,6 @@ void Map2::swapEdges(Dart d, Dart e) //phi2sew(d2, e2); } -//void Map2::insertEdgeInVertex(Dart d, Dart e) -//{ -// assert(!sameVertex(d,e) && phi2(e) == phi_1(e)); -// phi1sew(phi_1(d), phi_1(e)); -//} -// -//bool Map2::removeEdgeFromVertex(Dart d) -//{ -// if (!isBoundaryEdge(d)) -// { -// phi1sew(phi_1(d), phi2(d)) ; -// return true ; -// } -// return false ; -//} - void Map2::sewFaces(Dart d, Dart e, bool withBoundary) { // if sewing with fixed points @@ -614,6 +598,18 @@ Dart Map2::findBoundaryEdgeOfVertex(Dart d) return NIL ; } +Dart Map2::findBoundaryEdgeOfFace(Dart d) +{ + Dart it = d ; + do + { + if (isBoundaryMarked(phi2(it))) + return phi2(it) ; + it = phi1(it) ; + } while (it != d) ; + return NIL ; +} + bool Map2::isBoundaryFace(Dart d) { Dart it = d ; diff --git a/src/Topology/map/map3.cpp b/src/Topology/map/map3.cpp index ae27a20be1ac872a5d4a179c81822e7cddfe1310..8af27777fd24feec7b98b8d5b3621790ce489914 100644 --- a/src/Topology/map/map3.cpp +++ b/src/Topology/map/map3.cpp @@ -448,87 +448,6 @@ Dart Map3::collapseEdge(Dart d, bool delDegenerateVolumes) } - - -// Dart e = d; -// -// // stocke un brin par volume autour de l'arete -// std::vector tmp; -// tmp.reserve(32); -// do -// { -// tmp.push_back(e); -// e = alpha2(e); -// } while (e != d); -// -// // contraction de la 2 carte de chaque 2-arete -// for (std::vector::iterator it = tmp.begin(); it != tmp.end(); ++it) -// { -// // un brin d'une face adjacente a l'arrete contracte -// Dart d = phi2(phi_1(*it)); -// Map2::collapseEdge(*it, true); -// -// // test de la degeneresence -// // impossible d'avoir un volume de moins de 4 faces sans avoir de phi2 en points fixe donc on les vire -// if(delDegenerateVolumes && Map2::volumeDegree(d) < 4) -// { -// Dart e = d; -// // pour tous les brins de la face adjacente -// -// do -// { -// Dart ee = phi3(e); -// Dart ff = phi3(phi2(e)); -// -// // si les brins ont un voisin par phi3 -// if(ee != e) -// -// phi3unsew(ee); -// if(ff != phi2(e)) -// phi3unsew(ff); -// -// // si les deux en ont un, il faut les coudres ensemble -// if(ee != e && ff != phi2(e)) -// phi3sew(ee, ff); -// -// // on peut supprimer les brins de cette arete -// deleteDart(e); -// deleteDart(phi2(e)); -// e = phi1(e); -// -// } while (e != d); -// } -// } - -//bool Map3::collapseDegeneratedFace(Dart d) -//{ -// Dart d3 = phi3(d); -// -// std::cout << "Map3::collapseDegeneratedFace"<< std::endl; -// -// if (!isDartValid(d)) -// Map2::collapseDegeneratedFace(d); -// else -// std::cout << "Warning Coll1 invalid"<< std::endl; -// -// -// if (isDartValid(d3)) -// Map2::collapseDegeneratedFace(d3); -// else -// std::cout << "Warning coll2 invalid"<< std::endl; -// -// -// -///* -// Map3::unsewVolumes(d); -// -// std::cout << Map2::collapseDegeneratedFace(d) << std::endl; -// std::cout << Map2::collapseDegeneratedFace(d3) << std::endl; -// std::cout << std::endl; -//*/ -// return true; -//} - bool Map3::splitFacePreCond(Dart d, Dart e) { return (d != e && sameOrientedFace(d, e)) ; @@ -997,7 +916,7 @@ bool Map3::hasBoundaryEdge(Dart d) bool Map3::check() { std::cout << "Check: topology begin" << std::endl; - DartMarker m(*this); + DartMarkerStore m(*this); for(Dart d = Map3::begin(); d != Map3::end(); Map3::next(d)) { Dart d3 = phi3(d); @@ -1009,8 +928,11 @@ bool Map3::check() if(phi1(d3) != phi3(phi_1(d))) { - std::cout << "Check: phi3 , faces are not entirely sewn" << std::endl; - //return false; + if(isBoundaryMarked(d)) + std::cout << "Boundary case - Check: phi3 , faces are not entirely sewn" << std::endl; + else + std::cout << "Check: phi3 , faces are not entirely sewn" << std::endl; + return false; } Dart d2 = phi2(d);