00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef VCGLIB_SPATIAL_HASHING_2D
00025 #define VCGLIB_SPATIAL_HASHING_2D
00026
00027 #include <vcg/space/index/grid_util2d.h>
00028 #include <vcg/space/index/grid_closest2d.h>
00029
00030 #include <vector>
00031 #include <algorithm>
00032 #ifdef _WIN32
00033 #ifndef __MINGW32__
00034 #include <hash_map>
00035 #define STDEXT stdext
00036 #else
00037 #include <ext/hash_map>
00038 #define STDEXT __gnu_cxx
00039 #endif
00040 #else // We are in the *nix gcc branch
00041 #if (__GNUC__ ==4) && (__GNUC_MINOR__ > 3) && (defined(__DEPRECATED))
00042 #undef __DEPRECATED // since gcc 4.4 <ext/hash_map> was deprecated and generate warnings. Relax Deprecation Just for this...
00043 #define ___WE_UNDEFINED_DEPRECATED__
00044 #endif
00045 #include <ext/hash_map>
00046 #define STDEXT __gnu_cxx
00047 #if defined(___WE_UNDEFINED_DEPRECATED__)
00048 #define __DEPRECATED
00049 #endif
00050 #endif
00051
00052
00053 namespace vcg{
00054
00055
00056
00057
00058 struct HashFunctor2D : public std::unary_function<Point2i, size_t>
00059 {
00060 enum
00061 {
00062 bucket_size = 4,
00063 min_buckets = 8
00064 };
00065
00066 size_t operator()(const Point2i &p) const
00067 {
00068 const size_t _HASH_P0 = 73856093u;
00069 const size_t _HASH_P1 = 19349663u;
00070
00071
00072 return size_t(p.V(0))*_HASH_P0 ^ size_t(p.V(1))*_HASH_P1;
00073 }
00074
00075 bool operator()(const Point2i &s1, const Point2i &s2) const
00076 {
00077 return (s1 < s2);
00078 }
00079 };
00080
00081
00082
00083
00089 template < typename ObjType,class FLT=double>
00090 class SpatialHashTable2D:public BasicGrid2D<FLT>, public SpatialIndex2D<ObjType,FLT>
00091 {
00092
00093 public:
00094 typedef SpatialHashTable2D SpatialHashType;
00095 typedef ObjType* ObjPtr;
00096 typedef typename ObjType::ScalarType ScalarType;
00097 typedef Point2<ScalarType> CoordType;
00098 typedef typename BasicGrid2D<FLT>::Box2x Box2x;
00099
00100
00101
00102
00103
00104 typedef typename STDEXT::hash_multimap<Point2i, ObjType *, HashFunctor2D> HashType;
00105 typedef typename HashType::iterator HashIterator;
00106 HashType hash_table;
00107
00108
00109
00110 std::vector<Point2i> AllocatedCells;
00111
00113 ScalarType cell_size;
00114
00115
00116
00117
00118 struct CellIterator
00119 {
00120 CellIterator(){}
00121 HashIterator t;
00122 ObjPtr &operator *(){return (t->second); }
00123 ObjPtr operator *() const {return (t->second); }
00124 bool operator != (const CellIterator & p) const {return t!=p.t;}
00125 void operator ++() {t++;}
00126 };
00127
00128 inline bool Empty() const
00129 {
00130 return hash_table.empty();
00131 }
00132
00133 size_t CellSize(const Point3i &cell)
00134 {
00135 return hash_table.count(cell);
00136 }
00137
00138 inline bool EmptyCell(const Point3i &cell) const
00139 {
00140 return hash_table.find(cell) == hash_table.end();
00141 }
00142
00143 void UpdateAllocatedCells()
00144 {
00145 AllocatedCells.clear();
00146 if(hash_table.empty()) return;
00147 AllocatedCells.push_back(hash_table.begin()->first);
00148 for(HashIterator fi=hash_table.begin();fi!=hash_table.end();++fi)
00149 {
00150 if(AllocatedCells.back()!=fi->first) AllocatedCells.push_back(fi->first);
00151 }
00152 }
00153 protected:
00154
00156 void InsertObject(ObjType* s, const Point2i &cell)
00157 {
00158 hash_table.insert(typename HashType::value_type(cell, s));
00159 }
00160
00162 void RemoveCell(const Point3i &)
00163 {
00164 }
00165
00166
00167 bool RemoveObject(ObjType* s, const Point2i &cell)
00168 {
00169 std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(cell);
00170 CellIterator first; first.t=CellRange.first;
00171 CellIterator end; end.t=CellRange.second;
00172 for(CellIterator ci = first; ci!=end;++ci)
00173 {
00174 if (*ci == s)
00175 {
00176 hash_table.erase(ci.t);
00177 return true;
00178 }
00179 }
00180 return false;
00181 }
00182
00183 void AddBox(ObjType* s,
00184 const Box2<ScalarType> &b)
00185 {
00186 vcg::Box2i bb;
00187 this->BoxToIBox(b,bb);
00188
00189 for (int i=bb.min.X();i<=bb.max.X();i++)
00190 for (int j=bb.min.Y();j<=bb.max.Y();j++)
00191 InsertObject(s,vcg::Point2i(i,j));
00192 }
00193
00194 void AddBoxes(ObjType* s,
00195 const std::vector<Box2<ScalarType> > &boxes)
00196 {
00197 std::vector<vcg::Point2i> Indexes;
00198 for (unsigned int i=0;i<boxes.size();i++)
00199 {
00200 vcg::Box2i bb;
00201 this->BoxToIBox(boxes[i],bb);
00202
00203 for (int i=bb.min.X();i<=bb.max.X();i++)
00204 for (int j=bb.min.Y();j<=bb.max.Y();j++)
00205 Indexes.push_back(vcg::Point2i(i,j));
00206 }
00207 std::sort(Indexes.begin(),Indexes.end());
00208 std::vector<vcg::Point2i>::iterator it=std::unique(Indexes.begin(),Indexes.end());
00209 Indexes.resize( it - Indexes.begin() );
00210
00211 for (int i=0;i<Indexes.size();i++)
00212 InsertObject(s,Indexes[i]);
00213 }
00214
00215 public:
00216
00217 void Add( ObjType* s,bool subdivideBox=false)
00218 {
00219
00220 if (!subdivideBox)
00221 {
00222 Box2<ScalarType> b;
00223 s->GetBBox(b);
00224 AddBox(s,b);
00225 }
00226 else
00227 {
00228 std::vector<Box2<ScalarType> > Boxes;
00229 s->GetSubBBox(cell_size,Boxes);
00230
00231
00232 AddBoxes(s,Boxes);
00233 }
00234 }
00235
00237
00238 bool RemoveCell(ObjType* s)
00239 {
00240 Point3i pi;
00241 PToIP(s->cP(),pi);
00242 std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(pi);
00243 hash_table.erase(CellRange.first,CellRange.second);
00244 return true;
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 void Remove( ObjType* s)
00324 {
00325 Box2<ScalarType> b;
00326 s->GetBBox(b);
00327 vcg::Box2i bb;
00328 BoxToIBox(b,bb);
00329
00330 for (int i=bb.min.X();i<=bb.max.X();i++)
00331 for (int j=bb.min.Y();j<=bb.max.Y();j++)
00332
00333 RemoveObject(s,vcg::Point2i(i,j));
00334 }
00335
00337 void InitEmpty(const Box2x &_bbox, vcg::Point2i grid_size)
00338 {
00339 Box2x b;
00340 Box2x &bbox = this->bbox;
00341 CoordType &dim = this->dim;
00342 Point2i &siz = this->siz;
00343 CoordType &voxel = this->voxel;
00344
00345 assert(!_bbox.IsNull());
00346 bbox=_bbox;
00347 dim = bbox.max - bbox.min;
00348 assert((grid_size.V(0)>0)&&(grid_size.V(1)>0));
00349 siz=grid_size;
00350
00351 voxel[0] = dim[0]/siz[0];
00352 voxel[1] = dim[1]/siz[1];
00353 cell_size=voxel.Norm();
00354
00355 hash_table.clear();
00356 }
00357
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00395 template <class OBJITER>
00396 void Set(const OBJITER & _oBegin, const OBJITER & _oEnd,
00397 bool subdivideBox=false,const Box2x &_bbox=Box2x() )
00398 {
00399 OBJITER i;
00400 Box2x b;
00401 Box2x &bbox = this->bbox;
00402 CoordType &dim = this->dim;
00403 Point2i &siz = this->siz;
00404 CoordType &voxel = this->voxel;
00405
00406 int _size=(int)std::distance<OBJITER>(_oBegin,_oEnd);
00407 if(!_bbox.IsNull()) this->bbox=_bbox;
00408 else
00409 {
00410 for(i = _oBegin; i!= _oEnd; ++i)
00411 {
00412 (*i)->GetBBox(b);
00413 this->bbox.Add(b);
00414 }
00416 bbox.Offset(bbox.Diag()/100.0) ;
00417 }
00418
00419 dim = bbox.max - bbox.min;
00420 BestDim2D( _size, dim, siz );
00421
00422 voxel[0] = dim[0]/siz[0];
00423 voxel[1] = dim[1]/siz[1];
00424 cell_size=voxel.Norm();
00425
00426 for(i = _oBegin; i!= _oEnd; ++i)
00427 {
00428 Add(&(*i),subdivideBox);
00429 }
00430 }
00431
00433 template <class OBJITER>
00434 void SetByPointers(const OBJITER & _oBegin, const OBJITER & _oEnd,
00435 const Point2i & cellsize=Point2i(-1,-1), bool subdivideBox=false,const Box2x &_bbox=Box2x() )
00436 {
00437 OBJITER i;
00438 Box2x b;
00439 Box2x &bbox = this->bbox;
00440 CoordType &dim = this->dim;
00441 Point2i &siz = this->siz;
00442 CoordType &voxel = this->voxel;
00443
00444 int _size=(int)std::distance<OBJITER>(_oBegin,_oEnd);
00445 if(!_bbox.IsNull()) this->bbox=_bbox;
00446 else
00447 {
00448 for(i = _oBegin; i!= _oEnd; ++i)
00449 {
00450 (*i)->GetBBox(b);
00451 this->bbox.Add(b);
00452 }
00454 bbox.Offset(bbox.Diag()/100.0) ;
00455 }
00456
00457 if (cellsize[0] < 0 && cellsize[1] < 0)
00458 {
00459
00460 dim = bbox.max - bbox.min;
00461 BestDim2D( _size, dim, siz );
00462 voxel[0] = dim[0]/siz[0];
00463 voxel[1] = dim[1]/siz[1];
00464 }
00465 else
00466 {
00467
00468 voxel[0] = cellsize[0];
00469 voxel[1] = cellsize[1];
00470 }
00471
00472 cell_size=voxel.Norm();
00473
00474 for(i = _oBegin; i!= _oEnd; ++i)
00475 {
00476 Add(*i,subdivideBox);
00477 }
00478 }
00479
00481 void GridReal( const Point2<ScalarType> & p, CellIterator & first, CellIterator & last )
00482 {
00483 vcg::Point2i _c;
00484 this->PToIP(p,_c);
00485 Grid(_c,first,last);
00486 }
00487
00489 void Grid( int x,int y, CellIterator & first, CellIterator & last )
00490 {
00491 this->Grid(vcg::Point2i(x,y),first,last);
00492 }
00493
00495 void Grid( const Point2i & _c, CellIterator & first, CellIterator & end )
00496 {
00497 std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(_c);
00498 first.t=CellRange.first;
00499 end.t=CellRange.second;
00500 }
00501
00502 void Clear()
00503 {
00504 hash_table.clear();
00505 AllocatedCells.clear();
00506 }
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 template <class OBJMARKER, class OBJPTRCONTAINER>
00542 unsigned int GetInBox(OBJMARKER & _marker,
00543 const Box2x _bbox,
00544 OBJPTRCONTAINER & _objectPtrs)
00545 {
00546 _objectPtrs.clear();
00547 return(vcg::GridGetInBox2D<SpatialHashType,OBJMARKER,OBJPTRCONTAINER>
00548 (*this,_marker,_bbox,_objectPtrs));
00549 }
00550
00551 template <class OBJMARKER, class OBJPTRCONTAINER>
00552 unsigned int GetInBoxes(OBJMARKER & _marker,
00553 const std::vector<Box2x> &_bbox,
00554 OBJPTRCONTAINER &_objectPtrs)
00555 {
00556 _objectPtrs.clear();
00557 return(vcg::GridGetInBoxes2D<SpatialHashType,OBJMARKER,OBJPTRCONTAINER>
00558 (*this,_marker,_bbox,_objectPtrs));
00559 }
00560 };
00561
00562
00563
00564 }
00565
00566 #endif