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:
parent
a5cb113561
commit
d71d110703
|
|
@ -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::VertexType VertexType;
|
||||||
typedef typename MeshType::FaceType FaceType;
|
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;
|
||||||
|
bestDist=newDist;
|
||||||
|
bestPos=v.cP();
|
||||||
|
bestN=v.cN();
|
||||||
|
orig=&v;
|
||||||
}
|
}
|
||||||
AverageCell(): p(0,0,0), n(0,0,0),cnt(0){}
|
}
|
||||||
CoordType p;
|
inline void AddFaceVertex(MeshType &m, FaceType &f, int i) { assert(0);}
|
||||||
CoordType n;
|
NearestToCenter(): valid(false){}
|
||||||
int cnt;
|
|
||||||
|
CoordType bestPos;
|
||||||
|
CoordType bestN;
|
||||||
|
ScalarType bestDist;
|
||||||
|
bool valid;
|
||||||
int id;
|
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,6 +234,7 @@ class Clustering
|
||||||
|
|
||||||
bool DuplicateFaceParam;
|
bool DuplicateFaceParam;
|
||||||
|
|
||||||
|
// This class keeps the references to the three cells where a face has its vertexes.
|
||||||
class SimpleTri
|
class SimpleTri
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -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,22 +316,32 @@ 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())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
HashedPoint3i pi;
|
HashedPoint3i pi;
|
||||||
SimpleTri st;
|
SimpleTri st;
|
||||||
for(int i=0;i<3;++i)
|
for(int i=0;i<3;++i)
|
||||||
{
|
{
|
||||||
Grid.PToIP((*fi).cV(i)->cP(), pi );
|
Grid.PToIP((*fi).cV(i)->cP(), pi );
|
||||||
st.v[i]=&(GridCell[pi]);
|
st.v[i]=&(GridCell[pi]);
|
||||||
st.v[i]->Add(m,*(fi),i);
|
st.v[i]->AddFaceVertex(m,*(fi),i);
|
||||||
}
|
}
|
||||||
if( (st.v[0]!=st.v[1]) && (st.v[0]!=st.v[2]) && (st.v[1]!=st.v[2]) )
|
if( (st.v[0]!=st.v[1]) && (st.v[0]!=st.v[2]) && (st.v[1]!=st.v[2]) )
|
||||||
{ // if we allow the duplication of faces we sort the vertex only partially (to maintain the original face orientation)
|
{ // if we allow the duplication of faces we sort the vertex only partially (to maintain the original face orientation)
|
||||||
|
|
@ -310,8 +352,38 @@ class Clustering
|
||||||
// printf("Inserted %8i triangles, clustered to %8i tri and %i cells\n",distance(m.face.begin(),fi),TriSet.size(),GridCell.size());
|
// printf("Inserted %8i triangles, clustered to %8i tri and %i cells\n",distance(m.face.begin(),fi),TriSet.size(),GridCell.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
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();
|
||||||
|
|
||||||
void Extract(MeshType &m)
|
if (GridCell.empty()) 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();
|
m.Clear();
|
||||||
|
|
||||||
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue