Cleaned up a bit for better handling of point clouds

This commit is contained in:
Paolo Cignoni 2013-09-11 11:11:10 +00:00
parent 646a31972f
commit 58471132ba
1 changed files with 104 additions and 144 deletions

View File

@ -20,44 +20,6 @@
* for more details. * * for more details. *
* * * *
****************************************************************************/ ****************************************************************************/
/****************************************************************************
History
$Log: not supported by cvs2svn $
Revision 1.11 2006/06/08 13:55:16 cignoni
Added ColorPreserving Cellbase template.
Revision 1.10 2006/05/26 10:18:11 cignoni
Re-adapted to ms compilers
Revision 1.9 2006/05/25 09:37:14 cignoni
Many changes for the different interpretation of hash_set between gcc and .net. Probably to be completed.
Revision 1.8 2006/05/24 16:42:22 m_di_benedetto
Corrected bbox inflation amount in case of _cellsize != 0
Revision 1.7 2006/05/24 15:16:01 cignoni
better comment to the init parameters
Revision 1.6 2006/05/24 08:54:04 cignoni
Added missing std:: to swap
Revision 1.5 2006/05/21 06:40:31 cignoni
Added DoubleFace management
Revision 1.4 2006/05/19 20:49:03 m_di_benedetto
Added check for empty generated mesh (prevent call to mesh allocator with zero vertices or faces).
Revision 1.3 2006/05/18 22:20:53 m_di_benedetto
added check for deleted faces and modified/added std namespace qualifier.
Revision 1.2 2006/05/18 13:59:20 cignoni
Some minor optimizations
Revision 1.1 2006/05/16 21:56:06 cignoni
First working Version
****************************************************************************/
#ifndef __VCGLIB_CLUSTERING #ifndef __VCGLIB_CLUSTERING
#define __VCGLIB_CLUSTERING #define __VCGLIB_CLUSTERING
@ -123,91 +85,90 @@ public:
template<class MeshType > template<class MeshType >
class NearestToCenter class NearestToCenter
{ {
typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::ScalarType ScalarType;
typedef typename MeshType::CoordType CoordType; typedef typename MeshType::CoordType CoordType;
typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexType VertexType;
typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FaceType FaceType;
typedef BasicGrid<typename MeshType::ScalarType> GridType; typedef BasicGrid<typename MeshType::ScalarType> GridType;
public: public:
inline void AddVertex(MeshType &/*m*/, GridType &g, Point3i &pi, VertexType &v) inline void AddVertex(MeshType &/*m*/, GridType &g, Point3i &pi, VertexType &v)
{ {
CoordType c; CoordType c;
g.IPiToBoxCenter(pi,c); g.IPiToBoxCenter(pi,c);
ScalarType newDist = Distance(c,v.cP()); ScalarType newDist = Distance(c,v.cP());
if(!valid || newDist < bestDist) if(!valid || newDist < bestDist)
{ {
valid=true; valid=true;
bestDist=newDist; bestDist=newDist;
bestPos=v.cP(); bestPos=v.cP();
bestN=v.cN(); bestN=v.cN();
orig=&v; orig=&v;
} }
} }
inline void AddFaceVertex(MeshType &/*m*/, FaceType &/*f*/, int /*i*/) { assert(0);} inline void AddFaceVertex(MeshType &/*m*/, FaceType &/*f*/, int /*i*/) { assert(0);}
NearestToCenter(): valid(false){} NearestToCenter(): valid(false){}
CoordType bestPos; CoordType bestPos;
CoordType bestN; CoordType bestN;
ScalarType bestDist; ScalarType bestDist;
bool valid; bool valid;
int id; int id;
VertexType *orig; VertexType *orig;
CoordType Pos() const CoordType Pos() const
{ {
assert(valid); assert(valid);
return bestPos; return bestPos;
} }
Color4b Col() const {return Color4b::White;} Color4b Col() const {return Color4b::White;}
CoordType N() const {return bestN;} CoordType N() const {return bestN;}
VertexType * Ptr() const {return orig;} 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 typename MeshType::VertexType VertexType;
typedef BasicGrid<typename MeshType::ScalarType> GridType; typedef BasicGrid<typename MeshType::ScalarType> GridType;
public: public:
inline void AddFaceVertex(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]);
// we prefer to use the un-normalized face normal so small faces facing away are dropped out // we prefer to use the un-normalized face normal so small faces facing away are dropped out
// and the resulting average is weighed with the size of the faces falling here. // and the resulting average is weighed with the size of the faces falling here.
n+=f.cN(); n+=f.cN();
cnt++; cnt++;
} }
inline void AddVertex(MeshType &/*m*/, GridType &/*g*/, Point3i &/*pi*/, VertexType &v) inline void AddVertex(MeshType &m, GridType &/*g*/, Point3i &/*pi*/, VertexType &v)
{ {
p+=v.cP(); p+=v.cP();
n+=v.cN(); n+=v.cN();
c+=CoordType(v.C()[0],v.C()[1],v.C()[2]); if(tri::HasPerVertexColor(m))
cnt++; 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;
CoordType c; CoordType c;
int cnt; int cnt;
int id; int id;
Color4b Col() const Color4b Col() const
{ {
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 N() const {return n;} CoordType N() const {return n;}
VertexType * Ptr() const {return 0;} VertexType * Ptr() const {return 0;}
CoordType Pos() const { return p/cnt; } CoordType Pos() const { return p/cnt; }
}; };
@ -235,16 +196,16 @@ class Clustering
bool DuplicateFaceParam; bool DuplicateFaceParam;
// This class keeps the references to the three cells where a face has its vertexes. // This class keeps the references to the three cells where a face has its vertexes.
class SimpleTri class SimpleTri
{ {
public: public:
CellType *v[3]; CellType *v[3];
int ii(int i) const {return *((int *)(&(v[i])));} int ii(int i) const {return *((int *)(&(v[i])));}
bool operator < ( const SimpleTri &p) const { bool operator < ( const SimpleTri &p) const {
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]);
} }
// Sort the vertex of the face maintaining the original face orientation (it only ensure that v0 is the minimum) // Sort the vertex of the face maintaining the original face orientation (it only ensure that v0 is the minimum)
void sortOrient() void sortOrient()
@ -281,13 +242,13 @@ class Clustering
void Init(Box3<ScalarType> _mbb, int _size, ScalarType _cellsize=0) void Init(Box3<ScalarType> _mbb, int _size, ScalarType _cellsize=0)
{ {
GridCell.clear(); GridCell.clear();
TriSet.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);
Grid.bbox.min-=CoordType(infl,infl,infl); Grid.bbox.min-=CoordType(infl,infl,infl);
Grid.bbox.max+=CoordType(infl,infl,infl); Grid.bbox.max+=CoordType(infl,infl,infl);
Grid.dim = Grid.bbox.max - Grid.bbox.min; Grid.dim = Grid.bbox.max - Grid.bbox.min;
if( _cellsize==0) if( _cellsize==0)
BestDim( _size, Grid.dim, Grid.siz ); BestDim( _size, Grid.dim, Grid.siz );
@ -300,7 +261,6 @@ class Clustering
Grid.voxel[2] = Grid.dim[2]/Grid.siz[2]; Grid.voxel[2] = Grid.dim[2]/Grid.siz[2];
} }
BasicGrid<ScalarType> Grid; BasicGrid<ScalarType> Grid;
#ifdef _MSC_VER #ifdef _MSC_VER
@ -308,7 +268,7 @@ class Clustering
typedef typename STDEXT::hash_set<SimpleTri>::iterator TriHashSetIterator; typedef typename STDEXT::hash_set<SimpleTri>::iterator TriHashSetIterator;
#else #else
struct SimpleTriHashFunc{ struct SimpleTriHashFunc{
inline size_t operator ()(const SimpleTri &p) const {return size_t(p);} inline size_t operator ()(const SimpleTri &p) const {return size_t(p);}
}; };
STDEXT::hash_set<SimpleTri,SimpleTriHashFunc> TriSet; STDEXT::hash_set<SimpleTri,SimpleTriHashFunc> TriSet;
typedef typename STDEXT::hash_set<SimpleTri,SimpleTriHashFunc>::iterator TriHashSetIterator; typedef typename STDEXT::hash_set<SimpleTri,SimpleTriHashFunc>::iterator TriHashSetIterator;
@ -334,43 +294,43 @@ class Clustering
{ {
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())
{ {
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]->AddFaceVertex(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)
if(DuplicateFaceParam) st.sortOrient(); if(DuplicateFaceParam) st.sortOrient();
else st.sort(); else st.sort();
TriSet.insert(st); TriSet.insert(st);
} }
// 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());
} }
} }
int CountPointSet() {return GridCell.size(); } int CountPointSet() {return GridCell.size(); }
void SelectPointSet(MeshType &m) void SelectPointSet(MeshType &m)
{ {
typename STDEXT::hash_map<HashedPoint3i,CellType>::iterator gi; typename STDEXT::hash_map<HashedPoint3i,CellType>::iterator gi;
UpdateSelection<MeshType>::VertexClear(m); UpdateSelection<MeshType>::VertexClear(m);
for(gi=GridCell.begin();gi!=GridCell.end();++gi) for(gi=GridCell.begin();gi!=GridCell.end();++gi)
{ {
VertexType *ptr=(*gi).second.Ptr(); VertexType *ptr=(*gi).second.Ptr();
if(ptr && ( ptr >= &*m.vert.begin() ) && ( ptr <= &*(m.vert.end() - 1) ) ) if(ptr && ( ptr >= &*m.vert.begin() ) && ( ptr <= &*(m.vert.end() - 1) ) )
ptr->SetS(); ptr->SetS();
}
} }
}
void ExtractPointSet(MeshType &m) void ExtractPointSet(MeshType &m)
{ {
m.Clear(); m.Clear();
if (GridCell.empty()) return; if (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;
@ -379,20 +339,18 @@ class Clustering
{ {
m.vert[i].P()=(*gi).second.Pos(); m.vert[i].P()=(*gi).second.Pos();
m.vert[i].N()=(*gi).second.N(); m.vert[i].N()=(*gi).second.N();
m.vert[i].C()=(*gi).second.Col(); if(HasPerVertexColor(m))
++i; m.vert[i].C()=(*gi).second.Col();
++i;
} }
} }
void ExtractMesh(MeshType &m) void ExtractMesh(MeshType &m)
{ {
m.Clear(); m.Clear();
if (TriSet.empty() || GridCell.empty()) if (GridCell.empty()) return;
{
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;
@ -400,11 +358,13 @@ class Clustering
for(gi=GridCell.begin();gi!=GridCell.end();++gi) for(gi=GridCell.begin();gi!=GridCell.end();++gi)
{ {
m.vert[i].P()=(*gi).second.Pos(); m.vert[i].P()=(*gi).second.Pos();
if(m.vert[i].HasColor()) m.vert[i].N()=(*gi).second.N();
if(HasPerVertexColor(m))
m.vert[i].C()=(*gi).second.Col(); m.vert[i].C()=(*gi).second.Col();
(*gi).second.id=i; (*gi).second.id=i;
++i; ++i;
} }
Allocator<MeshType>::AddFaces(m,TriSet.size()); Allocator<MeshType>::AddFaces(m,TriSet.size());
TriHashSetIterator ti; TriHashSetIterator ti;
i=0; i=0;
@ -417,7 +377,7 @@ class Clustering
// the best orientation according to the averaged normal // the best orientation according to the averaged normal
if(!DuplicateFaceParam) if(!DuplicateFaceParam)
{ {
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;