added ClosersIterator and other minor changes. Not compatible with the previous version.
Still other modifications to do (temporary commit)
This commit is contained in:
parent
eed72fadc4
commit
7610457632
|
@ -24,59 +24,75 @@
|
||||||
History
|
History
|
||||||
|
|
||||||
$Log: not supported by cvs2svn $
|
$Log: not supported by cvs2svn $
|
||||||
|
Revision 1.2 2005/02/21 12:13:25 ganovelli
|
||||||
|
added vcg header
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifndef SPATIAL_HASHING
|
#ifndef VCGLIB_SPATIAL_HASHING
|
||||||
#define SPATIAL_HASHING
|
#define VCGLIB_SPATIAL_HASHING
|
||||||
|
|
||||||
#define P0 73
|
#define P0 73856093
|
||||||
#define P1 19
|
#define P1 19349663
|
||||||
#define P2 83
|
#define P2 83492791
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <hash_map>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
template <class SimplexType>
|
#ifdef WIN32
|
||||||
|
#include <hash_map>
|
||||||
|
#define STDEXT stdext
|
||||||
|
#else
|
||||||
|
#include <ext/hash_map>
|
||||||
|
#define STDEXT __gnu_cxx
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace vcg{
|
||||||
|
/** Spatial Hash Table
|
||||||
|
Spatial Hashing as described in
|
||||||
|
"Optimized Spatial Hashing for Collision Detection of Deformable Objects",
|
||||||
|
Matthias Teschner and Bruno Heidelberger and Matthias Muller and Danat Pomeranets and Markus Gross
|
||||||
|
*/
|
||||||
|
template <class ElemType>
|
||||||
class SpatialHashTable{
|
class SpatialHashTable{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef typename SimplexType* SimplexPointer;
|
typedef ElemType* SimplexPointer;
|
||||||
typedef typename SimplexType::CoordType Point3x;
|
typedef typename ElemType::CoordType CoordType;
|
||||||
typedef typename Point3x::ScalarType ScalarType;
|
typedef typename CoordType::ScalarType ScalarType;
|
||||||
|
|
||||||
|
|
||||||
//iterator to the map element into the cell
|
|
||||||
typedef typename std::map<SimplexType*,int>::iterator IteMap;
|
|
||||||
//element of a cell
|
//element of a cell
|
||||||
typedef typename std::pair<SimplexType*,int> MapCellElem;
|
typedef typename std::pair<ElemType*,int> MapCellElem;
|
||||||
|
|
||||||
//element stored in the hash table
|
//element stored in the hash table
|
||||||
struct Helement
|
struct HElement
|
||||||
{
|
{
|
||||||
|
|
||||||
std::map<SimplexType*,int> elem;
|
//iterator to the map element into the cell
|
||||||
|
typedef typename std::map<ElemType*,int>::iterator IteMap;
|
||||||
|
|
||||||
|
std::map<ElemType*,int> elem;
|
||||||
//int flag;
|
//int flag;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Helement()
|
HElement()
|
||||||
{
|
{
|
||||||
// flag=0;
|
// flag=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Helement(SimplexType* sim,int _tempMark)
|
HElement(ElemType* sim,const int &_tempMark)
|
||||||
{
|
{
|
||||||
elem.insert(MapCellElem(sim,_tempMark));
|
elem.insert(MapCellElem(sim,_tempMark));
|
||||||
// flag=0;
|
// flag=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
///return true if the element is in the cell
|
///return true if the element is in the cell
|
||||||
bool IsIn(SimplexType* sim)
|
bool IsIn(ElemType* sim)
|
||||||
{
|
{
|
||||||
int n=elem.count(sim);
|
int n=elem.count(sim);
|
||||||
return (n==1);
|
return (n==1);
|
||||||
|
@ -88,7 +104,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
///update or insert an element into a cell
|
///update or insert an element into a cell
|
||||||
void Update(SimplexType* sim,int _tempMark)
|
void Update(ElemType* sim, const int & _tempMark)
|
||||||
{
|
{
|
||||||
std::pair<IteMap, bool> res=elem.insert(MapCellElem(sim,_tempMark));
|
std::pair<IteMap, bool> res=elem.insert(MapCellElem(sim,_tempMark));
|
||||||
//the element was already in the map structure so update the temporary mark
|
//the element was already in the map structure so update the temporary mark
|
||||||
|
@ -101,111 +117,172 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
//return an array of all simplexes of the map that have a right timestamp or are not deleted
|
//return an array of all simplexes of the map that have a right timestamp or are not deleted
|
||||||
std::vector<SimplexType*> Simplexes(int _tempMark)
|
std::vector<ElemType*> Simplexes(const int & _tempMark)
|
||||||
{
|
{
|
||||||
std::vector<SimplexType*> result;
|
std::vector<ElemType*> result;
|
||||||
result.clear();
|
result.clear();
|
||||||
for (IteMap ite=elem.begin();ite!=elem.end();ite++)
|
for (IteMap ite=elem.begin();ite!=elem.end();ite++)
|
||||||
{
|
{
|
||||||
SimplexType* sim=(*ite).first;
|
ElemType* sim=(*ite).first;
|
||||||
int t=(*ite).second;
|
int t=(*ite).second;
|
||||||
if ((!sim->IsD())&&(t>=_tempMark))
|
if ((!sim->IsD())&&(t>=_tempMark))
|
||||||
result.push_back(sim);
|
result.push_back(sim);
|
||||||
}
|
}
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
};
|
}; // end struct HElement
|
||||||
|
|
||||||
//enum {
|
|
||||||
// // First user bit
|
|
||||||
// USER0 = 0x0001 // First user bit
|
|
||||||
// };
|
|
||||||
|
|
||||||
//static int &LastBitFlag()
|
struct ClosersIterator{
|
||||||
// {
|
CoordType p;
|
||||||
// static int b =USER0;
|
SpatialHashTable<ElemType> * sh;
|
||||||
// return b;
|
vcg::Point3i mincorner,maxcorner;
|
||||||
// }
|
ScalarType sq_radius;
|
||||||
|
|
||||||
///// allocate a bit among the flags that can be used by user.
|
// current position
|
||||||
//static inline int NewBitFlag()
|
vcg::Point3i curr_ic; // triple corresponding to the cell
|
||||||
// {
|
HElement * curr_c; // current cell
|
||||||
// LastBitFlag()=LastBitFlag()<<1;
|
typename HElement::IteMap curr_i; // current iterator
|
||||||
// return LastBitFlag();
|
bool end;
|
||||||
// }
|
|
||||||
|
bool Advance(){
|
||||||
|
if(curr_ic[0] < maxcorner[0]) ++curr_ic[0];
|
||||||
|
else{
|
||||||
|
if(curr_ic[1] < maxcorner[1]) ++curr_ic[1];
|
||||||
|
else{
|
||||||
|
if(curr_ic[2] < maxcorner[2]) ++curr_ic[2];
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
curr_ic[1] = mincorner[1];
|
||||||
|
}
|
||||||
|
curr_ic[0] = mincorner[0];
|
||||||
|
}
|
||||||
|
curr_c = &(*(sh->hash_table.find(sh->Hash(curr_ic)))).second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void Init(SpatialHashTable<ElemType> * _sh, CoordType _p, const ScalarType &_radius)
|
||||||
|
{
|
||||||
|
sh = _sh;
|
||||||
|
p =_p;
|
||||||
|
CoordType halfDiag(_radius,_radius,_radius);
|
||||||
|
mincorner = sh->Cell(p-halfDiag);
|
||||||
|
maxcorner = sh->Cell(p+halfDiag);
|
||||||
|
curr_ic = mincorner;
|
||||||
|
sq_radius = _radius * _radius;
|
||||||
|
|
||||||
|
IteHtable iht = sh->hash_table.find(sh->Hash(curr_ic));
|
||||||
|
|
||||||
|
// initialize the iterator to the first element
|
||||||
|
bool isempty = (iht == sh->hash_table.end());
|
||||||
|
if(isempty)
|
||||||
|
while( Advance() && (isempty=sh->IsEmptyCell(curr_ic)));
|
||||||
|
|
||||||
|
if(!isempty){
|
||||||
|
curr_c = &(*(sh->hash_table.find(sh->Hash(curr_ic)))).second;
|
||||||
|
curr_i = curr_c->elem.begin();
|
||||||
|
end = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
end = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator ++() {
|
||||||
|
bool isempty = true;
|
||||||
|
HElement::IteMap e = curr_c->elem.end();
|
||||||
|
--e;
|
||||||
|
if(curr_i != e)
|
||||||
|
++curr_i;
|
||||||
|
else{
|
||||||
|
while( Advance() && (isempty=sh->IsEmptyCell(curr_ic)));
|
||||||
|
if(!isempty){
|
||||||
|
curr_c = &(*(sh->hash_table.find(sh->Hash(curr_ic)))).second;
|
||||||
|
curr_i = curr_c->elem.begin();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
end = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ElemType * operator *(){
|
||||||
|
vcg::Point3d __ = (*curr_i).first->P();
|
||||||
|
return (*curr_i).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool End(){
|
||||||
|
//bool __ = (curr_i == curr_c->elem.end());
|
||||||
|
//return ( (curr_ic == maxcorner) && (curr_i == curr_c->elem.end()) );
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
}; // end struct CloserIterator
|
||||||
|
|
||||||
//// de-allocate a bit among the flags that can be used by user.
|
|
||||||
//static inline bool DeleteBitFlag(int bitval)
|
|
||||||
// {
|
|
||||||
// if(LastBitFlag()==bitval) {
|
|
||||||
// LastBitFlag()= LastBitFlag()>>1;
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// assert(0);
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
//hash table definition
|
//hash table definition
|
||||||
typedef typename stdext::hash_map<int,Helement> Htable;
|
typedef typename STDEXT::hash_map<int,HElement> Htable;
|
||||||
//record of the hash table
|
//record of the hash table
|
||||||
typedef typename std::pair<int,Helement> HRecord;
|
typedef typename std::pair<int,HElement> HRecord;
|
||||||
//iterator to the hash table
|
//iterator to the hash table
|
||||||
typedef typename Htable::iterator IteHtable;
|
typedef typename Htable::iterator IteHtable;
|
||||||
|
|
||||||
|
|
||||||
//SpatialHashTable(ContSimplex & r_):_simplex(r_){};
|
|
||||||
SpatialHashTable(){};
|
SpatialHashTable(){};
|
||||||
~SpatialHashTable(){};
|
~SpatialHashTable(){};
|
||||||
|
|
||||||
|
|
||||||
//ContSimplex & _simplex;
|
//ContSimplex & _simplex;
|
||||||
int TempMark;
|
int tempMark;
|
||||||
Htable hash_table;
|
Htable hash_table;
|
||||||
|
|
||||||
int num;
|
int num;
|
||||||
float l;
|
float l;
|
||||||
|
|
||||||
|
|
||||||
Point3x min;
|
CoordType min;
|
||||||
Point3x max;
|
CoordType max;
|
||||||
|
|
||||||
|
|
||||||
void Init(Point3x _min,Point3x _max,ScalarType _l)
|
void Init(CoordType _min,CoordType _max,ScalarType _l)
|
||||||
{
|
{
|
||||||
min=_min;
|
min=_min;
|
||||||
max=_max;
|
max=_max;
|
||||||
l=_l;
|
l=_l;
|
||||||
Point3x d=max-min;
|
CoordType d=max-min;
|
||||||
num=floor(d.V(0)*d.V(1)*d.V(2)/l);
|
//num = (int) floor(d.V(0)*d.V(1)*d.V(2)/l);
|
||||||
TempMark=0;
|
num = (int) floor(100*d.V(0)*d.V(1)*d.V(2)/l);
|
||||||
|
tempMark=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InsertInCell(SimplexType* s,Point3i cell)
|
void InsertInCell(ElemType* s,Point3i cell)
|
||||||
{
|
{
|
||||||
int h=Hash(cell);
|
int h=Hash(cell);
|
||||||
//insert a cell if there isn't
|
//insert a cell if there isn't
|
||||||
if (hash_table.count(h)==0)
|
if (hash_table.count(h)==0)
|
||||||
hash_table.insert(HRecord(h,Helement(s,TempMark)));
|
hash_table.insert(HRecord(h,HElement(s,tempMark)));
|
||||||
//otherwise insert the element or update the temporary mark
|
//otherwise insert the element or update the temporary mark
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
IteHtable HI=hash_table.find(h);
|
IteHtable HI=hash_table.find(h);
|
||||||
// (*HI).second.flag|=_flag;
|
// (*HI).second.flag|=_flag;
|
||||||
(*HI).second.Update(s,TempMark);
|
(*HI).second.Update(s,tempMark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<Point3i> addBox(SimplexType* s,Point3x _min,Point3x _max)
|
std::vector<Point3i> AddElem( ElemType* s)
|
||||||
{
|
{
|
||||||
|
std::vector<Point3i> box=BoxCells(s->BBox().min,s->BBox().max);
|
||||||
std::vector<Point3i> box=BoxCells(_min,_max);
|
|
||||||
for (std::vector<Point3i>::iterator bi=box.begin();bi<box.end();bi++)
|
for (std::vector<Point3i>::iterator bi=box.begin();bi<box.end();bi++)
|
||||||
InsertInCell(s,*bi);
|
InsertInCell(s,*bi);
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Point3i> BoxCells(Point3x _min,Point3x _max)
|
template<class ContElemType>
|
||||||
|
void AddElems( ContElemType & elem_set)
|
||||||
|
{
|
||||||
|
typename ContElemType::iterator i;
|
||||||
|
for(i = elem_set.begin(); i!= elem_set.end(); ++i)
|
||||||
|
AddElem(&(*i));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Point3i> BoxCells(CoordType _min,CoordType _max)
|
||||||
{
|
{
|
||||||
std::vector<Point3i> ret;
|
std::vector<Point3i> ret;
|
||||||
ret.clear();
|
ret.clear();
|
||||||
|
@ -225,57 +302,24 @@ public:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Point3i> Cells(SimplexType *s)
|
// tanto per prova
|
||||||
{
|
int CloserThan( typename ElemType::CoordType p,
|
||||||
Point3x min=Point3x((*s).V(0)->P());
|
typename ElemType::ScalarType radius,
|
||||||
Point3x max=min;
|
std::vector<ElemType*> & closers){
|
||||||
|
ClosersIterator cli;
|
||||||
//find min max coordinate of bounding box
|
cli.Init(this,p,radius);
|
||||||
for (int i=1;i<3;i++)
|
while(!cli.End()){
|
||||||
{
|
if ( (((*cli)->P() -p )*((*cli)->P() -p ) < radius*radius) &&
|
||||||
if (min.V(0)>(*s).V(i)->P().V(0))
|
(*cli.curr_i).second >= tempMark)
|
||||||
min.V(0)=(*s).V(i)->P().V(0);
|
closers.push_back(*cli);
|
||||||
if (min.V(1)>(*s).V(i)->P().V(1))
|
++cli;
|
||||||
min.V(1)=(*s).V(i)->P().V(1);
|
}
|
||||||
if (min.V(2)>(*s).V(i)->P().V(2))
|
return closers.size();
|
||||||
min.V(2)=(*s).V(i)->P().V(2);
|
|
||||||
|
|
||||||
if (max.V(0)<(*s).V(i)->P().V(0))
|
|
||||||
max.V(0)=(*s).V(i)->P().V(0);
|
|
||||||
if (max.V(1)<(*s).V(i)->P().V(1))
|
|
||||||
max.V(1)=(*s).V(i)->P().V(1);
|
|
||||||
if (max.V(2)>(*s).V(i)->P().V(2))
|
|
||||||
max.V(2)=(*s).V(i)->P().V(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return BoxCells(s,min,max);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Point3i> addSimplex(SimplexType *s)
|
std::vector<Point3i> Cells(ElemType *s)
|
||||||
{
|
{
|
||||||
Point3x min=Point3x((*s).V(0)->P());
|
return BoxCells(s,s->BBox().min,s->BBox().max);
|
||||||
Point3x max=min;
|
|
||||||
|
|
||||||
//find min max coordinate of bounding box
|
|
||||||
for (int i=1;i<3;i++)
|
|
||||||
{
|
|
||||||
if (min.V(0)>(*s).V(i)->P().V(0))
|
|
||||||
min.V(0)=(*s).V(i)->P().V(0);
|
|
||||||
if (min.V(1)>(*s).V(i)->P().V(1))
|
|
||||||
min.V(1)=(*s).V(i)->P().V(1);
|
|
||||||
if (min.V(2)>(*s).V(i)->P().V(2))
|
|
||||||
min.V(2)=(*s).V(i)->P().V(2);
|
|
||||||
|
|
||||||
if (max.V(0)<(*s).V(i)->P().V(0))
|
|
||||||
max.V(0)=(*s).V(i)->P().V(0);
|
|
||||||
if (max.V(1)<(*s).V(i)->P().V(1))
|
|
||||||
max.V(1)=(*s).V(i)->P().V(1);
|
|
||||||
if (max.V(2)>(*s).V(i)->P().V(2))
|
|
||||||
max.V(2)=(*s).V(i)->P().V(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
///now set the cell touched by the bounding box of the triangle
|
|
||||||
return (addBox(s,min,max));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Point3i MinCell()
|
inline Point3i MinCell()
|
||||||
|
@ -300,53 +344,25 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///refresh all the alement in the container
|
inline bool IsEmptyCell(Point3i _c)
|
||||||
/*void RefreshElements()
|
|
||||||
{
|
{
|
||||||
TempMark++;
|
int h=Hash(_c);
|
||||||
for (SimplexIterator si=_simplex.begin();si<_simplex.end();++si)
|
if (hash_table.count(h)==0)
|
||||||
{
|
return true;
|
||||||
if (!(*si).IsD())
|
else
|
||||||
addSimplex(&*si);
|
return false;
|
||||||
}
|
}
|
||||||
}*/
|
|
||||||
|
|
||||||
///erase all element of the hash table where the timestamp is old
|
|
||||||
//void Clean()
|
|
||||||
//{
|
|
||||||
// for (IteHtable Ih=hash_table.begin();Ih!=hash_table.end();Ih++)
|
|
||||||
// //if after clean there are no element erase the cell
|
|
||||||
// if ((*Ih).second.Clean(TempMark))
|
|
||||||
// hash_table.erase(Ih);
|
|
||||||
//}
|
|
||||||
|
|
||||||
/*void Clean()
|
|
||||||
{
|
|
||||||
hash_table.clear();
|
|
||||||
RefreshElements();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
void Clear()
|
void Clear()
|
||||||
{
|
{
|
||||||
hash_table.clear();
|
hash_table.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*int FlagCell(Point3i p)
|
std::vector<SimplexPointer> getAt(CoordType _p)
|
||||||
{
|
|
||||||
int h=Hash(p);
|
|
||||||
if (hash_table.count(h)==0)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IteHtable Ih=hash_table.find(h);
|
|
||||||
return ((*Ih).second.Flag());
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
std::vector<SimplexPointer> getAt(Point3x _p)
|
|
||||||
{
|
{
|
||||||
std::vector<SimplexPointer> result;
|
std::vector<SimplexPointer> result;
|
||||||
Point3i c=Cell(p);
|
Point3i c=Cell(_p);
|
||||||
return (getAtCell(c));
|
return (getAtCell(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,30 +377,34 @@ public:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
IteHtable res=hash_table.find(h);
|
IteHtable res=hash_table.find(h);
|
||||||
return ((*res).second.Simplexes(TempMark));
|
return ((*res).second.Simplexes(tempMark));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Point3i Cell(const CoordType & p) const
|
||||||
private:
|
|
||||||
|
|
||||||
Point3i Cell(Point3x p)
|
|
||||||
{
|
{
|
||||||
int x=floor(p.V(0)/l);
|
int x=(int)floor(p.V(0)/l);
|
||||||
int y=floor(p.V(1)/l);
|
int y=(int)floor(p.V(1)/l);
|
||||||
int z=floor(p.V(2)/l);
|
int z=(int)floor(p.V(2)/l);
|
||||||
return Point3i(x,y,z);
|
return Point3i(x,y,z);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Hash(Point3i p)
|
// hashing
|
||||||
|
const int Hash(Point3i p) const
|
||||||
{
|
{
|
||||||
|
vcg::Point3i dim(100,100,100);
|
||||||
return ((p.V(0)*P0 ^ p.V(1)*P1 ^ p.V(2)*P2)%num);
|
return ((p.V(0)*P0 ^ p.V(1)*P1 ^ p.V(2)*P2)%num);
|
||||||
|
// return ( p[2]-min[2] )* dim[0]*dim[1] +
|
||||||
|
// ( p[1]-min[1] )* dim[1] +
|
||||||
|
// ( p[0]-min[0] );
|
||||||
}
|
}
|
||||||
|
private:
|
||||||
|
}; // end class
|
||||||
|
|
||||||
};
|
}// end namespace
|
||||||
|
|
||||||
#undef P0
|
#undef P0
|
||||||
#undef P1
|
#undef P1
|
||||||
#undef P2
|
#undef P2
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue