spatial_hashing2d.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2004                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
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 //#include <map>
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         // hashing function
00058         struct HashFunctor2D : public std::unary_function<Point2i, size_t>
00059         {
00060                 enum
00061                 { // parameters for hash table
00062                         bucket_size = 4, // 0 < bucket_size
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             //const size_t _HASH_P2 = 83492791u;
00071 
00072             return size_t(p.V(0))*_HASH_P0 ^  size_t(p.V(1))*_HASH_P1;// ^  size_t(p.V(2))*_HASH_P2;
00073         }
00074 
00075         bool operator()(const Point2i &s1, const Point2i &s2) const
00076         { // test if s1 ordered before s2
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         // Hash table definition
00101         // the hash index directly the grid structure.
00102         // We use a MultiMap because we need to store many object (faces) inside each cell of the grid.
00103 
00104                 typedef typename STDEXT::hash_multimap<Point2i, ObjType *, HashFunctor2D> HashType;
00105                 typedef typename HashType::iterator HashIterator;
00106                 HashType hash_table; // The real HASH TABLE **************************************
00107 
00108         // This vector is just a handy reference to all the allocated cells,
00109         // becouse hashed multimaps does not expose a direct list of all the different keys.
00110         std::vector<Point2i> AllocatedCells;
00111 
00113         ScalarType cell_size;
00114 
00115         // Class to abstract a HashIterator (that stores also the key,
00116         // while the interface of the generic spatial indexing need only simple object (face) pointers.
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 &/*cell*/)
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             //then insert all the cell of bb
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                 //then insert all the cell of bb
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                 //for (unsigned int i=0;i<Boxes.size();i++)
00231                 //    AddBox(s,Boxes[i]);
00232                 AddBoxes(s,Boxes);
00233             }
00234         }
00235 
00237         // it removes s too.
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     /*  int RemoveInSphere(const Point3<ScalarType> &p, const ScalarType radius)
00248         {
00249             Box3x b(p-Point3f(radius,radius,radius),p+Point3f(radius,radius,radius));
00250             vcg::Box3i bb;
00251             this->BoxToIBox(b,bb);
00252             ScalarType r2=radius*radius;
00253             int cnt=0;
00254             std::vector<HashIterator> toDel;
00255 
00256             for (int i=bb.min.X();i<=bb.max.X();i++)
00257                 for (int j=bb.min.Y();j<=bb.max.Y();j++)
00258                     for (int k=bb.min.Z();k<=bb.max.Z();k++)
00259                     {
00260                         std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(Point3i(i,j,k));
00261                         for(HashIterator hi = CellRange.first; hi!=CellRange.second;++hi)
00262                         {
00263                             if(SquaredDistance(p,hi->second->cP()) <= r2)
00264                             {
00265                                 cnt++;
00266                                 toDel.push_back(hi);
00267                             }
00268                         }
00269                     }
00270                     for(typename std::vector<HashIterator>::iterator vi=toDel.begin(); vi!=toDel.end();++vi)
00271                         hash_table.erase(*vi);
00272 
00273                     return cnt;
00274         }*/
00276         //template<class DistanceFunctor>
00277         //int RemoveInSphereNormal(const Point3<ScalarType> &p, const Point3<ScalarType> &n, DistanceFunctor &DF, const ScalarType radius)
00278         //{
00279         //      Box3x b(p-Point3f(radius,radius,radius),p+Point3f(radius,radius,radius));
00280         //      vcg::Box3i bb;
00281         //      this->BoxToIBox(b,bb);
00282         //      int cnt=0;
00283         //      std::vector<HashIterator> toDel;
00284 
00285         //      for (int i=bb.min.X();i<=bb.max.X();i++)
00286         //              for (int j=bb.min.Y();j<=bb.max.Y();j++)
00287         //                      for (int k=bb.min.Z();k<=bb.max.Z();k++)
00288         //                      {
00289         //                              std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(Point3i(i,j,k));
00290         //                              for(HashIterator hi = CellRange.first; hi!=CellRange.second;++hi)
00291         //                              {
00292         //                                      if(DF(p,n,hi->second->cP(),hi->second->cN()) <= radius)
00293         //                                      {
00294         //                                              cnt++;
00295         //                                              toDel.push_back(hi);
00296         //                                      }
00297         //                              }
00298         //                      }
00299         //                      for(typename std::vector<HashIterator>::iterator vi=toDel.begin(); vi!=toDel.end();++vi)
00300         //                              hash_table.erase(*vi);
00301 
00302         //                      return cnt;
00303         //}
00304 
00307 
00308         //void RemovePunctual( ObjType *s)
00309         //{
00310         //      Point3i pi;
00311         //      PToIP(s->cP(),pi);
00312         //      std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(pi);
00313         //      for(HashIterator hi = CellRange.first; hi!=CellRange.second;++hi)
00314         //      {
00315         //              if (hi->second == s)
00316         //              {
00317         //                      hash_table.erase(hi);
00318         //                      return;
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             //then remove the obj from all the cell of bb
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                     //for (int k=bb.min.Z();k<=bb.max.Z();k++)
00333                         RemoveObject(s,vcg::Point2i(i,j));//,k));
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));//&&(grid_size.V(2)>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         /*template <class OBJITER>
00360         void Set(const OBJITER & _oBegin, const OBJITER & _oEnd, const Box2x &_bbox=Box2x() )
00361         {
00362             OBJITER i;
00363             Box2x b;
00364             Box2x &bbox = this->bbox;
00365             CoordType &dim = this->dim;
00366             Point2i &siz = this->siz;
00367             CoordType &voxel = this->voxel;
00368 
00369             int _size=(int)std::distance<OBJITER>(_oBegin,_oEnd);
00370             if(!_bbox.IsNull()) this->bbox=_bbox;
00371             else
00372             {
00373                 for(i = _oBegin; i!= _oEnd; ++i)
00374                 {
00375                     (*i).GetBBox(b);
00376                     this->bbox.Add(b);
00377                 }
00379                 bbox.Offset(bbox.Diag()/100.0) ;
00380             }
00381 
00382             dim  = bbox.max - bbox.min;
00383             BestDim2D( _size, dim, siz );
00384             // find voxel size
00385             voxel[0] = dim[0]/siz[0];
00386             voxel[1] = dim[1]/siz[1];
00387             //voxel[2] = dim[2]/siz[2];
00388 
00389             for(i = _oBegin; i!= _oEnd; ++i)
00390                 Add(&(*i));
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             // find voxel size
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                             // cell size estimation
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                             // cell size assignment
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         /*template <class OBJPOINTDISTFUNCTOR, class OBJMARKER>
00510         ObjPtr  GetClosest(OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker,
00511             const CoordType & _p, const ScalarType & _maxDist,ScalarType & _minDist, CoordType & _closestPt)
00512         {
00513             return (vcg::GridClosest<SpatialHashType,OBJPOINTDISTFUNCTOR,OBJMARKER>(*this,_getPointDistance,_marker, _p,_maxDist,_minDist,_closestPt));
00514         }
00515 
00516 
00517         template <class OBJPOINTDISTFUNCTOR, class OBJMARKER, class OBJPTRCONTAINER,class DISTCONTAINER, class POINTCONTAINER>
00518         unsigned int GetKClosest(OBJPOINTDISTFUNCTOR & _getPointDistance,OBJMARKER & _marker,
00519             const unsigned int _k, const CoordType & _p, const ScalarType & _maxDist,OBJPTRCONTAINER & _objectPtrs,
00520             DISTCONTAINER & _distances, POINTCONTAINER & _points)
00521         {
00522             return (vcg::GridGetKClosest<SpatialHashType,
00523                 OBJPOINTDISTFUNCTOR,OBJMARKER,OBJPTRCONTAINER,DISTCONTAINER,POINTCONTAINER>
00524                 (*this,_getPointDistance,_marker,_k,_p,_maxDist,_objectPtrs,_distances,_points));
00525         }
00526 
00527         template <class OBJPOINTDISTFUNCTOR, class OBJMARKER, class OBJPTRCONTAINER, class DISTCONTAINER, class POINTCONTAINER>
00528         unsigned int GetInSphere(OBJPOINTDISTFUNCTOR & _getPointDistance,
00529             OBJMARKER & _marker,
00530             const CoordType & _p,
00531             const ScalarType & _r,
00532             OBJPTRCONTAINER & _objectPtrs,
00533             DISTCONTAINER & _distances,
00534             POINTCONTAINER & _points)
00535         {
00536             return(vcg::GridGetInSphere<SpatialHashType,
00537                 OBJPOINTDISTFUNCTOR,OBJMARKER,OBJPTRCONTAINER,DISTCONTAINER,POINTCONTAINER>
00538                 (*this,_getPointDistance,_marker,_p,_r,_objectPtrs,_distances,_points));
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     }; // end class
00561 
00562 
00563 
00564     } // end namespace
00565 
00566 #endif


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:36:31