removed a useless template specialization to a few std::make_pair

This commit is contained in:
Paolo Cignoni 2013-03-22 16:53:42 +00:00
parent 246345bf19
commit 3a9a72c098
1 changed files with 384 additions and 383 deletions

View File

@ -27,6 +27,7 @@
// Standard headers // Standard headers
#include <map> #include <map>
#include <algorithm> #include <algorithm>
#include <utility>
#include <stack> #include <stack>
// VCG headers // VCG headers
@ -49,7 +50,7 @@ namespace vcg {
template <class ConnectedMeshType> template <class ConnectedMeshType>
class ConnectedIterator class ConnectedIterator
{ {
public: public:
typedef ConnectedMeshType MeshType; typedef ConnectedMeshType MeshType;
typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexType VertexType;
typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::VertexPointer VertexPointer;
@ -65,18 +66,18 @@ class ConnectedIterator
public: public:
void operator ++() void operator ++()
{ {
FacePointer fpt=sf.top(); FacePointer fpt=sf.top();
sf.pop(); sf.pop();
for(int j=0;j<3;++j) for(int j=0;j<3;++j)
if( !face::IsBorder(*fpt,j) ) if( !face::IsBorder(*fpt,j) )
{ {
FacePointer l=fpt->FFp(j); FacePointer l=fpt->FFp(j);
if( !tri::IsMarked(*mp,l) ) if( !tri::IsMarked(*mp,l) )
{ {
tri::Mark(*mp,l); tri::Mark(*mp,l);
sf.push(l); sf.push(l);
} }
} }
} }
void start(MeshType &m, FacePointer p) void start(MeshType &m, FacePointer p)
@ -87,7 +88,7 @@ public:
assert(p); assert(p);
assert(!p->IsD()); assert(!p->IsD());
tri::Mark(m,p); tri::Mark(m,p);
sf.push(p); sf.push(p);
} }
bool completed() { bool completed() {
return sf.empty(); return sf.empty();
@ -106,7 +107,7 @@ private:
/// ///
/** \addtogroup trimesh */ /** \addtogroup trimesh */
/*@{*/ /*@{*/
/// Class of static functions to clean//restore meshs. /// Class of static functions to clean//restore meshs.
template <class CleanMeshType> template <class CleanMeshType>
class Clean class Clean
{ {
@ -125,7 +126,7 @@ private:
typedef typename MeshType::FaceIterator FaceIterator; typedef typename MeshType::FaceIterator FaceIterator;
typedef typename MeshType::ConstFaceIterator ConstFaceIterator; typedef typename MeshType::ConstFaceIterator ConstFaceIterator;
typedef typename MeshType::FaceContainer FaceContainer; typedef typename MeshType::FaceContainer FaceContainer;
typedef typename vcg::Box3<ScalarType> Box3Type; typedef typename vcg::Box3<ScalarType> Box3Type;
typedef GridStaticPtr<FaceType, ScalarType > TriMeshGrid; typedef GridStaticPtr<FaceType, ScalarType > TriMeshGrid;
typedef Point3<ScalarType> Point3x; typedef Point3<ScalarType> Point3x;
@ -191,7 +192,7 @@ private:
} }
} }
for(FaceIterator fi = m.face.begin(); fi!=m.face.end(); ++fi) for(FaceIterator fi = m.face.begin(); fi!=m.face.end(); ++fi)
if( !(*fi).IsD() ) if( !(*fi).IsD() )
for(k = 0; k < 3; ++k) for(k = 0; k < 3; ++k)
if( mp.find( (typename MeshType::VertexPointer)(*fi).V(k) ) != mp.end() ) if( mp.find( (typename MeshType::VertexPointer)(*fi).V(k) ) != mp.end() )
@ -212,7 +213,7 @@ private:
RemoveDegenerateEdge(m); RemoveDegenerateEdge(m);
RemoveDuplicateEdge(m); RemoveDuplicateEdge(m);
} }
return deleted; return deleted;
} }
class SortedPair class SortedPair
@ -239,7 +240,7 @@ private:
unsigned int v[2]; unsigned int v[2];
EdgePointer fp; EdgePointer fp;
}; };
class SortedTriple class SortedTriple
{ {
public: public:
SortedTriple() {} SortedTriple() {}
@ -253,7 +254,7 @@ private:
{ {
return (v[2]!=p.v[2])?(v[2]<p.v[2]): return (v[2]!=p.v[2])?(v[2]<p.v[2]):
(v[1]!=p.v[1])?(v[1]<p.v[1]): (v[1]!=p.v[1])?(v[1]<p.v[1]):
(v[0]<p.v[0]); } (v[0]<p.v[0]); }
bool operator == (const SortedTriple &s) const bool operator == (const SortedTriple &s) const
{ {
@ -375,15 +376,15 @@ private:
/** /**
Degenerate vertices are vertices that have coords with invalid floating point values, Degenerate vertices are vertices that have coords with invalid floating point values,
All the faces incident on deleted vertices are also deleted All the faces incident on deleted vertices are also deleted
*/ */
static int RemoveDegenerateVertex(MeshType& m) static int RemoveDegenerateVertex(MeshType& m)
{ {
VertexIterator vi; VertexIterator vi;
int count_vd = 0; int count_vd = 0;
for(vi=m.vert.begin(); vi!=m.vert.end();++vi) for(vi=m.vert.begin(); vi!=m.vert.end();++vi)
if(math::IsNAN( (*vi).P()[0]) || if(math::IsNAN( (*vi).P()[0]) ||
math::IsNAN( (*vi).P()[1]) || math::IsNAN( (*vi).P()[1]) ||
math::IsNAN( (*vi).P()[2]) ) math::IsNAN( (*vi).P()[2]) )
{ {
count_vd++; count_vd++;
@ -415,9 +416,9 @@ private:
*/ */
static int RemoveDegenerateFace(MeshType& m) static int RemoveDegenerateFace(MeshType& m)
{ {
int count_fd = 0; int count_fd = 0;
for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi) for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi)
if(!(*fi).IsD()) if(!(*fi).IsD())
{ {
if((*fi).V(0) == (*fi).V(1) || if((*fi).V(0) == (*fi).V(1) ||
@ -449,10 +450,10 @@ private:
static int RemoveNonManifoldVertex(MeshType& m) static int RemoveNonManifoldVertex(MeshType& m)
{ {
/*int count_vd = */ /*int count_vd = */
CountNonManifoldVertexFF(m,true); CountNonManifoldVertexFF(m,true);
/*int count_fd = */ /*int count_fd = */
tri::UpdateSelection<MeshType>::FaceFromVertexLoose(m); tri::UpdateSelection<MeshType>::FaceFromVertexLoose(m);
int count_removed = 0; int count_removed = 0;
FaceIterator fi; FaceIterator fi;
for(fi=m.face.begin(); fi!=m.face.end();++fi) for(fi=m.face.begin(); fi!=m.face.end();++fi)
@ -546,9 +547,9 @@ private:
/// Removal of faces that were incident on a non manifold edge. /// Removal of faces that were incident on a non manifold edge.
static int RemoveNonManifoldFace(MeshType& m) static int RemoveNonManifoldFace(MeshType& m)
{ {
FaceIterator fi; FaceIterator fi;
int count_fd = 0; int count_fd = 0;
std::vector<FacePointer> ToDelVec; std::vector<FacePointer> ToDelVec;
for(fi=m.face.begin(); fi!=m.face.end();++fi) for(fi=m.face.begin(); fi!=m.face.end();++fi)
if (!fi->IsD()) if (!fi->IsD())
@ -556,10 +557,10 @@ private:
if ((!IsManifold(*fi,0))|| if ((!IsManifold(*fi,0))||
(!IsManifold(*fi,1))|| (!IsManifold(*fi,1))||
(!IsManifold(*fi,2))) (!IsManifold(*fi,2)))
ToDelVec.push_back(&*fi); ToDelVec.push_back(&*fi);
} }
std::sort(ToDelVec.begin(),ToDelVec.end(),CompareAreaFP()); std::sort(ToDelVec.begin(),ToDelVec.end(),CompareAreaFP());
for(size_t i=0;i<ToDelVec.size();++i) for(size_t i=0;i<ToDelVec.size();++i)
{ {
@ -567,8 +568,8 @@ private:
{ {
FaceType &ff= *ToDelVec[i]; FaceType &ff= *ToDelVec[i];
if ((!IsManifold(ff,0))|| if ((!IsManifold(ff,0))||
(!IsManifold(ff,1))|| (!IsManifold(ff,1))||
(!IsManifold(ff,2))) (!IsManifold(ff,2)))
{ {
for(int j=0;j<3;++j) for(int j=0;j<3;++j)
if(!face::IsBorder<FaceType>(ff,j)) if(!face::IsBorder<FaceType>(ff,j))
@ -579,8 +580,8 @@ private:
} }
} }
} }
return count_fd; return count_fd;
} }
/* /*
The following functions remove faces that are geometrically "bad" according to edges and area criteria. The following functions remove faces that are geometrically "bad" according to edges and area criteria.
@ -589,27 +590,27 @@ private:
These functions can optionally take into account only the selected faces. These functions can optionally take into account only the selected faces.
*/ */
template<bool Selected> template<bool Selected>
static int RemoveFaceOutOfRangeAreaSel(MeshType& m, ScalarType MinAreaThr=0, ScalarType MaxAreaThr=(std::numeric_limits<ScalarType>::max)()) static int RemoveFaceOutOfRangeAreaSel(MeshType& m, ScalarType MinAreaThr=0, ScalarType MaxAreaThr=(std::numeric_limits<ScalarType>::max)())
{ {
FaceIterator fi; FaceIterator fi;
int count_fd = 0; int count_fd = 0;
MinAreaThr*=2; MinAreaThr*=2;
MaxAreaThr*=2; MaxAreaThr*=2;
for(fi=m.face.begin(); fi!=m.face.end();++fi) for(fi=m.face.begin(); fi!=m.face.end();++fi)
if(!(*fi).IsD()) if(!(*fi).IsD())
if(!Selected || (*fi).IsS()) if(!Selected || (*fi).IsS())
{ {
const ScalarType doubleArea=DoubleArea<FaceType>(*fi); const ScalarType doubleArea=DoubleArea<FaceType>(*fi);
if((doubleArea<=MinAreaThr) || (doubleArea>=MaxAreaThr) ) if((doubleArea<=MinAreaThr) || (doubleArea>=MaxAreaThr) )
{ {
Allocator<MeshType>::DeleteFace(m,*fi); Allocator<MeshType>::DeleteFace(m,*fi);
count_fd++; count_fd++;
} }
} }
return count_fd; return count_fd;
} }
// alias for the old style. Kept for backward compatibility // alias for the old style. Kept for backward compatibility
static int RemoveZeroAreaFace(MeshType& m) { return RemoveFaceOutOfRangeArea(m);} static int RemoveZeroAreaFace(MeshType& m) { return RemoveFaceOutOfRangeArea(m);}
// Aliases for the functions that do not look at selection // Aliases for the functions that do not look at selection
@ -622,76 +623,76 @@ private:
* Is the mesh only composed by quadrilaterals? * Is the mesh only composed by quadrilaterals?
*/ */
static bool IsBitQuadOnly(const MeshType &m) static bool IsBitQuadOnly(const MeshType &m)
{ {
typedef typename MeshType::FaceType F; typedef typename MeshType::FaceType F;
if (!HasPerFaceFlags(m)) return false; if (!HasPerFaceFlags(m)) return false;
for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) { for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) {
unsigned int tmp = fi->Flags()&(F::FAUX0|F::FAUX1|F::FAUX2); unsigned int tmp = fi->Flags()&(F::FAUX0|F::FAUX1|F::FAUX2);
if ( tmp != F::FAUX0 && tmp != F::FAUX1 && tmp != F::FAUX2) return false; if ( tmp != F::FAUX0 && tmp != F::FAUX1 && tmp != F::FAUX2) return false;
} }
return true; return true;
} }
/** /**
* Is the mesh only composed by triangles? (non polygonal faces) * Is the mesh only composed by triangles? (non polygonal faces)
*/ */
static bool IsBitTriOnly(const MeshType &m) static bool IsBitTriOnly(const MeshType &m)
{ {
if (!HasPerFaceFlags(m)) return true; if (!HasPerFaceFlags(m)) return true;
for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) { for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) {
if ( if (
!fi->IsD() && fi->IsAnyF() !fi->IsD() && fi->IsAnyF()
) return false; ) return false;
} }
return true; return true;
} }
static bool IsBitPolygonal(const MeshType &m){ static bool IsBitPolygonal(const MeshType &m){
return !IsBitTriOnly(m); return !IsBitTriOnly(m);
} }
/** /**
* Is the mesh only composed by quadrilaterals and triangles? (no pentas, etc) * Is the mesh only composed by quadrilaterals and triangles? (no pentas, etc)
*/ */
static bool IsBitTriQuadOnly(const MeshType &m) static bool IsBitTriQuadOnly(const MeshType &m)
{ {
typedef typename MeshType::FaceType F; typedef typename MeshType::FaceType F;
if (!HasPerFaceFlags(m)) return false; if (!HasPerFaceFlags(m)) return false;
for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) { for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) {
unsigned int tmp = fi->cFlags()&(F::FAUX0|F::FAUX1|F::FAUX2); unsigned int tmp = fi->cFlags()&(F::FAUX0|F::FAUX1|F::FAUX2);
if ( tmp!=F::FAUX0 && tmp!=F::FAUX1 && tmp!=F::FAUX2 && tmp!=0 ) return false; if ( tmp!=F::FAUX0 && tmp!=F::FAUX1 && tmp!=F::FAUX2 && tmp!=0 ) return false;
} }
return true; return true;
} }
/** /**
* How many quadrilaterals? * How many quadrilaterals?
*/ */
static int CountBitQuads(const MeshType &m) static int CountBitQuads(const MeshType &m)
{ {
if (!HasPerFaceFlags(m)) return 0; if (!HasPerFaceFlags(m)) return 0;
typedef typename MeshType::FaceType F; typedef typename MeshType::FaceType F;
int count=0; int count=0;
for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) { for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) {
unsigned int tmp = fi->cFlags()&(F::FAUX0|F::FAUX1|F::FAUX2); unsigned int tmp = fi->cFlags()&(F::FAUX0|F::FAUX1|F::FAUX2);
if ( tmp==F::FAUX0 || tmp==F::FAUX1 || tmp==F::FAUX2) count++; if ( tmp==F::FAUX0 || tmp==F::FAUX1 || tmp==F::FAUX2) count++;
} }
return count / 2; return count / 2;
} }
/** /**
* How many triangles? (non polygonal faces) * How many triangles? (non polygonal faces)
*/ */
static int CountBitTris(const MeshType &m) static int CountBitTris(const MeshType &m)
{ {
if (!HasPerFaceFlags(m)) return m.fn; if (!HasPerFaceFlags(m)) return m.fn;
int count=0; int count=0;
for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) { for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) {
if (!(fi->IsAnyF())) count++; if (!(fi->IsAnyF())) count++;
} }
return count; return count;
} }
/** /**
* How many polygons of any kind? (including triangles) * How many polygons of any kind? (including triangles)
@ -699,15 +700,15 @@ private:
static int CountBitPolygons(const MeshType &m) static int CountBitPolygons(const MeshType &m)
{ {
if (!HasPerFaceFlags(m)) return m.fn; if (!HasPerFaceFlags(m)) return m.fn;
typedef typename MeshType::FaceType F; typedef typename MeshType::FaceType F;
int count = 0; int count = 0;
for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) { for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) {
if (fi->IsF(0)) count++; if (fi->IsF(0)) count++;
if (fi->IsF(1)) count++; if (fi->IsF(1)) count++;
if (fi->IsF(2)) count++; if (fi->IsF(2)) count++;
} }
return m.fn - count/2; return m.fn - count/2;
} }
/** /**
* The number of polygonal faces is * The number of polygonal faces is
@ -717,7 +718,7 @@ private:
* where: * where:
* EN_f is the number of faux edges. * EN_f is the number of faux edges.
* VN_f is the number of faux vertices (e.g vertices completely surrounded by faux edges) * VN_f is the number of faux vertices (e.g vertices completely surrounded by faux edges)
* as a intuitive proof think to a internal vertex that is collapsed onto a border of a polygon: * as a intuitive proof think to a internal vertex that is collapsed onto a border of a polygon:
* it deletes 2 faces, 1 faux edges and 1 vertex so to keep the balance you have to add back the removed vertex. * it deletes 2 faces, 1 faux edges and 1 vertex so to keep the balance you have to add back the removed vertex.
*/ */
static int CountBitLargePolygons(MeshType &m) static int CountBitLargePolygons(MeshType &m)
@ -734,22 +735,22 @@ private:
if (!HasPerFaceFlags(m)) return m.fn; if (!HasPerFaceFlags(m)) return m.fn;
typedef typename MeshType::FaceType F; typedef typename MeshType::FaceType F;
int countE = 0; int countE = 0;
for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD()) { if (!fi->IsD()) {
for(int i=0;i<3;++i) for(int i=0;i<3;++i)
{ {
if (fi->IsF(i)) if (fi->IsF(i))
countE++; countE++;
else else
{ {
fi->V0(i)->SetV(); fi->V0(i)->SetV();
fi->V1(i)->SetV(); fi->V1(i)->SetV();
} }
} }
} }
// Third Loop, count the number of referenced vertexes that are completely surrounded by faux edges. // Third Loop, count the number of referenced vertexes that are completely surrounded by faux edges.
int countV = 0; int countV = 0;
for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
if (!vi->IsD() && !vi->IsV()) countV++; if (!vi->IsD() && !vi->IsV()) countV++;
@ -757,22 +758,22 @@ private:
} }
/** /**
* Checks that the mesh has consistent per-face faux edges * Checks that the mesh has consistent per-face faux edges
* (the ones that merges triangles into larger polygons). * (the ones that merges triangles into larger polygons).
* A border edge should never be faux, and faux edges should always be * A border edge should never be faux, and faux edges should always be
* reciprocated by another faux edges. * reciprocated by another faux edges.
* It requires FF adjacency. * It requires FF adjacency.
*/ */
static bool HasConsistentPerFaceFauxFlag(const MeshType &m) static bool HasConsistentPerFaceFauxFlag(const MeshType &m)
{ {
RequireFFAdjacency(m); RequireFFAdjacency(m);
RequirePerFaceFlags(m); RequirePerFaceFlags(m);
for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if(!(*fi).IsD()) if(!(*fi).IsD())
for (int k=0; k<3; k++) for (int k=0; k<3; k++)
if( fi->IsF(k) != fi->cFFp(k)->IsF(fi->cFFi(k)) ) { if( fi->IsF(k) != fi->cFFp(k)->IsF(fi->cFFi(k)) ) {
return false; return false;
} }
// non-reciprocal faux edge! // non-reciprocal faux edge!
@ -788,12 +789,12 @@ private:
for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if(!(*fi).IsD()) if(!(*fi).IsD())
for (int k=0; k<3; k++) for (int k=0; k<3; k++)
{ {
VertexType *v0=(*fi).V(0); VertexType *v0=(*fi).V(0);
VertexType *v1=(*fi).V(1); VertexType *v1=(*fi).V(1);
VertexType *v2=(*fi).V(2); VertexType *v2=(*fi).V(2);
if ((v0==v1)||(v0==v2)||(v1==v2)) if ((v0==v1)||(v0==v2)||(v1==v2))
return false; return false;
} }
return true; return true;
@ -894,14 +895,14 @@ private:
* typical situation two cones connected by one vertex. * typical situation two cones connected by one vertex.
*/ */
static int CountNonManifoldVertexFF( MeshType & m, bool selectVert = true ) static int CountNonManifoldVertexFF( MeshType & m, bool selectVert = true )
{ {
RequireFFAdjacency(m); RequireFFAdjacency(m);
if(selectVert) UpdateSelection<MeshType>::VertexClear(m); if(selectVert) UpdateSelection<MeshType>::VertexClear(m);
int nonManifoldCnt=0; int nonManifoldCnt=0;
SimpleTempData<typename MeshType::VertContainer, int > TD(m.vert,0); SimpleTempData<typename MeshType::VertContainer, int > TD(m.vert,0);
// First Loop, just count how many faces are incident on a vertex and store it in the TemporaryData Counter. // First Loop, just count how many faces are incident on a vertex and store it in the TemporaryData Counter.
FaceIterator fi; FaceIterator fi;
for (fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) for (fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD())
{ {
@ -910,7 +911,7 @@ private:
TD[(*fi).V(2)]++; TD[(*fi).V(2)]++;
} }
tri::UpdateFlags<MeshType>::VertexClearV(m); tri::UpdateFlags<MeshType>::VertexClearV(m);
// Second Loop. // Second Loop.
// mark out of the game the vertexes that are incident on non manifold edges. // mark out of the game the vertexes that are incident on non manifold edges.
for (fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) for (fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD())
@ -923,17 +924,17 @@ private:
} }
// Third Loop, for safe vertexes, check that the number of faces that you can reach starting // Third Loop, for safe vertexes, check that the number of faces that you can reach starting
// from it and using FF is the same of the previously counted. // from it and using FF is the same of the previously counted.
for (fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) for (fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD())
{ {
for(int i=0;i<3;i++) if(!(*fi).V(i)->IsV()){ for(int i=0;i<3;i++) if(!(*fi).V(i)->IsV()){
(*fi).V(i)->SetV(); (*fi).V(i)->SetV();
face::Pos<FaceType> pos(&(*fi),i); face::Pos<FaceType> pos(&(*fi),i);
int starSizeFF = pos.NumberOfIncidentFaces(); int starSizeFF = pos.NumberOfIncidentFaces();
if (starSizeFF != TD[(*fi).V(i)]) if (starSizeFF != TD[(*fi).V(i)])
{ {
if(selectVert) (*fi).V(i)->SetS(); if(selectVert) (*fi).V(i)->SetS();
nonManifoldCnt++; nonManifoldCnt++;
} }
} }
@ -945,8 +946,8 @@ private:
{ {
count_e=0; count_e=0;
boundary_e=0; boundary_e=0;
UpdateFlags<MeshType>::FaceClearV(m); UpdateFlags<MeshType>::FaceClearV(m);
FaceIterator fi; FaceIterator fi;
vcg::face::Pos<FaceType> he; vcg::face::Pos<FaceType> he;
vcg::face::Pos<FaceType> hei; vcg::face::Pos<FaceType> hei;
bool counted =false; bool counted =false;
@ -954,15 +955,15 @@ private:
{ {
if(!((*fi).IsD())) if(!((*fi).IsD()))
{ {
(*fi).SetV(); (*fi).SetV();
count_e +=3; //assume that we have to increase the number of edges with three count_e +=3; //assume that we have to increase the number of edges with three
for(int j=0; j<3; j++) for(int j=0; j<3; j++)
{ {
if (face::IsBorder(*fi,j)) //If this edge is a border edge if (face::IsBorder(*fi,j)) //If this edge is a border edge
boundary_e++; // then increase the number of boundary edges boundary_e++; // then increase the number of boundary edges
else if (IsManifold(*fi,j))//If this edge is manifold else if (IsManifold(*fi,j))//If this edge is manifold
{ {
if((*fi).FFp(j)->IsV()) //If the face on the other side of the edge is already selected if((*fi).FFp(j)->IsV()) //If the face on the other side of the edge is already selected
count_e--; // we counted one edge twice count_e--; // we counted one edge twice
} }
else//We have a non-manifold edge else//We have a non-manifold edge
@ -972,7 +973,7 @@ private:
he.NextF(); he.NextF();
while (he.f!=hei.f)// so we have to iterate all faces that are connected to this edge while (he.f!=hei.f)// so we have to iterate all faces that are connected to this edge
{ {
if (he.f->IsV())// if one of the other faces was already visited than this edge was counted already. if (he.f->IsV())// if one of the other faces was already visited than this edge was counted already.
{ {
counted=true; counted=true;
break; break;
@ -996,14 +997,14 @@ private:
static int CountHoles( MeshType & m) static int CountHoles( MeshType & m)
{ {
int numholev=0; int numholev=0;
FaceIterator fi; FaceIterator fi;
FaceIterator gi; FaceIterator gi;
vcg::face::Pos<FaceType> he; vcg::face::Pos<FaceType> he;
vcg::face::Pos<FaceType> hei; vcg::face::Pos<FaceType> hei;
std::vector< std::vector<Point3x> > holes; //indices of vertices std::vector< std::vector<Point3x> > holes; //indices of vertices
vcg::tri::UpdateFlags<MeshType>::VertexClearS(m); vcg::tri::UpdateFlags<MeshType>::VertexClearS(m);
@ -1015,10 +1016,10 @@ private:
{ {
if(fi->V(j)->IsS()) continue; if(fi->V(j)->IsS()) continue;
if(face::IsBorder(*fi,j))//found an unvisited border edge if(face::IsBorder(*fi,j))//found an unvisited border edge
{ {
he.Set(&(*fi),j,fi->V(j)); //set the face-face iterator to the current face, edge and vertex he.Set(&(*fi),j,fi->V(j)); //set the face-face iterator to the current face, edge and vertex
std::vector<Point3x> hole; //start of a new hole std::vector<Point3x> hole; //start of a new hole
hole.push_back(fi->P(j)); // including the first vertex hole.push_back(fi->P(j)); // including the first vertex
numholev++; numholev++;
he.v->SetS(); //set the current vertex as selected he.v->SetS(); //set the current vertex as selected
@ -1031,7 +1032,7 @@ private:
if(he.v->IsS())//check if this vertex was selected already, because then we have an additional hole. if(he.v->IsS())//check if this vertex was selected already, because then we have an additional hole.
{ {
//cut and paste the additional hole. //cut and paste the additional hole.
std::vector<Point3x> hole2; std::vector<Point3x> hole2;
int index = static_cast<int>(find(hole.begin(),hole.end(),newpoint) int index = static_cast<int>(find(hole.begin(),hole.end(),newpoint)
- hole.begin()); - hole.begin());
for(unsigned int i=index; i<hole.size(); i++) for(unsigned int i=index; i<hole.size(); i++)
@ -1063,11 +1064,11 @@ private:
return ConnectedComponents(m,CCV); return ConnectedComponents(m,CCV);
} }
static int ConnectedComponents(MeshType &m, std::vector< std::pair<int,FacePointer> > &CCV) static int ConnectedComponents(MeshType &m, std::vector< std::pair<int,FacePointer> > &CCV)
{ {
FaceIterator fi; FaceIterator fi;
FacePointer l; FacePointer l;
CCV.clear(); CCV.clear();
for(fi=m.face.begin();fi!=m.face.end();++fi) for(fi=m.face.begin();fi!=m.face.end();++fi)
(*fi).ClearS(); (*fi).ClearS();
@ -1075,37 +1076,37 @@ private:
int Compindex=0; int Compindex=0;
std::stack<FacePointer> sf; std::stack<FacePointer> sf;
FacePointer fpt=&*(m.face.begin()); FacePointer fpt=&*(m.face.begin());
for(fi=m.face.begin();fi!=m.face.end();++fi) for(fi=m.face.begin();fi!=m.face.end();++fi)
{ {
if(!((*fi).IsD()) && !(*fi).IsS()) if(!((*fi).IsD()) && !(*fi).IsS())
{ {
(*fi).SetS(); (*fi).SetS();
CCV.push_back(std::make_pair(0,&*fi)); CCV.push_back(std::make_pair(0,&*fi));
sf.push(&*fi); sf.push(&*fi);
while (!sf.empty()) while (!sf.empty())
{ {
fpt=sf.top(); fpt=sf.top();
++CCV.back().first; ++CCV.back().first;
sf.pop(); sf.pop();
for(int j=0;j<3;++j) for(int j=0;j<3;++j)
{ {
if( !face::IsBorder(*fpt,j) ) if( !face::IsBorder(*fpt,j) )
{ {
l=fpt->FFp(j); l=fpt->FFp(j);
if( !(*l).IsS() ) if( !(*l).IsS() )
{ {
(*l).SetS(); (*l).SetS();
sf.push(l); sf.push(l);
} }
} }
} }
} }
Compindex++; Compindex++;
} }
} }
assert(int(CCV.size())==Compindex); assert(int(CCV.size())==Compindex);
return Compindex; return Compindex;
} }
/** /**
@ -1115,7 +1116,7 @@ private:
the largest number of non-intersecting simple closed curves that can be the largest number of non-intersecting simple closed curves that can be
drawn on the surface without separating it. drawn on the surface without separating it.
Roughly speaking, it is the number of holes in a surface. Roughly speaking, it is the number of holes in a surface.
The genus g of a closed surface, also called the geometric genus, is related to the The genus g of a closed surface, also called the geometric genus, is related to the
Euler characteristic by the relation $chi$ by $chi==2-2g$. Euler characteristic by the relation $chi$ by $chi==2-2g$.
@ -1217,10 +1218,10 @@ private:
} }
} }
// static void IsOrientedMesh(MeshType &m, bool &Oriented, bool &Orientable) // static void IsOrientedMesh(MeshType &m, bool &Oriented, bool &Orientable)
static void OrientCoherentlyMesh(MeshType &m, bool &Oriented, bool &Orientable) static void OrientCoherentlyMesh(MeshType &m, bool &Oriented, bool &Orientable)
{ {
RequireFFAdjacency(m); RequireFFAdjacency(m);
assert(&Oriented != &Orientable); assert(&Oriented != &Orientable);
// This algorithms require FF topology initialized // This algorithms require FF topology initialized
assert(m.face.back().FFp(0)); assert(m.face.back().FFp(0));
@ -1234,7 +1235,7 @@ private:
for (fi = m.face.begin(); fi != m.face.end(); ++fi) for (fi = m.face.begin(); fi != m.face.end(); ++fi)
fi->ClearS(); fi->ClearS();
// initialize stack // initialize stack
std::stack<FacePointer> faces; std::stack<FacePointer> faces;
// for each face of the mesh // for each face of the mesh
@ -1265,7 +1266,7 @@ private:
{ {
if (!CheckOrientation(*fpaux, iaux)) if (!CheckOrientation(*fpaux, iaux))
{ {
Oriented = false; Oriented = false;
if (!fpaux->IsS()) if (!fpaux->IsS())
{ {
@ -1273,10 +1274,10 @@ private:
assert(CheckOrientation(*fpaux, iaux)); assert(CheckOrientation(*fpaux, iaux));
} }
else else
{ {
Orientable = false; Orientable = false;
break; break;
} }
} }
// put the oriented face into the stack // put the oriented face into the stack
@ -1294,25 +1295,25 @@ private:
if (!Orientable) break; if (!Orientable) break;
} }
} }
/// Flip the orientation of the whole mesh flipping all the faces (by swapping the first two vertices) /// Flip the orientation of the whole mesh flipping all the faces (by swapping the first two vertices)
static void FlipMesh(MeshType &m, bool selected=false) static void FlipMesh(MeshType &m, bool selected=false)
{ {
for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD()) for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if(!(*fi).IsD())
if(!selected || (*fi).IsS()) if(!selected || (*fi).IsS())
{ {
face::SwapEdge<FaceType,false>((*fi), 0); face::SwapEdge<FaceType,false>((*fi), 0);
if (HasPerWedgeTexCoord(m)) if (HasPerWedgeTexCoord(m))
std::swap((*fi).WT(0),(*fi).WT(1)); std::swap((*fi).WT(0),(*fi).WT(1));
} }
} }
/// Flip a mesh so that its normals are orented outside. /// Flip a mesh so that its normals are orented outside.
/// Just for safety it uses a voting scheme. /// Just for safety it uses a voting scheme.
/// It assumes that /// It assumes that
/// mesh has already has coherent normals. /// mesh has already has coherent normals.
/// mesh is watertight and signle component. /// mesh is watertight and signle component.
static bool FlipNormalOutside(MeshType &m) static bool FlipNormalOutside(MeshType &m)
{ {
if(m.vert.empty()) return false; if(m.vert.empty()) return false;
tri::UpdateNormal<MeshType>::PerVertexAngleWeighted(m); tri::UpdateNormal<MeshType>::PerVertexAngleWeighted(m);
tri::UpdateNormal<MeshType>::NormalizePerVertex(m); tri::UpdateNormal<MeshType>::NormalizePerVertex(m);
@ -1417,7 +1418,7 @@ private:
RequireFFAdjacency(m); RequireFFAdjacency(m);
RequirePerVertexMark(m); RequirePerVertexMark(m);
//Counters for logging and convergence //Counters for logging and convergence
int count, total = 0; int count, total = 0;
do { do {
tri::UpdateTopology<MeshType>::FaceFace(m); tri::UpdateTopology<MeshType>::FaceFace(m);
@ -1464,7 +1465,7 @@ private:
{ {
RequirePerVertexMark(m); RequirePerVertexMark(m);
//Counters for logging and convergence //Counters for logging and convergence
int count, total = 0; int count, total = 0;
do { do {
tri::UnMarkAll(m); tri::UnMarkAll(m);
@ -1498,41 +1499,41 @@ private:
return total; return total;
} }
static bool SelfIntersections(MeshType &m, std::vector<FaceType*> &ret) static bool SelfIntersections(MeshType &m, std::vector<FaceType*> &ret)
{ {
RequirePerFaceMark(m); RequirePerFaceMark(m);
Box3< ScalarType> bbox; Box3< ScalarType> bbox;
TriMeshGrid gM; TriMeshGrid gM;
ret.clear(); ret.clear();
FaceIterator fi; FaceIterator fi;
int referredBit = FaceType::NewBitFlag(); int referredBit = FaceType::NewBitFlag();
tri::UpdateFlags<MeshType>::FaceClear(m,referredBit); tri::UpdateFlags<MeshType>::FaceClear(m,referredBit);
std::vector<FaceType*> inBox; std::vector<FaceType*> inBox;
gM.Set(m.face.begin(),m.face.end()); gM.Set(m.face.begin(),m.face.end());
for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
{ {
(*fi).SetUserBit(referredBit); (*fi).SetUserBit(referredBit);
(*fi).GetBBox(bbox); (*fi).GetBBox(bbox);
vcg::tri::GetInBoxFace(m, gM, bbox,inBox); vcg::tri::GetInBoxFace(m, gM, bbox,inBox);
bool Intersected=false; bool Intersected=false;
typename std::vector<FaceType*>::iterator fib; typename std::vector<FaceType*>::iterator fib;
for(fib=inBox.begin();fib!=inBox.end();++fib) for(fib=inBox.begin();fib!=inBox.end();++fib)
{ {
if(!(*fib)->IsUserBit(referredBit) && (*fib != &*fi) ) if(!(*fib)->IsUserBit(referredBit) && (*fib != &*fi) )
if(TestFaceFaceIntersection(&*fi,*fib)){ if(TestFaceFaceIntersection(&*fi,*fib)){
ret.push_back(*fib); ret.push_back(*fib);
if(!Intersected) { if(!Intersected) {
ret.push_back(&*fi); ret.push_back(&*fi);
Intersected=true; Intersected=true;
} }
} }
} }
inBox.clear(); inBox.clear();
} }
FaceType::DeleteBitFlag(referredBit); FaceType::DeleteBitFlag(referredBit);
return (ret.size()>0); return (ret.size()>0);
} }
@ -1582,10 +1583,10 @@ private:
for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if(!(*fi).IsD()) if(!(*fi).IsD())
{ FaceType &f=(*fi); { FaceType &f=(*fi);
if( ! ( (f.WT(0).N() == f.WT(1).N()) && (f.WT(0).N() == (*fi).WT(2).N()) ) ) if( ! ( (f.WT(0).N() == f.WT(1).N()) && (f.WT(0).N() == (*fi).WT(2).N()) ) )
return false; // all the vertices must have the same index. return false; // all the vertices must have the same index.
if((*fi).WT(0).N() <0) return false; // no undefined texture should be allowed if((*fi).WT(0).N() <0) return false; // no undefined texture should be allowed
} }
return true; return true;
} }
@ -1614,7 +1615,7 @@ private:
if the faces share only a vertex, the opposite edge is tested against the face if the faces share only a vertex, the opposite edge is tested against the face
*/ */
static bool TestFaceFaceIntersection(FaceType *f0,FaceType *f1) static bool TestFaceFaceIntersection(FaceType *f0,FaceType *f1)
{ {
assert(f0!=f1); assert(f0!=f1);
int sv = face::CountSharedVertex(f0,f1); int sv = face::CountSharedVertex(f0,f1);
if(sv==3) return true; if(sv==3) return true;
@ -1630,48 +1631,48 @@ private:
if(vcg::IntersectionSegmentTriangle(Segment3<ScalarType>((*f0).V1(i0)->P()*0.5+shP,(*f0).V2(i0)->P()*0.5+shP), *f1, a, b) ) return true; if(vcg::IntersectionSegmentTriangle(Segment3<ScalarType>((*f0).V1(i0)->P()*0.5+shP,(*f0).V2(i0)->P()*0.5+shP), *f1, a, b) ) return true;
if(vcg::IntersectionSegmentTriangle(Segment3<ScalarType>((*f1).V1(i1)->P()*0.5+shP,(*f1).V2(i1)->P()*0.5+shP), *f0, a, b) ) return true; if(vcg::IntersectionSegmentTriangle(Segment3<ScalarType>((*f1).V1(i1)->P()*0.5+shP,(*f1).V2(i1)->P()*0.5+shP), *f0, a, b) ) return true;
} }
return false; return false;
} }
/** /**
This function merge all the vertices that are closer than the given radius This function merge all the vertices that are closer than the given radius
*/ */
static int MergeCloseVertex(MeshType &m, const ScalarType radius) static int MergeCloseVertex(MeshType &m, const ScalarType radius)
{ {
int mergedCnt=0; int mergedCnt=0;
mergedCnt = ClusterVertex(m,radius); mergedCnt = ClusterVertex(m,radius);
RemoveDuplicateVertex(m,true); RemoveDuplicateVertex(m,true);
return mergedCnt; return mergedCnt;
} }
static int ClusterVertex(MeshType &m, const ScalarType radius) static int ClusterVertex(MeshType &m, const ScalarType radius)
{ {
if(m.vn==0) return 0; if(m.vn==0) return 0;
// some spatial indexing structure does not work well with deleted vertices... // some spatial indexing structure does not work well with deleted vertices...
tri::Allocator<MeshType>::CompactVertexVector(m); tri::Allocator<MeshType>::CompactVertexVector(m);
typedef vcg::SpatialHashTable<VertexType, ScalarType> SampleSHT; typedef vcg::SpatialHashTable<VertexType, ScalarType> SampleSHT;
SampleSHT sht; SampleSHT sht;
tri::VertTmark<MeshType> markerFunctor; tri::VertTmark<MeshType> markerFunctor;
typedef vcg::vertex::PointDistanceFunctor<ScalarType> VDistFunct; typedef vcg::vertex::PointDistanceFunctor<ScalarType> VDistFunct;
std::vector<VertexType*> closests; std::vector<VertexType*> closests;
int mergedCnt=0; int mergedCnt=0;
sht.Set(m.vert.begin(), m.vert.end()); sht.Set(m.vert.begin(), m.vert.end());
UpdateFlags<MeshType>::VertexClearV(m); UpdateFlags<MeshType>::VertexClearV(m);
for(VertexIterator viv = m.vert.begin(); viv!= m.vert.end(); ++viv) for(VertexIterator viv = m.vert.begin(); viv!= m.vert.end(); ++viv)
if(!(*viv).IsD() && !(*viv).IsV()) if(!(*viv).IsD() && !(*viv).IsV())
{ {
(*viv).SetV(); (*viv).SetV();
Point3<ScalarType> p = viv->cP(); Point3<ScalarType> p = viv->cP();
Box3<ScalarType> bb(p-Point3<ScalarType>(radius,radius,radius),p+Point3<ScalarType>(radius,radius,radius)); Box3<ScalarType> bb(p-Point3<ScalarType>(radius,radius,radius),p+Point3<ScalarType>(radius,radius,radius));
GridGetInBox(sht, markerFunctor, bb, closests); GridGetInBox(sht, markerFunctor, bb, closests);
// qDebug("Vertex %i has %i closest", &*viv - &*m.vert.begin(),closests.size()); // qDebug("Vertex %i has %i closest", &*viv - &*m.vert.begin(),closests.size());
for(size_t i=0; i<closests.size(); ++i) for(size_t i=0; i<closests.size(); ++i)
{ {
ScalarType dist = Distance(p,closests[i]->cP()); ScalarType dist = Distance(p,closests[i]->cP());
if(dist < radius && !closests[i]->IsV()) if(dist < radius && !closests[i]->IsV())
{ {
// printf("%f %f \n",dist,radius); // printf("%f %f \n",dist,radius);
mergedCnt++; mergedCnt++;
closests[i]->SetV(); closests[i]->SetV();
@ -1687,7 +1688,7 @@ static std::pair<int,int> RemoveSmallConnectedComponentsSize(MeshType &m, int m
{ {
std::vector< std::pair<int, typename MeshType::FacePointer> > CCV; std::vector< std::pair<int, typename MeshType::FacePointer> > CCV;
int TotalCC=ConnectedComponents(m, CCV); int TotalCC=ConnectedComponents(m, CCV);
int DeletedCC=0; int DeletedCC=0;
ConnectedIterator<MeshType> ci; ConnectedIterator<MeshType> ci;
for(unsigned int i=0;i<CCV.size();++i) for(unsigned int i=0;i<CCV.size();++i)
@ -1695,16 +1696,16 @@ static std::pair<int,int> RemoveSmallConnectedComponentsSize(MeshType &m, int m
std::vector<typename MeshType::FacePointer> FPV; std::vector<typename MeshType::FacePointer> FPV;
if(CCV[i].first<maxCCSize) if(CCV[i].first<maxCCSize)
{ {
DeletedCC++; DeletedCC++;
for(ci.start(m,CCV[i].second);!ci.completed();++ci) for(ci.start(m,CCV[i].second);!ci.completed();++ci)
FPV.push_back(*ci); FPV.push_back(*ci);
typename std::vector<typename MeshType::FacePointer>::iterator fpvi; typename std::vector<typename MeshType::FacePointer>::iterator fpvi;
for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi) for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi)
Allocator<MeshType>::DeleteFace(m,(**fpvi)); Allocator<MeshType>::DeleteFace(m,(**fpvi));
} }
} }
return std::make_pair<int,int>(TotalCC,DeletedCC); return std::make_pair(TotalCC,DeletedCC);
} }
@ -1729,13 +1730,13 @@ static std::pair<int,int> RemoveSmallConnectedComponentsDiameter(MeshType &m, Sc
} }
if(bb.Diag()<maxDiameter) if(bb.Diag()<maxDiameter)
{ {
DeletedCC++; DeletedCC++;
typename std::vector<typename MeshType::FacePointer>::iterator fpvi; typename std::vector<typename MeshType::FacePointer>::iterator fpvi;
for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi) for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi)
tri::Allocator<MeshType>::DeleteFace(m,(**fpvi)); tri::Allocator<MeshType>::DeleteFace(m,(**fpvi));
} }
} }
return std::make_pair<int,int>(TotalCC,DeletedCC); return std::make_pair(TotalCC,DeletedCC);
} }
/// Remove the connected components greater than a given diameter /// Remove the connected components greater than a given diameter
@ -1759,13 +1760,13 @@ static std::pair<int,int> RemoveHugeConnectedComponentsDiameter(MeshType &m, Sca
} }
if(bb.Diag()>minDiameter) if(bb.Diag()>minDiameter)
{ {
DeletedCC++; DeletedCC++;
typename std::vector<typename MeshType::FacePointer>::iterator fpvi; typename std::vector<typename MeshType::FacePointer>::iterator fpvi;
for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi) for(fpvi=FPV.begin(); fpvi!=FPV.end(); ++fpvi)
tri::Allocator<MeshType>::DeleteFace(m,(**fpvi)); tri::Allocator<MeshType>::DeleteFace(m,(**fpvi));
} }
} }
return std::make_pair<int,int>(TotalCC,DeletedCC); return std::make_pair(TotalCC,DeletedCC);
} }
}; // end class }; // end class