resolved hash code conflicts

This commit is contained in:
Nico Pietroni 2005-06-01 13:47:59 +00:00
parent 536ba5ab48
commit cd855e4e57
1 changed files with 621 additions and 349 deletions

View File

@ -24,6 +24,9 @@
History
$Log: not supported by cvs2svn $
Revision 1.5 2005/03/15 09:50:44 ganovelli
there was a debug line, now removed
Revision 1.4 2005/03/14 15:11:18 ganovelli
ClosestK added and other minor changes
@ -49,178 +52,348 @@ added vcg header
#include <vector>
#include <algorithm>
#ifdef WIN32
#include <hash_map>
#define STDEXT stdext
#include <hash_map>
#define STDEXT stdext
#else
#include <ext/hash_map>
#define STDEXT __gnu_cxx
#include <ext/hash_map>
#define STDEXT __gnu_cxx
#endif
namespace vcg{
/** Spatial Hash Table
/** 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{
template <class ElemType>
class SpatialHashTable{
public:
public:
typedef typename ElemType::CoordType CoordType;
typedef typename CoordType::ScalarType ScalarType;
//element of a cell
typedef typename std::pair<ElemType*,int> MapCellElem;
//type of entries element of a cell
typedef typename std::pair<ElemType*,int> EntryType;
//element stored in the hash table
//This Class Identify the cell
struct HElement
{
private:
///the min and max point corresponding to the cell - used to inverse hashing
CoordType min;//coordinate min of the cell
CoordType max;//coordinate max of the cell
Point3i cell_n;//cell number
public:
//elements
std::map<ElemType*,int> _entries;
//iterator to the map element into the cell
typedef typename std::map<ElemType*,int>::iterator IteMap;
std::map<ElemType*,int> elem;
//int flag;
public:
HElement()
{
// flag=0;
}
{}
HElement(ElemType* sim,const int &_tempMark)
HElement(ElemType* sim,const int &_tempMark,CoordType _min,CoordType _max,Point3i _cell)
{
elem.insert(MapCellElem(sim,_tempMark));
// flag=0;
_entries.insert(EntryType(sim,_tempMark));
min=_min;
max=_max;
assert(min<max);
cell_n=_cell;
}
///return true if the element is in the cell
bool IsIn(ElemType* sim)
{
int n=elem.count(sim);
{int n=elem.count(sim);
return (n==1);
}
///return the number of elements stored in the cell
int Size()
{
return (int)(elem.size());
}
{return (int)(_entries.size());}
///update or insert an element into a cell
void Update(ElemType* sim, const int & _tempMark)
{
std::pair<IteMap, bool> res=elem.insert(MapCellElem(sim,_tempMark));
//the element was already in the map structure so update the temporary mark
if (res.second==false)
{
//update the temporary mark
IteMap ite=res.first;
(*ite).second=_tempMark;
}
IteMap I=_entries.find(sim);
if (I!=_entries.end())//the entry exist in the cell
(*I).second=_tempMark;
else
_entries.insert(_entries.begin(),EntryType(sim,_tempMark));
//at the end update the temporary mark on the simplex
sim->Mark()=_tempMark;
}
//return an array of all simplexes of the map that have a right timestamp or are not deleted
void Elems(const int & _tempMark,std::vector<ElemType*> & res)
///given an iterator to the instance of the entry in the cell
///return true if the the entry is valid
///(using temporary mark).
bool IsUpdated(IteMap &I)
{
/* if ((*I).second >= (*I).first->Mark())
return true;
else
{
printf("DISUPDATED\N");
return false;
}*/
return ((*I).second >= (*I).first->Mark());
}
for (IteMap ite=elem.begin();ite!=elem.end();ite++)
///given an simplex pointer
///return true if the the entry corripondent to that
///simplex is valid or not
///(using temporary mark).
bool IsUpdated(ElemType* sim)
{
IteMap I=_entries.find(sim);
if (I!=_entries.end())
IsUpdated(I);
else
return false;
}
//add to the vector all simplexes of the map that have a right timestamp or are not deleted
void Elems(std::vector<ElemType*> & res)
{
for (IteMap ite=_entries.begin();ite!=_entries.end();ite++)
{
ElemType* sim=(*ite).first;
int t=(*ite).second;
if ((!sim->IsD())&&(t>=_tempMark))
if (IsUpdated(ite)&&(!sim->IsD()))
res.push_back(sim);
}
}
CoordType Min()
{return min;}
CoordType Max()
{return max;}
Point3i CellN()
{return cell_n;}
bool operator ==(const HElement &h)
{return (cell_n==h.CellN());}
bool operator !=(const HElement &h)
{return ((cell_n!=h.CellN()));}
}; // end struct HElement
///this Iterator returns all the elements that
///are in a specified box.
struct ClosersIterator{
private:
CoordType p;
SpatialHashTable<ElemType> * sh;
vcg::Point3i mincorner,maxcorner;
ScalarType sq_radius;
SpatialHashTable<ElemType> * sh; ///pointer to spatial hash table structure
vcg::Point3i mincorner,maxcorner; ///corners of the box where the scannig is performed
vcg::Point3i curr_ic; /// triple corresponding to the cell coordinate
HElement * curr_c; /// current cell pointer
typename HElement::IteMap curr_i; /// current iterator inside the cell
bool end; ///return true if the scanning of the elements is terminated
// current position
vcg::Point3i curr_ic; // triple corresponding to the cell
HElement * curr_c; // current cell
typename HElement::IteMap curr_i; // current iterator
bool end;
bool Advance(){
if(curr_ic[0] < maxcorner[0]) ++curr_ic[0];
///advance the current coordinate of one step inside the space box
///set and to true if scannig fo cells is complete
void Advance(){
if(curr_ic[0] < maxcorner[0])
++curr_ic[0];
else{
if(curr_ic[1] < maxcorner[1]) ++curr_ic[1];
if(curr_ic[1] < maxcorner[1])
++curr_ic[1];
else{
if(curr_ic[2] < maxcorner[2]) ++curr_ic[2];
if(curr_ic[2] < maxcorner[2])
++curr_ic[2];
else
return false;
end=true;
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();
//operator Next
//go to next simplex without considering temporary mark
void Next() {
SpatialHashTable<ElemType>::IteHtable I;
HElement::IteMap e = curr_c->_entries.end();
--e;
///if the current index
//is not at the end of element in the cell so advance of one step
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();
///Advance until find a cell that isn't empty or the scan is complete
Advance();
while((!End())&&(sh->numElemCell(curr_ic,I)==0))
{Advance();}
if (!End())
{
curr_c = &((*I).second);
curr_i = curr_c->_entries.begin();
}
}
}
public:
/////Initialize the iterator, p is the center of the box and _edge is his size
//void Init(SpatialHashTable<ElemType> * _sh, CoordType _p, const ScalarType &_edge)
//{
// sh = _sh;
// p =_p;
// ///find the box
// CoordType halfDiag(_edge,_edge,_edge);
// mincorner = sh->PointToCell(p-halfDiag);
// maxcorner = sh->PointToCell(p+halfDiag);
// ///set the initial cell of the iterator as the one that stay on the
// /// left lower position
// curr_ic = mincorner;
// ///find the cell corrisponding to first podsition
// IteHtable iht = sh->hash_table.find(sh->Hash(curr_ic));
// ///advance until find a cell that contain at least one updated element
// //and initialize the current cell and iterator inside it
// 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->_entries.begin();
// end = false;
// }
// else
// end = true;
//}
void AssertUpdated()
{
ScalarType Xs=(*curr_i).first->P().X();
ScalarType Ys=(*curr_i).first->P().Y();
ScalarType Zs=(*curr_i).first->P().Z();
ScalarType Xm=curr_c->Min().X();
ScalarType Ym=curr_c->Min().Y();
ScalarType Zm=curr_c->Min().Z();
ScalarType XM=curr_c->Max().X();
ScalarType YM=curr_c->Max().Y();
ScalarType ZM=curr_c->Max().Z();
if ((Xs<Xm)||(Xs>XM)||(Ys<Ym)||(Ys>YM)||(Zs<Zm)||(Zs>ZM))
printf("ERROR %d %d %d %d %d");
}
///Initialize the iterator, p is the center of the box and _edge is his size
void Init(SpatialHashTable<ElemType> * _sh, CoordType _p, const ScalarType &_edge)
{
end=false;
sh = _sh;
p =_p;
SpatialHashTable<ElemType>::IteHtable I;
///find the box
CoordType halfDiag(_edge,_edge,_edge);
mincorner = sh->PointToCell(p-halfDiag);
maxcorner = sh->PointToCell(p+halfDiag);
///set the initial cell of the iterator as the one that stay on the
/// left lower position
curr_ic = mincorner;
//if the fist position isn't empty
if (sh->numElemCell(curr_ic,I)>0)
{
curr_c = &((*I).second);
curr_i = curr_c->_entries.begin();
}
else
end = true;
{///advance until don't find an non empty cell
while((!End())&&(sh->numElemCell(curr_ic,I)==0))
Advance();
///then if is not finished find the first updated occorrency
if (!End())
{
curr_c = &((*I).second);
curr_i = curr_c->_entries.begin();
while ((!curr_c->IsUpdated(curr_i))&&(!end))
Next();
}
}
}
/////operator ++ of the itearator
//void Next() {
// bool isempty = true;
// HElement::IteMap e = curr_c->_entries.end();
// --e;
// ///if the current index
// //is not at the end of elemnt in the cell so advance of one step
// if(curr_i != e)
// ++curr_i;
// ///if the elemants on the cell are terminated then switch to another cell
// if(curr_i == e)
// {
// ///Advance until find a cell that isn't empty
// while( Advance() && (isempty=sh->IsEmptyCell(curr_ic)));
// if(!isempty){
// curr_c = &(*(sh->hash_table.find(sh->Hash(curr_ic)))).second;
// curr_i = curr_c->_entries.begin();
// }
// else
// end = true;
// }
//}
///operator ++ of the itearator
void operator ++()
{
Next();
while ((!curr_c->IsUpdated(curr_i))&&(!end))
Next();
assert(curr_c->IsUpdated(curr_i)||(end));
}
///dereferent operator
ElemType * operator *(){
return (*curr_i).first;
}
///return true if the scanning of elements is complete
bool End(){
//bool __ = (curr_i == curr_c->elem.end());
//return ( (curr_ic == maxcorner) && (curr_i == curr_c->elem.end()) );
return end;
}
}; // end struct CloserIterator
//hash table definition
typedef typename STDEXT::hash_map<int,HElement> Htable;
//typedef typename STDEXT::hash_map<int,HElement> Htable;
typedef typename STDEXT::hash_multimap<int,HElement> Htable;
//hash table definition
//typedef typename STDEXT::hash_map<vcg::Point3i,HElement> Htable;
//record of the hash table
typedef typename std::pair<int,HElement> HRecord;
//iterator to the hash table
@ -229,6 +402,7 @@ public:
SpatialHashTable(){};
~SpatialHashTable(){};
private:
//ContSimplex & _simplex;
int tempMark;
@ -241,56 +415,73 @@ public:
CoordType min;
CoordType max;
int conflicts;
/*Point3i min;
Point3i max;*/
void Init(CoordType _min,CoordType _max,ScalarType _l)
{
min=_min;
max=_max;
l=_l;
CoordType d=max-min;
//num = (int) floor(d.V(0)*d.V(1)*d.V(2)/l);
num = (int) floor(100*d.V(0)*d.V(1)*d.V(2)/l);
tempMark=0;
}
void InsertInCell(ElemType* s,Point3i cell)
///insert a new cell
void _InsertNewHentry(ElemType* s,Point3i cell)
{
int h=Hash(cell);
//insert a cell if there isn't
if (hash_table.count(h)==0)
hash_table.insert(HRecord(h,HElement(s,tempMark)));
//otherwise insert the element or update the temporary mark
CoordType _min;
CoordType _max;
_min=CellToPoint(cell);
_max=_min+CoordType(l,l,l);
hash_table.insert(HRecord(h,HElement(s,tempMark,_min,_max,cell)));
s->Mark()=tempMark;
}
bool _IsInHtable(Point3i cell,IteHtable &result)
{
int h=Hash(cell);
int count=hash_table.count(h);
if (count==0)///in this case there is no entry for that key
return false;
else
{
IteHtable HI=hash_table.find(h);
// (*HI).second.flag|=_flag;
(*HI).second.Update(s,tempMark);
}
}
////std::pair<Htable::const_iterator, Htable::const_iterator> p =hash_table.equal_range(h);
std::pair<IteHtable, IteHtable> p =hash_table.equal_range(h);
IteHtable i = p.first;
while((i != p.second)&&((*i).second.CellN()!=cell))++i;
std::vector<Point3i> AddElem( ElemType* s)
if (i==p.second)///the scan is terminated and we have not fuond the cell
{
std::vector<Point3i> box=BoxCells(s->BBox().min,s->BBox().max);
for (std::vector<Point3i>::iterator bi=box.begin();bi<box.end();bi++)
InsertInCell(s,*bi);
return box;
conflicts++;
return false;
}
else ///we have found the right cell
{
result=i;
return true;
}
}
}
template<class ContElemType>
void AddElems( ContElemType & elem_set)
///insert an element in a specified cell if the cell doesn't exist than
///create it.
void _InsertInCell(ElemType* s,Point3i cell)
{
typename ContElemType::iterator i;
for(i = elem_set.begin(); i!= elem_set.end(); ++i)
AddElem(&(*i));
IteHtable I;
if (!_IsInHtable(cell,I))
_InsertNewHentry(s,cell);
else///there is the entry specified by the iterator I so update only the temporary mark
(*I).second.Update(s,tempMark);
}
std::vector<Point3i> BoxCells(CoordType _min,CoordType _max)
// 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 the cells intersected by the Bounding box of the simplex
void BoxCells(CoordType _min,CoordType _max,std::vector<Point3i>& ret)
{
std::vector<Point3i> ret;
ret.clear();
Point3i MinI=Cell(_min);
Point3i MaxI=Cell(_max);
Point3i MinI=PointToCell(_min);
Point3i MaxI=PointToCell(_max);
int dimx=abs(MaxI.V(0)-MinI.V(0));
int dimy=abs(MaxI.V(1)-MinI.V(1));
int dimz=abs(MaxI.V(2)-MinI.V(2));
@ -302,17 +493,91 @@ public:
Point3i cell=Point3i(MinI.V(0)+x,MinI.V(1)+y,MinI.V(2)+z);
ret.push_back(cell);
}
return ret;
assert(ret.size()!=0);
}
//*********************************************************************
template <class A>
bool usefirst(const A & a,const A & b)const {return a.first < b.first;}
/*void getAtCell(Point3i _c,std::vector<ElemType*> & res)
{
std::vector<ElemType> result;
int h=Hash(_c);
if (numElemCell(_c)!=0){
IteHtable h_res=hash_table.find(h);
((*h_res).second.Elems(tempMark,res));
}
}*/
int ClosestK(const int& k,
ElemType* e,
std::vector<ElemType*>& res) {
///add to the vector the simplexes with that eddress
void getAtCell(Point3i _c,std::vector<ElemType*> & res)
{
int h=Hash(_c);
IteHtable I;
if (_IsInHtable(_c,I))//if there is the cell then
(*I).second.Elems(res);
}
Point3i PointToCell(CoordType p)
{
int x=(int)floor((p.V(0)-(ScalarType)min.V(0))/l);
int y=(int)floor((p.V(1)-(ScalarType)min.V(1))/l);
int z=(int)floor((p.V(2)-(ScalarType)min.V(2))/l);
return (vcg::Point3i(x,y,z));
}
CoordType CellToPoint(Point3i c)
{
ScalarType x=(((ScalarType)c.V(0)+min.V(0))*l);
ScalarType y=(((ScalarType)c.V(1)+min.V(1))*l);
ScalarType z=(((ScalarType)c.V(2)+min.V(2))*l);
return (CoordType(x,y,z));
}
public:
///initialize the structure HashSpace is one estimation about
///how many keys the system have to generate in order to obtain as less
///conflicts as possible
void Init(CoordType _min,CoordType _max,ScalarType _l,int HashSpace=1000)
{
l=_l;
min=_min;
max=_max;
num=HashSpace;
tempMark=0;
conflicts=0;
}
std::vector<Point3i> AddElem( ElemType* s)
{
std::vector<Point3i> box;
BoxCells(s->BBox().min,s->BBox().max,box);
for (std::vector<Point3i>::iterator bi=box.begin();bi<box.end();bi++)
_InsertInCell(s,*bi);
return box;
}
/*void AddElem( ElemType* s)
{
std::vector<Point3i> box;
BoxCells(s->BBox().min,s->BBox().max,box);
for (std::vector<Point3i>::iterator bi=box.begin();bi<box.end();bi++)
_InsertInCell(s,*bi);
}*/
template<class ContElemType>
void AddElems( ContElemType & elem_set)
{
typename ContElemType::iterator i;
for(i = elem_set.begin(); i!= elem_set.end(); ++i)
AddElem(&(*i));
}
////*********************************************************************
//template <class A>
// bool usefirst(const A & a,const A & b)const {return a.first < b.first;}
int ClosestK(const int& k,ElemType* e, std::vector<ElemType*>& res)
{
typedef std::pair<ScalarType,ElemType*> ElemDist;
std::vector<ElemDist > neigh_dist;
std::vector<ElemDist >::iterator ite_nd;
@ -333,7 +598,7 @@ public:
int x,y,z;
vcg::Point3i mincorner,maxcorner,c;
c = Cell(p);
c = PointToCell(p);
mincorner = maxcorner = c;
neigh_dist.push_back(ElemDist(-1,e));
ite_nd = neigh_dist.begin();
@ -361,7 +626,7 @@ public:
( x == maxcorner[0])
)++x; else x=maxcorner[0];
}
// ,usefirst<ElemDist> ---<std::vector<ElemDist >::iterator >
// ,usefirst<ElemDist> ---<std::vector<ElemDist >::iterator >
ite_nd =neigh_dist.begin();
std::advance(ite_nd,res.size());
std::sort(ite_nd,neigh_dist.end());
@ -379,7 +644,7 @@ public:
}
return 0;
}
//**********************************************************************
//**********************************************************************
// return the elem closer than radius
@ -389,8 +654,7 @@ public:
ClosersIterator cli;
cli.Init(this,p,radius);
while(!cli.End()){
if ( (((*cli)->P() -p )*((*cli)->P() -p ) < radius*radius) &&
(*cli.curr_i).second >= tempMark)
if ( (((*cli)->P() -p )*((*cli)->P() -p ) < radius*radius))// &&(*cli.curr_i).second >= tempMark)
closers.push_back(*cli);
++cli;
}
@ -404,15 +668,15 @@ public:
inline Point3i MinCell()
{
return Cell(min);
return PointToCell(min);
}
inline Point3i MaxCell()
{
return Cell(max);
return PointToCell(max);
}
inline int numElemCell(Point3i _c)
/*inline int numElemCell(Point3i _c)
{
int h=Hash(_c);
if (hash_table.count(h)==0)
@ -422,59 +686,67 @@ public:
IteHtable Ih=hash_table.find(h);
return ((*Ih).second.Size());
}
}*/
///return the number of elemnts in the cell ond the iterator to the cell
///if the cell exist
int numElemCell(Point3i _c,IteHtable &I)
{
int h=Hash(_c);
if (_IsInHtable(_c,I))
return ((*I).second.Size());
else
return 0;
}
inline bool IsEmptyCell(Point3i _c)
/*inline bool IsEmptyCell(Point3i _c)
{
return(numElemCell(_c)==0);
}*/
/*inline bool IsEmptyCell(Point3i _c)
{
int h=Hash(_c);
if (hash_table.count(h)==0)
return true;
else
return false;
}
}*/
///return the number of cell created
int CellNumber()
{return (hash_table.size());}
int Conflicts()
{return conflicts;}
void Clear()
{
hash_table.clear();
}
//void std::vector<ElemType> getAt(CoordType _p,std::vector<ElemType> & res)
//{
// std::vector<ElemType> result;
// Point3i c=Cell(_p);
// return (getAtCell(c,res));
//}
void UpdateTmark()
{tempMark++;}
void getAtCell(Point3i _c,std::vector<ElemType*> & res)
///only debug
void DrawCell(HElement &c)
{
std::vector<ElemType> result;
int h=Hash(_c);
if (numElemCell(_c)!=0){
IteHtable h_res=hash_table.find(h);
((*h_res).second.Elems(tempMark,res));
}
glPushMatrix();
glTranslate(c.Min()+vcg::Point3d(l/2,l/2,l/2));
glutWireCube(l);
glPopMatrix();
}
const Point3i Cell(const CoordType & p) const
void Draw()
{
int x=(int)floor(p.V(0)/l);
int y=(int)floor(p.V(1)/l);
int z=(int)floor(p.V(2)/l);
return Point3i(x,y,z);
for (IteHtable I=hash_table.begin();I!=hash_table.end();I++)
DrawCell((*I).second);
}
// 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[2]-min[2] )* dim[0]*dim[1] +
// ( p[1]-min[1] )* dim[1] +
// ( p[0]-min[0] );
}
private:
}; // end class
///only debug
}; // end class
}// end namespace