Commit 569c7111 authored by untereiner's avatar untereiner

Merge cgogn:~thery/CGoGN

parents 424ba2db 3e757ee2
......@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>174</width>
<width>176</width>
<height>427</height>
</rect>
</property>
......
......@@ -16,5 +16,7 @@ ENDIF ( NOT Boost_FOUND )
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIRS} )
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC" )
SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC" )
ADD_SUBDIRECTORY( code/ )
......@@ -45,10 +45,10 @@ template <typename PFP>
bool isBetween(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& positions, Dart d, Dart e, Dart f) ;
template <typename PFP>
void mergeVertex(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& positions, Dart d, Dart e);
void mergeVertex(typename PFP::MAP& map, VertexAttribute<typename PFP::VEC3>& positions, Dart d, Dart e);
template <typename PFP>
void mergeVertices(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& positions);
void mergeVertices(typename PFP::MAP& map, VertexAttribute<typename PFP::VEC3>& positions);
}
......
......@@ -43,55 +43,61 @@ bool isBetween(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>
}
template <typename PFP>
void mergeVertex(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& positions, Dart d, Dart e)
void mergeVertex(typename PFP::MAP& map, VertexAttribute<typename PFP::VEC3>& positions, Dart d, Dart e, int precision)
{
assert(Geom::arePointsEquals(positions[d],positions[e]) && !map.sameVertex(d,e));
// d1 traverses the vertex of d (following the alpha1 permutation)
// y is a temporay buffer to stop the loop
Dart d1=d;
// e1 traverses the vertex of e (following the alpha1 permutation)
Dart e1=e;
bool notempty = true;
do {
if (map.phi2_1(e1) == e1) notempty = false;
// detach z from its vertex
map.removeEdgeFromVertex(e1);
// Searchs the dart of the vertex of x where tz may be inserted
Dart nd1 = d1;
do {
if (CGoGN::Algo::BooleanOperator::isBetween<PFP>(map,positions,e1,d1,map.phi2_1(d1))) break;
d1 = map.phi2_1(d1);
} while (d1 != nd1);
map.insertEdgeInVertex(d1,e1);
d1 = e1;
} while (notempty);
assert(positions[d].isNear(positions[e], precision) && !map.sameVertex(d, e)) ;
// 0-embed z on the vertex of x without copy of the vertex
// positions[d] = ;
}
bool notempty = true ;
do // While vertex of e contains more than one dart
{
Dart e1 = map.alpha1(e) ; // e1 stores next dart of vertex of e
if (e1 == e)
notempty = false ; // last dart of vertex of e
else {
map.removeEdgeFromVertex(e) ; // detach e from its vertex
}
// Searchs where e may be inserted in the vertex of d
Dart d1 = d ;
do
{
if (CGoGN::Algo::BooleanOperator::isBetween<PFP>(map, positions, e, d,
map.alpha1(d))) break ;
d = map.alpha1(d) ;
} while (d != d1) ;
// Inserted e in the correct place (after d)
map.insertEdgeInVertex(d, e) ;
// Go on with next darts
d = e ;
e = e1 ;
} while (notempty) ;
}
template <typename PFP>
void mergeVertices(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& positions)
void mergeVertices(typename PFP::MAP& map, VertexAttribute<typename PFP::VEC3>& positions, int precision)
{
// TODO optimiser en triant les sommets
for(Dart d = map.begin() ; d != map.end() ; map.next(d))
// map.template enableQuickTraversal<VERTEX>();
TraversorV<typename PFP::MAP> travV1(map) ;
CellMarker<VERTEX> vM(map);
for(Dart d1 = travV1.begin() ; d1 != travV1.end() ; d1 = travV1.next())
{
CellMarker<VERTEX> vM(map);
vM.mark(d);
std::cout << "." ; std::cout.flush() ;
for(Dart dd = map.begin() ; dd != map.end() ; map.next(dd))
vM.mark(d1);
TraversorV<typename PFP::MAP> travV2(map) ;
for(Dart d2 = travV2.begin() ; d2 != travV2.end() ; d2 = travV2.next())
{
if(!vM.isMarked(dd))
if(!vM.isMarked(d2))
{
if(Geom::arePointsEquals(positions[d],positions[dd]))
if(positions[d1].isNear(positions[d2], precision))
{
mergeVertex<PFP>(map,positions,d,dd);
if (map.sameVertex(d1,d2)) std::cout << "fusion: sameVertex" << std::endl ;
if (!map.sameVertex(d1,d2)) mergeVertex<PFP>(map,positions,d1,d2,precision);
}
}
}
}
// map.template disableQuickTraversal<VERTEX>();
}
}
......
......@@ -46,6 +46,7 @@ enum ApproximatorType
A_CornerCutting,
A_TangentPredict1,
A_TangentPredict2,
A_NormalArea,
A_ColorNaive,
A_ColorQEMext,
A_Lightfield,
......@@ -177,6 +178,11 @@ public:
return m_approx[index][d] ;
}
const VertexAttribute<T>& getAttr(unsigned int index = 0) const
{
return *(m_attrV[index]) ;
}
std::vector<T> getAllApprox(Dart d) const
{
std::vector<T> res ;
......@@ -248,169 +254,6 @@ public:
}
} ;
//template <typename PFP, typename T>
//class ApproximatorEdge : public ApproximatorGen<PFP>
//{
//public:
// typedef typename PFP::MAP MAP ;
// typedef typename PFP::VEC3 VEC3 ;
// typedef typename PFP::REAL REAL ;
//
//protected:
// Predictor<PFP, T>* m_predictor ;
//
// std::vector<VertexAttribute<T>* > m_attrV ; // vertex attributes to be approximated
// std::vector<EdgeAttribute<T> > m_approx ; // attributes to store approximation result
// std::vector<EdgeAttribute<T> > m_detail ; // attributes to store detail information for reconstruction
// std::vector<T> m_app ;
//
//public:
// ApproximatorEdge(MAP& m, std::vector<VertexAttribute<T>* > va, Predictor<PFP, T> * predictor) :
// ApproximatorGen<PFP>(m), m_predictor(predictor), m_attrV(va)
// {
// const unsigned int& size = m_attrV.size() ;
// assert(size > 0 || !"ApproximatorEdge: no attributes provided") ;
//
// m_approx.resize(size) ;
// m_detail.resize(size) ;
// m_app.resize(size) ;
//
// for (unsigned int i = 0 ; i < size ; ++i)
// {
// if (!m_attrV[i]->isValid())
// std::cerr << "ApproximatorEdge Warning: attribute number " << i << " is not valid" << std::endl ;
//
// std::stringstream aname ;
// aname << "approx_" << m_attrV[i]->name() ;
// m_approx[i] = this->m_map.template addAttribute<T, EDGE>(aname.str()) ;
//
// if(m_predictor) // if predictors are associated to the approximator
// { // create attributes to store the details needed for reconstruction
// std::stringstream dname ;
// dname << "detail_" << m_attrV[i]->name() ;
// m_detail[i] = this->m_map.template addAttribute<T, EDGE>(dname.str()) ;
// }
// }
// }
//
// virtual ~ApproximatorEdge()
// {
// for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
// {
// this->m_map.template removeAttribute(m_approx[i]) ;
// if(m_predictor)
// this->m_map.template removeAttribute(m_detail[i]) ;
// }
// }
//
// const std::string& getApproximatedAttributeName(unsigned int index = 0) const
// {
// return m_attrV[index]->name() ;
// }
//
//// std::vector<std::string> getApproximatedAttributeNames() const
//// {
//// std::vector<std::string> names ;
//// names.resize(m_attrV.size()) ;
//// for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
//// names[i] = m_attrV[i]->name() ;
////
//// return names ;
//// }
//
// unsigned int getNbApproximated() const
// {
// return m_attrV.size() ;
// }
//
// void saveApprox(Dart d)
// {
// for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
// m_app[i] = m_approx[i][d] ;
// }
//
// void affectApprox(Dart d)
// {
// for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
// m_attrV[i]->operator[](d) = m_app[i] ;
// }
//
// const T& getApprox(Dart d, unsigned int index = 0) const
// {
// return m_approx[index][d] ;
// }
//
// std::vector<T> getAllApprox(Dart d) const
// {
// std::vector<T> res ;
// res.resize(m_attrV.size()) ;
// for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
// res[i] = m_approx[i][d] ;
//
// return res ;
// }
//
// const Predictor<PFP, T>* getPredictor() const
// {
// return m_predictor ;
// }
//
// const T& getDetail(Dart d, unsigned int index = 0) const
// {
// assert(m_predictor || !"Trying to get detail on a non-predictive scheme") ;
// return m_detail[index][d] ;
// }
//
// std::vector<T> getAllDetail(Dart d) const
// {
// assert(m_predictor || !"Trying to get detail on a non-predictive scheme") ;
//
// std::vector<T> res ;
// res.resize(m_attrV.size()) ;
// for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
// res[i] = m_detail[i][d] ;
// return res ;
// }
//
// void setDetail(Dart d, unsigned int index, T& val)
// {
// assert(m_predictor || !"Trying to set detail on a non-predictive scheme") ;
// m_detail[index][d] = val ;
// }
//
// void setDetail(Dart d, std::vector<T>& val)
// {
// assert(m_predictor || !"Trying to set detail on a non-predictive scheme") ;
//
// for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
// m_detail[index][d] = val[i] ;
// }
//
//
//// // TODO works only for vector types !!
//// REAL detailMagnitude(Dart d)
//// {
//// assert(m_predictor || !"Trying to get detail magnitude on a non-predictive scheme") ;
//// return m_detail[d].norm2() ;
//// }
//
// void addDetail(Dart d, double amount, bool sign, typename PFP::MATRIX33* detailTransform)
// {
// assert(m_predictor || !"Trying to add detail on a non-predictive scheme") ;
//
// for (unsigned int i = 0 ; i < m_attrV.size() ; ++i)
// {
// T det = m_detail[i][d] ;
// if(detailTransform)
// det = (*detailTransform) * det ;
// det *= amount ;
// if(!sign)
// det *= REAL(-1) ;
// m_attrV[i]->operator[](d) += det ;
// }
// }
//} ;
} //namespace Decimation
} // surface
......
......@@ -68,6 +68,9 @@ void decimate(
case A_TangentPredict2 :
approximators.push_back(new Approximator_MidEdge<PFP>(map, attribs)) ;
break ;
case A_NormalArea :
approximators.push_back(new Approximator_NormalArea<PFP>(map, attribs)) ;
break ;
case A_hHalfCollapse :
approximators.push_back(new Approximator_HalfCollapse<PFP>(map, attribs)) ;
break ;
......@@ -102,7 +105,7 @@ void decimate(
// pos
v_approx[0].push_back(attribs[0]) ;
approximators.push_back(new Approximator_QEMhalfEdge<PFP>(map, v_approx[0])) ;
approximators.push_back(new Approximator_HalfCollapse<PFP>(map, v_approx[0])) ;
// frame
assert(attribs.size() >= 4 || !"Decimate: A_hLightfieldHalf --> not enough attribs provided") ;
......@@ -160,6 +163,12 @@ void decimate(
case S_Curvature :
selector = new EdgeSelector_Curvature<PFP>(map, position, approximators, selected) ;
break ;
case S_NormalArea :
selector = new EdgeSelector_NormalArea<PFP>(map, position, approximators, selected) ;
break ;
case S_CurvatureTensor :
selector = new EdgeSelector_CurvatureTensor<PFP>(map, position, approximators, selected) ;
break ;
case S_MinDetail :
selector = new EdgeSelector_MinDetail<PFP>(map, position, approximators, selected) ;
break ;
......@@ -181,6 +190,12 @@ void decimate(
case S_hLightfield :
selector = new HalfEdgeSelector_Lightfield<PFP>(map, position, approximators, selected) ;
break ;
case S_hLightfieldExp :
selector = new HalfEdgeSelector_LightfieldExp<PFP>(map, position, approximators, selected) ;
break ;
case S_hLightfieldKCL :
selector = new HalfEdgeSelector_LightfieldKCL<PFP>(map, position, approximators, selected) ;
break ;
}
for(typename std::vector<ApproximatorGen<PFP>*>::iterator it = approximators.begin(); it != approximators.end(); ++it)
......
......@@ -31,7 +31,10 @@
#include "Container/fakeAttribute.h"
#include "Utils/qem.h"
#include "Utils/quadricRGBfunctions.h"
#include "Algo/Geometry/normal.h"
#include "Algo/Selection/collector.h"
#include "Algo/Geometry/curvature.h"
#include "Algo/Geometry/area.h"
namespace CGoGN
{
......@@ -271,6 +274,61 @@ public:
void updateWithoutCollapse();
} ;
template <typename PFP>
class EdgeSelector_NormalArea : public EdgeSelector<PFP>
{
public:
typedef typename PFP::MAP MAP ;
typedef typename PFP::VEC3 VEC3 ;
typedef typename PFP::REAL REAL ;
private:
typedef struct
{
typename std::multimap<float,Dart>::iterator it ;
bool valid ;
static std::string CGoGNnameOfType() { return "NormalAreaEdgeInfo" ; }
} NormalAreaEdgeInfo ;
typedef NoMathIOAttribute<NormalAreaEdgeInfo> EdgeInfo ;
EdgeAttribute<EdgeInfo> edgeInfo ;
EdgeAttribute<Geom::Matrix<3,3,REAL> > edgeMatrix ;
std::multimap<float,Dart> edges ;
typename std::multimap<float,Dart>::iterator cur ;
Approximator<PFP, typename PFP::VEC3, EDGE>* m_positionApproximator ;
void initEdgeInfo(Dart d) ;
void updateEdgeInfo(Dart d) ;
void computeEdgeInfo(Dart d, EdgeInfo& einfo) ;
void computeEdgeMatrix(Dart d) ;
// void recomputeQuadric(const Dart d, const bool recomputeNeighbors = false) ;
public:
EdgeSelector_NormalArea(MAP& m, VertexAttribute<typename PFP::VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select) :
EdgeSelector<PFP>(m, pos, approx, select),
m_positionApproximator(NULL)
{
edgeInfo = m.template addAttribute<EdgeInfo, EDGE>("edgeInfo") ;
edgeMatrix = m.template addAttribute<Geom::Matrix<3,3,REAL>, EDGE>("NormalAreaMatrix") ;
}
~EdgeSelector_NormalArea()
{
this->m_map.removeAttribute(edgeMatrix) ;
this->m_map.removeAttribute(edgeInfo) ;
}
SelectorType getType() { return S_NormalArea ; }
bool init() ;
bool nextEdge(Dart& d) ;
void updateBeforeCollapse(Dart d) ;
void updateAfterCollapse(Dart d2, Dart dd2) ;
void updateWithoutCollapse() { }
} ;
template <typename PFP>
class EdgeSelector_Curvature : public EdgeSelector<PFP>
{
......@@ -369,6 +427,66 @@ public:
void updateWithoutCollapse();
} ;
template <typename PFP>
class EdgeSelector_CurvatureTensor : public EdgeSelector<PFP>
{
// TODO : this selector still needs to be tested
public:
typedef typename PFP::MAP MAP ;
typedef typename PFP::VEC3 VEC3 ;
typedef typename PFP::REAL REAL ;
private:
typedef struct
{
typename std::multimap<float,Dart>::iterator it ;
bool valid ;
static std::string CGoGNnameOfType() { return "CurvatureTensorEdgeInfo" ; }
} CurvatureTensorEdgeInfo ;
typedef NoMathIOAttribute<CurvatureTensorEdgeInfo> EdgeInfo ;
EdgeAttribute<EdgeInfo> edgeInfo ;
EdgeAttribute<REAL> edgeangle ;
std::multimap<float,Dart> edges ;
typename std::multimap<float,Dart>::iterator cur ;
Approximator<PFP, VEC3,EDGE>* m_positionApproximator ;
void initEdgeInfo(Dart d) ;
void updateEdgeInfo(Dart d) ; // TODO : usually has a 2nd arg (, bool recompute) : why ??
void computeEdgeInfo(Dart d, EdgeInfo& einfo) ;
public:
EdgeSelector_CurvatureTensor(MAP& m, VertexAttribute<VEC3>& pos, std::vector<ApproximatorGen<PFP>*>& approx, const FunctorSelect& select) :
EdgeSelector<PFP>(m, pos, approx, select),
m_positionApproximator(NULL)
{
edgeangle = m.template getAttribute<REAL, EDGE>("edgeangle") ;
if(!edgeangle.isValid())
{
edgeangle = m.template addAttribute<REAL, EDGE>("edgeangle") ;
Algo::Geometry::computeAnglesBetweenNormalsOnEdges<PFP>(m, pos, edgeangle) ;
}
edgeInfo = m.template addAttribute<EdgeInfo, EDGE>("edgeInfo") ;
}
~EdgeSelector_CurvatureTensor()
{
this->m_map.removeAttribute(edgeangle) ; // TODO : pas malin s'il existait avant
this->m_map.removeAttribute(edgeInfo) ;
}
SelectorType getType() { return S_CurvatureTensor ; }
bool init() ;
bool nextEdge(Dart& d) ;
void updateBeforeCollapse(Dart d) ;
void updateAfterCollapse(Dart d2, Dart dd2) ;
void updateWithoutCollapse() {};
} ;
template <typename PFP>
class EdgeSelector_MinDetail : public EdgeSelector<PFP>
{
......
This diff is collapsed.
......@@ -26,6 +26,8 @@
#define __GEOMETRY_APPROXIMATOR_H__
#include "Algo/Decimation/approximator.h"
#include "Utils/convertType.h"
#include <Eigen/Dense>
namespace CGoGN
{
......@@ -147,6 +149,32 @@ public:
void approximate(Dart d) ;
} ;
template <typename PFP>
class Approximator_NormalArea : public Approximator<PFP, typename PFP::VEC3, EDGE>
{
public:
typedef typename PFP::MAP MAP ;
typedef typename PFP::VEC3 VEC3 ;
typedef typename PFP::REAL REAL ;
protected:
// VertexAttribute<Utils::Quadric<REAL> > m_quadric ;
EdgeAttribute<Geom::Matrix<3,3,REAL> > edgeMatrix ;
public:
Approximator_NormalArea(MAP& m, std::vector<VertexAttribute<VEC3>* > pos, Predictor<PFP, VEC3>* pred = NULL) :
Approximator<PFP, VEC3, EDGE>(m, pos, pred)
{
assert(pos.size() > 0 || !"Approximator_NormalArea: attribute vector is empty") ;
}
~Approximator_NormalArea()
{}
ApproximatorType getType() const { return A_NormalArea ; }
bool init() ;
void approximate(Dart d) ;
} ;
} //namespace Decimation
}
......
......@@ -371,6 +371,89 @@ void Approximator_CornerCutting<PFP>::approximate(Dart d)
}
}
/************************************************************************************
* NORMAL AREA METRIC *
************************************************************************************/
template <typename PFP>
bool Approximator_NormalArea<PFP>::init()
{
edgeMatrix = this->m_map.template getAttribute<Geom::Matrix<3,3,REAL>, EDGE>("NormalAreaMatrix") ;
assert(edgeMatrix.isValid());
// m_quadric = this->m_map.template getAttribute<Utils::Quadric<REAL>, VERTEX>("QEMquadric") ;
// Does not require to be valid (if it is not, altenatives will be used).
if(this->m_predictor)
{
return false ;
}
return true ;
}
template <typename PFP>
void Approximator_NormalArea<PFP>::approximate(Dart d)
{
typedef typename PFP::REAL REAL;
typedef Geom::Matrix<3,3,REAL> MATRIX;
typedef Eigen::Matrix<REAL,3,1> E_VEC3;
typedef Eigen::Matrix<REAL,3,3> E_MATRIX;
MAP& m = this->m_map ;
Dart dd = m.phi2(d);
MATRIX M1; // init zero included
MATRIX M2; // init zero included
assert(! m.isBoundaryEdge(d));
Traversor2VF<MAP> td (m,d);
Dart it = td.begin();
it = td.next();
Dart it2 = td.next();
while( it2 != td.end())
{
M1 += edgeMatrix[m.phi1(it)];
it = it2;
it2 = td.next();
}
Traversor2VF<MAP> tdd (m,dd);
it = tdd.begin();
it = tdd.next();
it2 = tdd.next();
while( it2 != tdd.end())
{
M2 += edgeMatrix[m.phi1(it)];
it = it2;
it2 = tdd.next();
}
const VEC3 & v1 = (*this->m_attrV[0])[d] ;
const VEC3 & v2 = (*this->m_attrV[0])[dd] ;
/* version plus sûre : sans cast avec recopie
E_MATRIX A ;
A << M1(0,0)+M2(0,0) , M1(0,1)+M2(0,1) , M1(0,2)+M2(0,2) , M1(1,0)+M2(1,0) , M1(1,1)+M2(1,1) , M1(1,2)+M2(1,2) , M1(2,0)+M2(2,0) , M1(2,1)+M2(2,1) , M1(2,2)+M2(2,2) ;
VEC3 mb = M1*v1 + M2*v2 ;
E_VEC3 b (mb[0],mb[1],mb[2]);
Eigen::LDLT<E_MATRIX> decompo (A);
E_VEC3 x = decompo.solve(b);
this->m_approx[0][d] = VEC3 (x(0),x(1),x(2)) ;
*/
/* version legerement moins gourmande et plus risquee : avec cast sans recopie */
VEC3 mb = M1*v1 + M2*v2 ;
M1 += M2;
Eigen::LDLT<E_MATRIX> decompo (Utils::convertRef<E_MATRIX>(M1));
E_VEC3 x = decompo.solve(Utils::convertRef<E_VEC3>(mb));
this->m_approx[0][d] = Utils::convertRef<VEC3>(x) ;
}
} //namespace Decimation
}
......
......@@ -166,18 +166,22 @@ public:
TraversorE<typename PFP::MAP> travE(this->m_map) ;
for(Dart d = travE.begin() ; d != travE.end() ; d = travE.next())
{
(*errors)[d] = -1 ;
if (halfEdgeInfo[d].valid)
{
(*errors)[d] = halfEdgeInfo[d].it->first ;
}
else
(*errors)[d] = -1 ;
Dart dd = this->m_map.phi2(d) ;
if (halfEdgeInfo[dd].valid && halfEdgeInfo[dd].it->