removed a useless template specialization to a few std::make_pair
This commit is contained in:
parent
246345bf19
commit
3a9a72c098
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue