Heavily restructured clustering class to allow also a subsampling strategy that allow the fast extraction of a well spaced subset of vertices

This commit is contained in:
Paolo Cignoni 2009-07-14 08:57:05 +00:00
parent a5cb113561
commit d71d110703
1 changed files with 129 additions and 57 deletions

View File

@ -120,41 +120,63 @@ public:
#endif #endif
// //
template<class MeshType> template<class MeshType >
class AverageCell class NearestToCenter
{ {
typedef typename MeshType::ScalarType ScalarType;
typedef typename MeshType::CoordType CoordType; typedef typename MeshType::CoordType CoordType;
typedef typename MeshType::FaceType FaceType; typedef typename MeshType::VertexType VertexType;
typedef typename MeshType::FaceType FaceType;
typedef BasicGrid<typename MeshType::ScalarType> GridType;
public: public:
inline void Add(MeshType &m, FaceType &f, int i) inline void AddVertex(MeshType &m, GridType &g, Point3i &pi, VertexType &v)
{ {
p+=f.cV(i)->cP(); CoordType c;
// we prefer to use the un-normalized face normal so small faces facing away are dropped out g.IPiToBoxCenter(pi,c);
// and the resulting average is weighed with the size of the faces falling here. ScalarType newDist = Distance(c,v.cP());
n+=f.cN(); if(!valid || newDist < bestDist)
cnt++; {
} valid=true;
AverageCell(): p(0,0,0), n(0,0,0),cnt(0){} bestDist=newDist;
CoordType p; bestPos=v.cP();
CoordType n; bestN=v.cN();
int cnt; orig=&v;
int id; }
}
inline void AddFaceVertex(MeshType &m, FaceType &f, int i) { assert(0);}
NearestToCenter(): valid(false){}
CoordType bestPos;
CoordType bestN;
ScalarType bestDist;
bool valid;
int id;
VertexType *orig;
CoordType Pos() const CoordType Pos() const
{ {
return p/cnt; assert(valid);
return bestPos;
} }
Color4b Col() const {return Color4b::White;} Color4b Col() const {return Color4b::White;}
CoordType N() const {return bestN;}
VertexType * Ptr() const {return orig;}
}; };
template<class MeshType> template<class MeshType>
class AverageColorCell class AverageColorCell
{ {
typedef typename MeshType::CoordType CoordType; typedef typename MeshType::CoordType CoordType;
typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FaceType FaceType;
typedef typename MeshType::VertexType VertexType;
typedef BasicGrid<typename MeshType::ScalarType> GridType;
public: public:
inline void Add(MeshType &m, FaceType &f, int i) inline void AddFaceVertex(MeshType &m, FaceType &f, int i)
{ {
p+=f.cV(i)->cP(); p+=f.cV(i)->cP();
c+=CoordType(f.cV(i)->C()[0],f.cV(i)->C()[1],f.cV(i)->C()[2]); c+=CoordType(f.cV(i)->C()[0],f.cV(i)->C()[1],f.cV(i)->C()[2]);
@ -164,6 +186,14 @@ class AverageColorCell
n+=f.cN(); n+=f.cN();
cnt++; cnt++;
} }
inline void AddVertex(MeshType &m, GridType &g, Point3i &pi, VertexType &v)
{
p+=v.cP();
n+=v.cN();
c+=CoordType(v.C()[0],v.C()[1],v.C()[2]);
cnt++;
}
AverageColorCell(): p(0,0,0), n(0,0,0), c(0,0,0),cnt(0){} AverageColorCell(): p(0,0,0), n(0,0,0), c(0,0,0),cnt(0){}
CoordType p; CoordType p;
CoordType n; CoordType n;
@ -175,17 +205,16 @@ class AverageColorCell
return Color4b(c[0]/cnt,c[1]/cnt,c[2]/cnt,255); return Color4b(c[0]/cnt,c[1]/cnt,c[2]/cnt,255);
} }
CoordType Pos() const CoordType N() const {return n;}
{ VertexType * Ptr() const {return 0;}
return p/cnt; CoordType Pos() const { return p/cnt; }
}
}; };
/* /*
Metodo di clustering Metodo di clustering
*/ */
template<class MeshType, class CellType, bool Selected=true> template<class MeshType, class CellType>
class Clustering class Clustering
{ {
public: public:
@ -205,7 +234,8 @@ class Clustering
bool DuplicateFaceParam; bool DuplicateFaceParam;
class SimpleTri // This class keeps the references to the three cells where a face has its vertexes.
class SimpleTri
{ {
public: public:
CellType *v[3]; CellType *v[3];
@ -251,6 +281,8 @@ class Clustering
void Init(Box3<ScalarType> _mbb, int _size, ScalarType _cellsize=0) void Init(Box3<ScalarType> _mbb, int _size, ScalarType _cellsize=0)
{ {
GridCell.clear();
TriSet.clear();
Grid.bbox=_mbb; Grid.bbox=_mbb;
///inflate the bb calculated ///inflate the bb calculated
ScalarType infl = (_cellsize == (ScalarType)0) ? (Grid.bbox.Diag() / _size) : (_cellsize); ScalarType infl = (_cellsize == (ScalarType)0) ? (Grid.bbox.Diag() / _size) : (_cellsize);
@ -284,41 +316,81 @@ class Clustering
STDEXT::hash_map<HashedPoint3i,CellType> GridCell; STDEXT::hash_map<HashedPoint3i,CellType> GridCell;
void Add(MeshType &m)
void AddPointSet(MeshType &m, bool UseOnlySelected=false)
{
VertexIterator vi;
for(vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD())
if(!UseOnlySelected || (*vi).IsS())
{
HashedPoint3i pi;
Grid.PToIP((*vi).cP(), pi );
GridCell[pi].AddVertex(m,Grid,pi,*(vi));
}
}
void AddMesh(MeshType &m)
{ {
FaceIterator fi; FaceIterator fi;
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()) HashedPoint3i pi;
{ SimpleTri st;
continue; for(int i=0;i<3;++i)
} {
HashedPoint3i pi; Grid.PToIP((*fi).cV(i)->cP(), pi );
SimpleTri st; st.v[i]=&(GridCell[pi]);
for(int i=0;i<3;++i) st.v[i]->AddFaceVertex(m,*(fi),i);
{ }
Grid.PToIP((*fi).cV(i)->cP(), pi ); if( (st.v[0]!=st.v[1]) && (st.v[0]!=st.v[2]) && (st.v[1]!=st.v[2]) )
st.v[i]=&(GridCell[pi]); { // if we allow the duplication of faces we sort the vertex only partially (to maintain the original face orientation)
st.v[i]->Add(m,*(fi),i); if(DuplicateFaceParam) st.sortOrient();
} else st.sort();
if( (st.v[0]!=st.v[1]) && (st.v[0]!=st.v[2]) && (st.v[1]!=st.v[2]) ) TriSet.insert(st);
{ // if we allow the duplication of faces we sort the vertex only partially (to maintain the original face orientation) }
if(DuplicateFaceParam) st.sortOrient(); // printf("Inserted %8i triangles, clustered to %8i tri and %i cells\n",distance(m.face.begin(),fi),TriSet.size(),GridCell.size());
else st.sort(); }
TriSet.insert(st);
}
// printf("Inserted %8i triangles, clustered to %8i tri and %i cells\n",distance(m.face.begin(),fi),TriSet.size(),GridCell.size());
}
} }
//
void Extract(MeshType &m) void SelectPointSet(MeshType &m)
{
typename STDEXT::hash_map<HashedPoint3i,CellType>::iterator gi;
UpdateSelection<CMeshO>::ClearVertex(m);
for(gi=GridCell.begin();gi!=GridCell.end();++gi)
{
VertexType *ptr=(*gi).second.Ptr();
if(ptr && ( ptr >= &*m.vert.begin() ) && ( ptr < &*m.vert.end() ) )
ptr->SetS();
}
}
void ExtractPointSet(MeshType &m)
{ {
m.Clear(); m.Clear();
if (TriSet.empty() || GridCell.empty()) if (GridCell.empty()) return;
{
return; Allocator<MeshType>::AddVertices(m,GridCell.size());
} typename STDEXT::hash_map<HashedPoint3i,CellType>::iterator gi;
int i=0;
for(gi=GridCell.begin();gi!=GridCell.end();++gi)
{
m.vert[i].P()=(*gi).second.Pos();
m.vert[i].N()=(*gi).second.N();
m.vert[i].C()=(*gi).second.Col();
++i;
}
}
void ExtractMesh(MeshType &m)
{
m.Clear();
if (TriSet.empty() || GridCell.empty())
{
return;
}
Allocator<MeshType>::AddVertices(m,GridCell.size()); Allocator<MeshType>::AddVertices(m,GridCell.size());
typename STDEXT::hash_map<HashedPoint3i,CellType>::iterator gi; typename STDEXT::hash_map<HashedPoint3i,CellType>::iterator gi;
@ -345,9 +417,9 @@ class Clustering
{ {
CoordType N=vcg::Normal(m.face[i]); CoordType N=vcg::Normal(m.face[i]);
int badOrient=0; int badOrient=0;
if( N.dot((*ti).v[0]->n) <0) ++badOrient; if( N.dot((*ti).v[0]->N()) <0) ++badOrient;
if( N.dot((*ti).v[1]->n) <0) ++badOrient; if( N.dot((*ti).v[1]->N()) <0) ++badOrient;
if( N.dot((*ti).v[2]->n) <0) ++badOrient; if( N.dot((*ti).v[2]->N()) <0) ++badOrient;
if(badOrient>2) if(badOrient>2)
std::swap(m.face[i].V(0),m.face[i].V(1)); std::swap(m.face[i].V(0),m.face[i].V(1));
} }