Heavyly restructured for meshlab inclusion. Now the access to the quadric elements are mediated by a static helper class.
This commit is contained in:
parent
2896499a4b
commit
6295f96fbd
vcg/complex/local_optimization
|
@ -24,6 +24,9 @@
|
||||||
History
|
History
|
||||||
|
|
||||||
$Log: not supported by cvs2svn $
|
$Log: not supported by cvs2svn $
|
||||||
|
Revision 1.9 2006/10/07 17:20:25 cignoni
|
||||||
|
Updated to the new style face->Normal() becomes Normal(face)
|
||||||
|
|
||||||
Revision 1.8 2005/10/02 23:19:36 cignoni
|
Revision 1.8 2005/10/02 23:19:36 cignoni
|
||||||
Changed the sign of the priority of a collapse. Now it is its the error as it should (and not -error)
|
Changed the sign of the priority of a collapse. Now it is its the error as it should (and not -error)
|
||||||
|
|
||||||
|
@ -75,10 +78,15 @@ namespace tri{
|
||||||
Requirements:
|
Requirements:
|
||||||
|
|
||||||
Vertex
|
Vertex
|
||||||
must have incremental mark
|
|
||||||
must have:
|
must have:
|
||||||
field QuadricType Q;
|
incremental mark
|
||||||
member
|
VF topology
|
||||||
|
|
||||||
|
must have:
|
||||||
|
members
|
||||||
|
|
||||||
|
QuadricType Qd();
|
||||||
|
|
||||||
ScalarType W() const;
|
ScalarType W() const;
|
||||||
A per-vertex Weight that can be used in simplification
|
A per-vertex Weight that can be used in simplification
|
||||||
lower weight means that error is lowered,
|
lower weight means that error is lowered,
|
||||||
|
@ -89,27 +97,26 @@ namespace tri{
|
||||||
(e.g. its weight with the one of the given vertex, the color ect).
|
(e.g. its weight with the one of the given vertex, the color ect).
|
||||||
Standard: void function;
|
Standard: void function;
|
||||||
|
|
||||||
Faces devono avere Shared Adjacency
|
OtherWise the class should be templated with a static helper class that helps to retrieve these functions.
|
||||||
durante la init serve FF per le quadriche di bordo
|
If the vertex class exposes these functions a default static helper class is provided.
|
||||||
durante la semplificazione si usa VF
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
//**Helper CLASSES**//
|
||||||
|
template <class VERTEX_TYPE>
|
||||||
|
class QInfoStandard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QInfoStandard(){};
|
||||||
|
static void Init(){};
|
||||||
|
static math::Quadric<double> &Qd(VERTEX_TYPE &v) {return v.Qd();}
|
||||||
|
static math::Quadric<double> &Qd(VERTEX_TYPE *v) {return v->Qd();}
|
||||||
|
static typename VERTEX_TYPE::ScalarType W(VERTEX_TYPE *v) {return 1.0;};
|
||||||
|
static typename VERTEX_TYPE::ScalarType W(VERTEX_TYPE &v) {return 1.0;};
|
||||||
|
static void Merge(VERTEX_TYPE & v_dest, VERTEX_TYPE const & v_del){};
|
||||||
|
};
|
||||||
|
|
||||||
template<class TriMeshType,class MYTYPE>
|
|
||||||
class TriEdgeCollapseQuadric: public TriEdgeCollapse< TriMeshType,MYTYPE>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef typename vcg::tri::TriEdgeCollapse< TriMeshType, MYTYPE > TEC;
|
|
||||||
typedef typename TEC::EdgeType EdgeType;
|
|
||||||
typedef typename TriEdgeCollapse<TriMeshType, MYTYPE>::HeapType HeapType;
|
|
||||||
typedef typename TriEdgeCollapse<TriMeshType, MYTYPE>::HeapElem HeapElem;
|
|
||||||
typedef typename TriMeshType::CoordType CoordType;
|
|
||||||
typedef typename TriMeshType::ScalarType ScalarType;
|
|
||||||
typedef math::Quadric< double > QuadricType;
|
|
||||||
typedef typename TriMeshType::FaceType FaceType;
|
|
||||||
typedef typename TriMeshType::VertexType VertexType;
|
|
||||||
|
|
||||||
class QParameter
|
class TriEdgeCollapseQuadricParameter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
double QualityThr; // all
|
double QualityThr; // all
|
||||||
|
@ -135,6 +142,22 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<class TriMeshType,class MYTYPE, class HelperType = QInfoStandard<TriMeshType::VertexType> >
|
||||||
|
class TriEdgeCollapseQuadric: public TriEdgeCollapse< TriMeshType, MYTYPE>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename vcg::tri::TriEdgeCollapse< TriMeshType, MYTYPE > TEC;
|
||||||
|
typedef typename TEC::EdgeType EdgeType;
|
||||||
|
typedef typename TriEdgeCollapse<TriMeshType, MYTYPE>::HeapType HeapType;
|
||||||
|
typedef typename TriEdgeCollapse<TriMeshType, MYTYPE>::HeapElem HeapElem;
|
||||||
|
typedef typename TriMeshType::CoordType CoordType;
|
||||||
|
typedef typename TriMeshType::ScalarType ScalarType;
|
||||||
|
typedef math::Quadric< double > QuadricType;
|
||||||
|
typedef typename TriMeshType::FaceType FaceType;
|
||||||
|
typedef typename TriMeshType::VertexType VertexType;
|
||||||
|
typedef TriEdgeCollapseQuadricParameter QParameter;
|
||||||
|
typedef HelperType QH;
|
||||||
|
|
||||||
static QParameter & Params(){static QParameter p; return p;}
|
static QParameter & Params(){static QParameter p; return p;}
|
||||||
enum Hint {
|
enum Hint {
|
||||||
HNHasFFTopology = 0x0001, // La mesh arriva con la topologia ff gia'fatta
|
HNHasFFTopology = 0x0001, // La mesh arriva con la topologia ff gia'fatta
|
||||||
|
@ -170,7 +193,8 @@ public:
|
||||||
{ CoordType newPos;
|
{ CoordType newPos;
|
||||||
if(Params().OptimalPlacement) newPos= ComputeMinimal();
|
if(Params().OptimalPlacement) newPos= ComputeMinimal();
|
||||||
else newPos=this->pos.V(1)->P();
|
else newPos=this->pos.V(1)->P();
|
||||||
this->pos.V(1)->q+=this->pos.V(0)->q;
|
//this->pos.V(1)->Qd()+=this->pos.V(0)->Qd();
|
||||||
|
QH::Qd(this->pos.V(1))+=QH::Qd(this->pos.V(0));
|
||||||
int FaceDel=DoCollapse(this->pos, newPos); // v0 is deleted and v1 take the new position
|
int FaceDel=DoCollapse(this->pos, newPos); // v0 is deleted and v1 take the new position
|
||||||
m.fn-=FaceDel;
|
m.fn-=FaceDel;
|
||||||
--m.vn;
|
--m.vn;
|
||||||
|
@ -351,8 +375,8 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QuadricType qq=v[0]->q;
|
QuadricType qq=QH::Qd(v[0]);
|
||||||
qq+=v[1]->q;
|
qq+=QH::Qd(v[1]);
|
||||||
double QuadErr = Params().ScaleFactor*qq.Apply(v[1]->P());
|
double QuadErr = Params().ScaleFactor*qq.Apply(v[1]->P());
|
||||||
|
|
||||||
// All collapses involving triangles with quality larger than <QualityThr> has no penalty;
|
// All collapses involving triangles with quality larger than <QualityThr> has no penalty;
|
||||||
|
@ -367,7 +391,7 @@ public:
|
||||||
|
|
||||||
if(QuadErr<Params().QuadricEpsilon) QuadErr=Params().QuadricEpsilon;
|
if(QuadErr<Params().QuadricEpsilon) QuadErr=Params().QuadricEpsilon;
|
||||||
|
|
||||||
if( Params().UseVertexWeight ) QuadErr *= (v[1]->W()+v[0]->W())/2;
|
if( Params().UseVertexWeight ) QuadErr *= (QH::W(v[1])+QH::W(v[0]))/2;
|
||||||
|
|
||||||
if(!Params().QualityCheck && !Params().NormalCheck) error = (ScalarType)(QuadErr);
|
if(!Params().QualityCheck && !Params().NormalCheck) error = (ScalarType)(QuadErr);
|
||||||
if( Params().QualityCheck && !Params().NormalCheck) error = (ScalarType)(QuadErr / MinQual);
|
if( Params().QualityCheck && !Params().NormalCheck) error = (ScalarType)(QuadErr / MinQual);
|
||||||
|
@ -447,10 +471,11 @@ static void InitQuadric(TriMeshType &m)
|
||||||
typename TriMeshType::FaceIterator pf;
|
typename TriMeshType::FaceIterator pf;
|
||||||
typename TriMeshType::VertexIterator pv;
|
typename TriMeshType::VertexIterator pv;
|
||||||
int j;
|
int j;
|
||||||
|
QH::Init();
|
||||||
// m.ClearFlags();
|
// m.ClearFlags();
|
||||||
for(pv=m.vert.begin();pv!=m.vert.end();++pv) // Azzero le quadriche
|
for(pv=m.vert.begin();pv!=m.vert.end();++pv) // Azzero le quadriche
|
||||||
if( ! (*pv).IsD() && (*pv).IsW())
|
if( ! (*pv).IsD() && (*pv).IsW())
|
||||||
(*pv).q.Zero();
|
QH::Qd(*pv).Zero();
|
||||||
|
|
||||||
|
|
||||||
for(pf=m.face.begin();pf!=m.face.end();++pf)
|
for(pf=m.face.begin();pf!=m.face.end();++pf)
|
||||||
|
@ -472,7 +497,7 @@ static void InitQuadric(TriMeshType &m)
|
||||||
q.ByPlane(p);
|
q.ByPlane(p);
|
||||||
|
|
||||||
for(j=0;j<3;++j)
|
for(j=0;j<3;++j)
|
||||||
if( (*pf).V(j)->IsW() ) (*pf).V(j)->q += q; // Sommo la quadrica ai vertici
|
if( (*pf).V(j)->IsW() ) QH::Qd((*pf).V(j)) += q; // Sommo la quadrica ai vertici
|
||||||
|
|
||||||
for(j=0;j<3;++j)
|
for(j=0;j<3;++j)
|
||||||
if( (*pf).IsB(j)) // Bordo!
|
if( (*pf).IsB(j)) // Bordo!
|
||||||
|
@ -484,12 +509,12 @@ static void InitQuadric(TriMeshType &m)
|
||||||
// poiche' la pesatura in funzione dell'area e'gia fatta in p.Direction()
|
// poiche' la pesatura in funzione dell'area e'gia fatta in p.Direction()
|
||||||
// Senza la normalize il bordo e' pesato in funzione della grandezza della mesh (mesh grandi non decimano sul bordo)
|
// Senza la normalize il bordo e' pesato in funzione della grandezza della mesh (mesh grandi non decimano sul bordo)
|
||||||
pb.SetDirection(p.Direction() ^ ( (*pf).V1(j)->cP() - (*pf).V(j)->cP() ).Normalize());
|
pb.SetDirection(p.Direction() ^ ( (*pf).V1(j)->cP() - (*pf).V(j)->cP() ).Normalize());
|
||||||
pb.SetDirection(pb.Direction()* Params().BoundaryWeight); // amplify border planes
|
pb.SetDirection(pb.Direction()* (ScalarType)Params().BoundaryWeight); // amplify border planes
|
||||||
pb.SetOffset(pb.Direction() * (*pf).V(j)->cP());
|
pb.SetOffset(pb.Direction() * (*pf).V(j)->cP());
|
||||||
q.ByPlane(pb);
|
q.ByPlane(pb);
|
||||||
|
|
||||||
if( (*pf).V (j)->IsW() ) (*pf).V (j)->q += q; // Sommo le quadriche
|
if( (*pf).V (j)->IsW() ) QH::Qd((*pf).V (j)) += q; // Sommo le quadriche
|
||||||
if( (*pf).V1(j)->IsW() ) (*pf).V1(j)->q += q;
|
if( (*pf).V1(j)->IsW() ) QH::Qd((*pf).V1(j)) += q;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,21 +567,21 @@ static void InitQuadric(TriMeshType &m)
|
||||||
typename TriMeshType::VertexType * v[2];
|
typename TriMeshType::VertexType * v[2];
|
||||||
v[0] = this->pos.V(0);
|
v[0] = this->pos.V(0);
|
||||||
v[1] = this->pos.V(1);
|
v[1] = this->pos.V(1);
|
||||||
QuadricType q=v[0]->q;
|
QuadricType q=QH::Qd(v[0]);
|
||||||
q+=v[1]->q;
|
q+=QH::Qd(v[1]);
|
||||||
|
|
||||||
CoordType x;
|
Point3<QuadricType::ScalarType> x;
|
||||||
bool rt=q.Minimum(x);
|
bool rt=q.Minimum(x);
|
||||||
if(!rt) {
|
if(!rt) { // if the computation of the minimum fails we choose between the two edge points and the middle one.
|
||||||
x=(v[0]->P()+v[1]->P())/2;
|
x.Import((v[0]->P()+v[1]->P())/2);
|
||||||
double qvx=q.Apply(x);
|
double qvx=q.Apply(x);
|
||||||
double qv0=q.Apply(v[0]->P());
|
double qv0=q.Apply(v[0]->P());
|
||||||
double qv1=q.Apply(v[1]->P());
|
double qv1=q.Apply(v[1]->P());
|
||||||
if(qv0<qvx) x=v[0]->P();
|
if(qv0<qvx) x.Import(v[0]->P());
|
||||||
if(qv1<qvx && qv1<qv0) x=v[1]->P();
|
if(qv1<qvx && qv1<qv0) x.Import(v[1]->P());
|
||||||
}
|
}
|
||||||
|
|
||||||
return x;
|
return CoordType::Construct(x);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue