#ifndef SPATIAL_HASHING #define SPATIAL_HASHING //#define P0 73856093 //#define P1 19349663 //#define P2 83492791 #define P0 73 #define P1 19 #define P2 83 #include #include #include template class SpatialHashTable{ public: typedef typename SimplexType* SimplexPointer; typedef typename SimplexType::CoordType Point3x; typedef typename Point3x::ScalarType ScalarType; //iterator to the map element into the cell typedef typename std::map::iterator IteMap; //element of a cell typedef typename std::pair MapCellElem; //element stored in the hash table struct Helement { std::map Elem; //int flag; public: Helement() { // flag=0; } Helement(SimplexType* sim,int _tempMark) { Elem.insert(MapCellElem(sim,_tempMark)); // flag=0; } ///return true if the element is in the cell bool IsIn(SimplexType* sim) { int n=Elem.count(sim); return (n==1); } int Size() { return (Elem.size()); } ///update or insert an element into a cell void Update(SimplexType* sim,int _tempMark) { std::pair 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 timastamp or are not deleted std::vector Simplexes(int _tempMark) { std::vector result; result.clear(); for (IteMap ite=Elem.begin();ite!=Elem.end();ite++) { SimplexType* sim=(*ite).first; int t=(*ite).second; if ((!sim->IsD())&&(t>=_tempMark)) result.push_back(sim); } return (result); } }; //enum { // // First user bit // USER0 = 0x0001 // First user bit // }; //static int &LastBitFlag() // { // static int b =USER0; // return b; // } ///// allocate a bit among the flags that can be used by user. //static inline int NewBitFlag() // { // LastBitFlag()=LastBitFlag()<<1; // return LastBitFlag(); // } //// 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 typedef typename std::hash_map Htable; //record of the hash table typedef typename std::pair HRecord; //iterator to the hash table typedef typename Htable::iterator IteHtable; //SpatialHashTable(ContSimplex & r_):_simplex(r_){}; SpatialHashTable(){}; ~SpatialHashTable(){}; //ContSimplex & _simplex; int TempMark; Htable hash_table; int num; float l; Point3x min; Point3x max; void Init(Point3x _min,Point3x _max,ScalarType _l) { min=_min; max=_max; l=_l; Point3x d=max-min; num=floor(d.V(0)*d.V(1)*d.V(2)/l); TempMark=0; } void InsertInCell(SimplexType* 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); } } std::vector addBox(SimplexType* s,Point3x _min,Point3x _max) { std::vector box=BoxCells(_min,_max); for (std::vector::iterator bi=box.begin();bi BoxCells(Point3x _min,Point3x _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; } std::vector Cells(SimplexType *s) { Point3x min=Point3x((*s).V(0)->P()); 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); } return BoxCells(s,min,max); } std::vector addSimplex(SimplexType *s) { Point3x min=Point3x((*s).V(0)->P()); 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() { return Cell(min); } inline Point3i MaxCell() { return Cell(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()); } } ///refresh all the alement in the container /*void RefreshElements() { TempMark++; for (SimplexIterator si=_simplex.begin();si<_simplex.end();++si) { if (!(*si).IsD()) addSimplex(&*si); } }*/ ///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() { hash_table.clear(); } /*int FlagCell(Point3i 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 getAt(Point3x _p) { std::vector result; Point3i c=Cell(p); return (getAtCell(c)); } std::vector getAtCell(Point3i _c) { std::vector result; int h=Hash(_c); if (numElemCell(_c)==0) { return result; } else { IteHtable res=hash_table.find(h); return ((*res).second.Simplexes(TempMark)); } } private: Point3i Cell(Point3x p) { int x=floor(p.V(0)/l); int y=floor(p.V(1)/l); int z=floor(p.V(2)/l); return Point3i(x,y,z); } int Hash(Point3i p) { return ((p.V(0)*P0 ^ p.V(1)*P1 ^ p.V(2)*P2)%num); } }; #endif