diff --git a/vcg/space/index/spatial_hashing.h b/vcg/space/index/spatial_hashing.h index 418ca938..84b4a9f4 100644 --- a/vcg/space/index/spatial_hashing.h +++ b/vcg/space/index/spatial_hashing.h @@ -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,432 +52,701 @@ added vcg header #include #include #ifdef WIN32 - #include - #define STDEXT stdext +#include +#define STDEXT stdext #else - #include - #define STDEXT __gnu_cxx +#include +#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 SpatialHashTable{ + /** 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 SpatialHashTable{ -public: - - typedef typename ElemType::CoordType CoordType; - typedef typename CoordType::ScalarType ScalarType; - - - //element of a cell - typedef typename std::pair MapCellElem; + public: - //element stored in the hash table - struct HElement + typedef typename ElemType::CoordType CoordType; + typedef typename CoordType::ScalarType ScalarType; + + + //type of entries element of a cell + typedef typename std::pair EntryType; + + //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 _entries; + //iterator to the map element into the cell typedef typename std::map::iterator IteMap; - std::map 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 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; - } - } - - //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 & res) - { + IteMap I=_entries.find(sim); - for (IteMap ite=elem.begin();ite!=elem.end();ite++) + 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; + } + + ///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()); + } + + ///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 & 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 * sh; - vcg::Point3i mincorner,maxcorner; - ScalarType sq_radius; - - // 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]; + SpatialHashTable * 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 + + ///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]; - else{ - if(curr_ic[2] < maxcorner[2]) ++curr_ic[2]; - else - return false; - curr_ic[1] = mincorner[1]; - } + if(curr_ic[1] < maxcorner[1]) + ++curr_ic[1]; + else{ + if(curr_ic[2] < maxcorner[2]) + ++curr_ic[2]; + else + 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 * _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::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(); } - else - end = true; } } - ElemType * operator *(){ - return (*curr_i).first; + + public: + + /////Initialize the iterator, p is the center of the box and _edge is his size + //void Init(SpatialHashTable * _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 ((XsXM)||(YsYM)||(ZsZM)) + 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 * _sh, CoordType _p, const ScalarType &_edge) + { + end=false; + sh = _sh; + p =_p; + SpatialHashTable::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 + {///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(){ + return end; } - 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 Htable; - //record of the hash table - typedef typename std::pair HRecord; - //iterator to the hash table - typedef typename Htable::iterator IteHtable; + //hash table definition + //typedef typename STDEXT::hash_map Htable; + typedef typename STDEXT::hash_multimap Htable; + //hash table definition + //typedef typename STDEXT::hash_map Htable; + //record of the hash table + typedef typename std::pair HRecord; + //iterator to the hash table + typedef typename Htable::iterator IteHtable; - SpatialHashTable(){}; - ~SpatialHashTable(){}; - - - //ContSimplex & _simplex; - int tempMark; - Htable hash_table; - - int num; - float l; - + SpatialHashTable(){}; + ~SpatialHashTable(){}; - CoordType min; - CoordType max; + private: + + //ContSimplex & _simplex; + int tempMark; + Htable hash_table; + + int num; + float l; - 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; - } + CoordType min; + CoordType max; - void InsertInCell(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 - else - { - IteHtable HI=hash_table.find(h); -// (*HI).second.flag|=_flag; - (*HI).second.Update(s,tempMark); - } - } - + int conflicts; + /*Point3i min; + Point3i max;*/ - std::vector AddElem( ElemType* s) - { - std::vector box=BoxCells(s->BBox().min,s->BBox().max); - for (std::vector::iterator bi=box.begin();bi - void AddElems( ContElemType & elem_set) - { - typename ContElemType::iterator i; - for(i = elem_set.begin(); i!= elem_set.end(); ++i) - AddElem(&(*i)); - } - - std::vector BoxCells(CoordType _min,CoordType _max) - { - std::vector ret; - ret.clear(); - Point3i MinI=Cell(_min); - Point3i MaxI=Cell(_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)); - - for (int x=0;x<=dimx;x++) - for (int y=0;y<=dimy;y++) - for (int z=0;z<=dimz;z++) - { - Point3i cell=Point3i(MinI.V(0)+x,MinI.V(1)+y,MinI.V(2)+z); - ret.push_back(cell); - } - return ret; - } - -//********************************************************************* - template - bool usefirst(const A & a,const A & b)const {return a.first < b.first;} - - int ClosestK(const int& k, - ElemType* e, - std::vector& res) { - - typedef std::pair ElemDist; - std::vector neigh_dist; - std::vector::iterator ite_nd; - std::vector neigh; - std::vector::iterator i_neigh; - typename ElemType::CoordType p = e->P(); - ScalarType radius,tmp,d; - - // set the radius as the distance to the closest face - radius = p[2]-floor(p[2]/l)*l; - if(radius > l*0.5) radius = l -radius; - tmp = p[1]-floor(p[1]/l)*l; - if(tmp > l*0.5) tmp = l -tmp; - if(radius > tmp) tmp = radius; - tmp = p[0]-floor(p[0]/l)*l; - if(tmp > l*0.5) tmp = l -tmp; - if(radius > tmp) radius = tmp; - - int x,y,z; - vcg::Point3i mincorner,maxcorner,c; - c = Cell(p); - mincorner = maxcorner = c; - neigh_dist.push_back(ElemDist(-1,e)); - ite_nd = neigh_dist.begin(); - - while((int)res.size() < k) + ///insert a new cell + void _InsertNewHentry(ElemType* s,Point3i cell) { + int h=Hash(cell); + 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 + { + ////std::pair p =hash_table.equal_range(h); + std::pair p =hash_table.equal_range(h); + IteHtable i = p.first; - //run on the border - for( z = mincorner[2]; z <= maxcorner[2]; ++z) - for( y = mincorner[1]; y <= maxcorner[1]; ++y) - for( x = mincorner[0]; x <= maxcorner[0];) + while((i != p.second)&&((*i).second.CellN()!=cell))++i; + + if (i==p.second)///the scan is terminated and we have not fuond the cell + { + conflicts++; + return false; + } + else ///we have found the right cell + { + result=i; + return true; + } + } + } + + ///insert an element in a specified cell if the cell doesn't exist than + ///create it. + void _InsertInCell(ElemType* s,Point3i cell) + { + 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); + } + + // 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& ret) + { + ret.clear(); + 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)); + + for (int x=0;x<=dimx;x++) + for (int y=0;y<=dimy;y++) + for (int z=0;z<=dimz;z++) + { + Point3i cell=Point3i(MinI.V(0)+x,MinI.V(1)+y,MinI.V(2)+z); + ret.push_back(cell); + } + assert(ret.size()!=0); + } + + /*void getAtCell(Point3i _c,std::vector & res) + { + std::vector result; + int h=Hash(_c); + if (numElemCell(_c)!=0){ + IteHtable h_res=hash_table.find(h); + ((*h_res).second.Elems(tempMark,res)); + } + }*/ + + ///add to the vector the simplexes with that eddress + void getAtCell(Point3i _c,std::vector & 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 AddElem( ElemType* s) + { + std::vector box; + BoxCells(s->BBox().min,s->BBox().max,box); + for (std::vector::iterator bi=box.begin();bi box; + BoxCells(s->BBox().min,s->BBox().max,box); + for (std::vector::iterator bi=box.begin();bi + void AddElems( ContElemType & elem_set) + { + typename ContElemType::iterator i; + for(i = elem_set.begin(); i!= elem_set.end(); ++i) + AddElem(&(*i)); + } + + + + ////********************************************************************* + //template + // bool usefirst(const A & a,const A & b)const {return a.first < b.first;} + + int ClosestK(const int& k,ElemType* e, std::vector& res) + { + typedef std::pair ElemDist; + std::vector neigh_dist; + std::vector::iterator ite_nd; + std::vector neigh; + std::vector::iterator i_neigh; + typename ElemType::CoordType p = e->P(); + ScalarType radius,tmp,d; + + // set the radius as the distance to the closest face + radius = p[2]-floor(p[2]/l)*l; + if(radius > l*0.5) radius = l -radius; + tmp = p[1]-floor(p[1]/l)*l; + if(tmp > l*0.5) tmp = l -tmp; + if(radius > tmp) tmp = radius; + tmp = p[0]-floor(p[0]/l)*l; + if(tmp > l*0.5) tmp = l -tmp; + if(radius > tmp) radius = tmp; + + int x,y,z; + vcg::Point3i mincorner,maxcorner,c; + c = PointToCell(p); + mincorner = maxcorner = c; + neigh_dist.push_back(ElemDist(-1,e)); + ite_nd = neigh_dist.begin(); + + while((int)res.size() < k) { - neigh.clear(); - getAtCell(vcg::Point3i(x,y,z),neigh); - for(i_neigh = neigh.begin(); i_neigh != neigh.end(); ++i_neigh) + //run on the border + for( z = mincorner[2]; z <= maxcorner[2]; ++z) + for( y = mincorner[1]; y <= maxcorner[1]; ++y) + for( x = mincorner[0]; x <= maxcorner[0];) { + + neigh.clear(); + getAtCell(vcg::Point3i(x,y,z),neigh); + for(i_neigh = neigh.begin(); i_neigh != neigh.end(); ++i_neigh) + { d = Distance(p,(*i_neigh)->P()); if( (*i_neigh) != e) neigh_dist.push_back(ElemDist(d,*i_neigh)); } - if( - ( ( y == mincorner[1]) || ( y == maxcorner[1])) || - ( ( z == mincorner[2]) || ( z == maxcorner[2])) || - ( x == maxcorner[0]) - )++x; else x=maxcorner[0]; + if( + ( ( y == mincorner[1]) || ( y == maxcorner[1])) || + ( ( z == mincorner[2]) || ( z == maxcorner[2])) || + ( x == maxcorner[0]) + )++x; else x=maxcorner[0]; + } + // ,usefirst ---::iterator > + ite_nd =neigh_dist.begin(); + std::advance(ite_nd,res.size()); + std::sort(ite_nd,neigh_dist.end()); + while ( ( (int)res.size() < k ) && (ite_nd != neigh_dist.end())) + { + if((*ite_nd).first < radius) + res.push_back( (*ite_nd).second ); + ++ite_nd; + } + + mincorner -= vcg::Point3i(1,1,1); + maxcorner += vcg::Point3i(1,1,1); + radius+=l; + + } + return 0; } -// ,usefirst ---::iterator > - ite_nd =neigh_dist.begin(); - std::advance(ite_nd,res.size()); - std::sort(ite_nd,neigh_dist.end()); - while ( ( (int)res.size() < k ) && (ite_nd != neigh_dist.end())) - { - if((*ite_nd).first < radius) - res.push_back( (*ite_nd).second ); - ++ite_nd; - } - - mincorner -= vcg::Point3i(1,1,1); - maxcorner += vcg::Point3i(1,1,1); - radius+=l; - - } - return 0; - } -//********************************************************************** + //********************************************************************** - // return the elem closer than radius - int CloserThan( typename ElemType::CoordType p, - typename ElemType::ScalarType radius, - std::vector & closers){ - ClosersIterator cli; - cli.Init(this,p,radius); - while(!cli.End()){ - if ( (((*cli)->P() -p )*((*cli)->P() -p ) < radius*radius) && - (*cli.curr_i).second >= tempMark) - closers.push_back(*cli); - ++cli; - } - return (int)closers.size(); - } + // return the elem closer than radius + int CloserThan( typename ElemType::CoordType p, + typename ElemType::ScalarType radius, + std::vector & closers){ + ClosersIterator cli; + cli.Init(this,p,radius); + while(!cli.End()){ + if ( (((*cli)->P() -p )*((*cli)->P() -p ) < radius*radius))// &&(*cli.curr_i).second >= tempMark) + closers.push_back(*cli); + ++cli; + } + return (int)closers.size(); + } - std::vector Cells(ElemType *s) - { - return BoxCells(s,s->BBox().min,s->BBox().max); - } + std::vector Cells(ElemType *s) + { + return BoxCells(s,s->BBox().min,s->BBox().max); + } - inline Point3i MinCell() - { - return Cell(min); - } + inline Point3i MinCell() + { + return PointToCell(min); + } - inline Point3i MaxCell() - { - return Cell(max); - } + inline Point3i MaxCell() + { + return PointToCell(max); + } - inline int numElemCell(Point3i _c) - { - int h=Hash(_c); - if (hash_table.count(h)==0) - return 0; - else - { - IteHtable Ih=hash_table.find(h); - return ((*Ih).second.Size()); - } - } + /*inline int numElemCell(Point3i _c) + { + int h=Hash(_c); + if (hash_table.count(h)==0) + return 0; + else + { + 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) + { + return(numElemCell(_c)==0); + }*/ - inline bool IsEmptyCell(Point3i _c) - { - int h=Hash(_c); - if (hash_table.count(h)==0) - return true; - else - return false; - } - - - void Clear() - { - hash_table.clear(); - } + /*inline bool IsEmptyCell(Point3i _c) + { + int h=Hash(_c); + if (hash_table.count(h)==0) + return true; + else + return false; + }*/ - //void std::vector getAt(CoordType _p,std::vector & res) - //{ - // std::vector result; - // Point3i c=Cell(_p); - // return (getAtCell(c,res)); - //} + ///return the number of cell created + int CellNumber() + {return (hash_table.size());} + + int Conflicts() + {return conflicts;} - void getAtCell(Point3i _c,std::vector & res) - { - std::vector result; - int h=Hash(_c); - if (numElemCell(_c)!=0){ - IteHtable h_res=hash_table.find(h); - ((*h_res).second.Elems(tempMark,res)); - } - } + void Clear() + { + hash_table.clear(); + } + + void UpdateTmark() + {tempMark++;} + + ///only debug + void DrawCell(HElement &c) + { + glPushMatrix(); + glTranslate(c.Min()+vcg::Point3d(l/2,l/2,l/2)); + glutWireCube(l); + glPopMatrix(); + } - const Point3i Cell(const CoordType & p) const - { - 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); - } + void Draw() + { + 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