spatial_hashing.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
00025 #define VCGLIB_SPATIAL_HASHING
00026 
00027 #include <vcg/space/index/grid_util.h>
00028 #include <vcg/space/index/grid_closest.h>
00029 #include<unordered_map>
00030 //#include <map>
00031 #include <vector>
00032 #include <algorithm>
00033 
00034 namespace vcg{
00035 
00036 
00037 
00038     // hashing function
00039     struct HashFunctor : public std::unary_function<Point3i, size_t>
00040     {
00041         enum
00042           { // parameters for hash table
00043                 bucket_size = 4, // 0 < bucket_size
00044                 min_buckets = 8
00045             };
00046 
00047         size_t operator()(const Point3i &p) const
00048         {
00049             const size_t _HASH_P0 = 73856093u;
00050             const size_t _HASH_P1 = 19349663u;
00051             const size_t _HASH_P2 = 83492791u;
00052 
00053             return size_t(p.V(0))*_HASH_P0 ^  size_t(p.V(1))*_HASH_P1 ^  size_t(p.V(2))*_HASH_P2;
00054         }
00055 
00056         bool operator()(const Point3i &s1, const Point3i &s2) const
00057         { // test if s1 ordered before s2
00058             return (s1 < s2);
00059         }
00060     };
00061 
00062 
00063 
00064 
00070     template < typename ObjType,class FLT=double>
00071     class SpatialHashTable:public BasicGrid<FLT>, public SpatialIndex<ObjType,FLT>
00072     {
00073 
00074     public:
00075     typedef SpatialHashTable SpatialHashType;
00076     typedef ObjType* ObjPtr;
00077     typedef typename ObjType::ScalarType ScalarType;
00078     typedef Point3<ScalarType> CoordType;
00079     typedef typename BasicGrid<FLT>::Box3x Box3x;
00080 
00081     // Hash table definition
00082     // the hash index directly the grid structure.
00083     // We use a MultiMap because we need to store many object (faces) inside each cell of the grid.
00084 
00085     typedef typename std::unordered_multimap<Point3i, ObjType *, HashFunctor> HashType;
00086     typedef typename HashType::iterator HashIterator;
00087     HashType hash_table; // The real HASH TABLE **************************************
00088 
00089     // This vector is just a handy reference to all the allocated cells,
00090     // becouse hashed multimaps does not expose a direct list of all the different keys.
00091     std::vector<Point3i> AllocatedCells;
00092 
00093     // Class to abstract a HashIterator (that stores also the key,
00094     // while the interface of the generic spatial indexing need only simple object (face) pointers.
00095 
00096     struct CellIterator
00097     {
00098         CellIterator(){}
00099         HashIterator t;
00100         ObjPtr &operator *(){return (t->second); }
00101         ObjPtr operator *() const {return (t->second); }
00102         bool operator != (const CellIterator & p) const {return t!=p.t;}
00103         void operator ++() {t++;}
00104     };
00105 
00106   inline bool Empty() const
00107   {
00108     return hash_table.empty();
00109   }
00110 
00111     size_t CellSize(const Point3i &cell)
00112     {
00113         return hash_table.count(cell);
00114     }
00115 
00116         inline bool EmptyCell(const Point3i &cell) const
00117         {
00118          return hash_table.find(cell) == hash_table.end();
00119         }
00120 
00121         void UpdateAllocatedCells()
00122         {
00123             AllocatedCells.clear();
00124             if(hash_table.empty()) return;
00125             AllocatedCells.push_back(hash_table.begin()->first);
00126             for(HashIterator fi=hash_table.begin();fi!=hash_table.end();++fi)
00127             {
00128                 if(AllocatedCells.back()!=fi->first) AllocatedCells.push_back(fi->first);
00129             }
00130         }
00131 protected:
00132 
00134     void InsertObject(ObjType* s, const Point3i &cell)
00135     {
00136         //if(hash_table.count(cell)==0) AllocatedCells.push_back(cell);
00137         hash_table.insert(typename HashType::value_type(cell, s));
00138     }
00139 
00141     void RemoveCell(const Point3i &/*cell*/)
00142     {
00143     }
00144 
00145 
00146     bool RemoveObject(ObjType* s, const Point3i &cell)
00147     {
00148         std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(cell);
00149         CellIterator first; first.t=CellRange.first;
00150         CellIterator end; end.t=CellRange.second;
00151         for(CellIterator ci = first; ci!=end;++ci)
00152         {
00153             if (*ci == s)
00154                {
00155                    hash_table.erase(ci.t);
00156                    return true;
00157                }
00158         }
00159         return false;
00160     }
00161 
00162     public:
00163 
00164         vcg::Box3i Add( ObjType* s)
00165         {
00166             Box3<ScalarType> b;
00167             s->GetBBox(b);
00168             vcg::Box3i bb;
00169       this->BoxToIBox(b,bb);
00170             //then insert all the cell of bb
00171             for (int i=bb.min.X();i<=bb.max.X();i++)
00172                 for (int j=bb.min.Y();j<=bb.max.Y();j++)
00173                     for (int k=bb.min.Z();k<=bb.max.Z();k++)
00174                         InsertObject(s,vcg::Point3i(i,j,k));
00175 
00176             return bb;
00177         }
00178 
00180         // it removes s too.
00181         bool RemoveCell(ObjType* s)
00182         {
00183             Point3i pi;
00184             PToIP(s->cP(),pi);
00185             std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(pi);
00186             hash_table.erase(CellRange.first,CellRange.second);
00187             return true;
00188         }    
00189 
00190         int CountInSphere(const Point3<ScalarType> &p, const ScalarType radius, std::vector<HashIterator> &inSphVec)
00191         {
00192           Box3x b(p-CoordType(radius,radius,radius),p+CoordType(radius,radius,radius));
00193           vcg::Box3i bb;
00194           this->BoxToIBox(b,bb);
00195           ScalarType r2=radius*radius;
00196           inSphVec.clear();
00197 
00198           for (int i=bb.min.X();i<=bb.max.X();i++)
00199             for (int j=bb.min.Y();j<=bb.max.Y();j++)
00200               for (int k=bb.min.Z();k<=bb.max.Z();k++)
00201               {
00202                 std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(Point3i(i,j,k));
00203                 for(HashIterator hi = CellRange.first; hi!=CellRange.second;++hi)
00204                 {
00205                   if(SquaredDistance(p,hi->second->cP()) <= r2)
00206                     inSphVec.push_back(hi);
00207                 }
00208               }
00209           return inSphVec.size();
00210         }
00211 
00212         int RemoveInSphere(const Point3<ScalarType> &p, const ScalarType radius)
00213         {
00214           std::vector<HashIterator> inSphVec;
00215           CountInSphere(p,radius,inSphVec);
00216             for(typename std::vector<HashIterator>::iterator vi=inSphVec.begin(); vi!=inSphVec.end();++vi)
00217                 hash_table.erase(*vi);
00218 
00219             return inSphVec.size();
00220         }
00221         // Specialized version that is able to take in input a
00222         template<class DistanceFunctor>
00223         int RemoveInSphereNormal(const Point3<ScalarType> &p, const Point3<ScalarType> &n, DistanceFunctor &DF, const ScalarType radius)
00224         {
00225             Box3x b(p-CoordType(radius,radius,radius),p+CoordType(radius,radius,radius));
00226             vcg::Box3i bb;
00227             this->BoxToIBox(b,bb);
00228             int cnt=0;
00229             std::vector<HashIterator> toDel;
00230 
00231             for (int i=bb.min.X();i<=bb.max.X();i++)
00232                 for (int j=bb.min.Y();j<=bb.max.Y();j++)
00233                     for (int k=bb.min.Z();k<=bb.max.Z();k++)
00234                     {
00235                         std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(Point3i(i,j,k));
00236                         for(HashIterator hi = CellRange.first; hi!=CellRange.second;++hi)
00237                         {
00238                             if(DF(p,n,hi->second->cP(),hi->second->cN()) <= radius)
00239                             {
00240                                 cnt++;
00241                                 toDel.push_back(hi);
00242                             }
00243                         }
00244                     }
00245             for(typename std::vector<HashIterator>::iterator vi=toDel.begin(); vi!=toDel.end();++vi)
00246                 hash_table.erase(*vi);
00247 
00248             return cnt;
00249         }
00250 
00251     // This version of the removal is specialized for the case where
00252         // an object has a pointshaped box and using the generic bbox interface is just a waste of time.
00253 
00254         void RemovePunctual( ObjType *s)
00255         {
00256             Point3i pi;
00257             PToIP(s->cP(),pi);
00258             std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(pi);
00259             for(HashIterator hi = CellRange.first; hi!=CellRange.second;++hi)
00260             {
00261                 if (hi->second == s)
00262                    {
00263                        hash_table.erase(hi);
00264                        return;
00265                    }
00266             }
00267         }
00268 
00269         void Remove( ObjType* s)
00270         {
00271             Box3<ScalarType> b;
00272             s->GetBBox(b);
00273             vcg::Box3i bb;
00274             BoxToIBox(b,bb);
00275             //then remove the obj from all the cell of bb
00276             for (int i=bb.min.X();i<=bb.max.X();i++)
00277                 for (int j=bb.min.Y();j<=bb.max.Y();j++)
00278                     for (int k=bb.min.Z();k<=bb.max.Z();k++)
00279                         RemoveObject(s,vcg::Point3i(i,j,k));
00280         }
00281 
00283         void InitEmpty(const Box3x &_bbox, vcg::Point3i grid_size)
00284         {
00285             Box3x b;
00286             Box3x &bbox = this->bbox;
00287             CoordType &dim = this->dim;
00288             Point3i &siz = this->siz;
00289             CoordType &voxel = this->voxel;
00290 
00291             assert(!_bbox.IsNull());
00292             bbox=_bbox;
00293             dim  = bbox.max - bbox.min;
00294             assert((grid_size.V(0)>0)&&(grid_size.V(1)>0)&&(grid_size.V(2)>0));
00295             siz=grid_size;
00296 
00297             voxel[0] = dim[0]/siz[0];
00298             voxel[1] = dim[1]/siz[1];
00299             voxel[2] = dim[2]/siz[2];
00300             hash_table.clear();
00301         }
00302 
00304         template <class OBJITER>
00305             void Set(const OBJITER & _oBegin, const OBJITER & _oEnd, const Box3x &_bbox=Box3x() )
00306         {
00307             OBJITER i;
00308             Box3x b;
00309             Box3x &bbox = this->bbox;
00310             CoordType &dim = this->dim;
00311             Point3i &siz = this->siz;
00312             CoordType &voxel = this->voxel;
00313 
00314             int _size=(int)std::distance<OBJITER>(_oBegin,_oEnd);
00315             if(!_bbox.IsNull()) this->bbox=_bbox;
00316             else
00317             {
00318                 for(i = _oBegin; i!= _oEnd; ++i)
00319                 {
00320                     (*i).GetBBox(b);
00321                     this->bbox.Add(b);
00322                 }
00324                 bbox.Offset(bbox.Diag()/100.0) ;
00325             }
00326 
00327             dim  = bbox.max - bbox.min;
00328             BestDim( _size, dim, siz );
00329             // find voxel size
00330             voxel[0] = dim[0]/siz[0];
00331             voxel[1] = dim[1]/siz[1];
00332             voxel[2] = dim[2]/siz[2];
00333 
00334             for(i = _oBegin; i!= _oEnd; ++i)
00335                 Add(&(*i));
00336         }
00337 
00338 
00340         void GridReal( const Point3<ScalarType> & p, CellIterator & first, CellIterator & last )
00341         {
00342             vcg::Point3i _c;
00343             this->PToIP(p,_c);
00344             Grid(_c,first,last);
00345         }
00346 
00348         void Grid( int x,int y,int z, CellIterator & first, CellIterator & last )
00349         {
00350             this->Grid(vcg::Point3i(x,y,z),first,last);
00351         }
00352 
00354         void Grid( const Point3i & _c, CellIterator & first, CellIterator & end )
00355         {
00356             std::pair<HashIterator,HashIterator> CellRange = hash_table.equal_range(_c);
00357             first.t=CellRange.first;
00358             end.t=CellRange.second;
00359         }
00360 
00361         void Clear()
00362         {
00363             hash_table.clear();
00364             AllocatedCells.clear();
00365         }
00366 
00367 
00368         template <class OBJPOINTDISTFUNCTOR, class OBJMARKER>
00369             ObjPtr  GetClosest(OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker,
00370             const CoordType & _p, const ScalarType & _maxDist,ScalarType & _minDist, CoordType & _closestPt)
00371         {
00372             return (vcg::GridClosest<SpatialHashType,OBJPOINTDISTFUNCTOR,OBJMARKER>(*this,_getPointDistance,_marker, _p,_maxDist,_minDist,_closestPt));
00373         }
00374 
00375 
00376         template <class OBJPOINTDISTFUNCTOR, class OBJMARKER, class OBJPTRCONTAINER,class DISTCONTAINER, class POINTCONTAINER>
00377             unsigned int GetKClosest(OBJPOINTDISTFUNCTOR & _getPointDistance,OBJMARKER & _marker,
00378             const unsigned int _k, const CoordType & _p, const ScalarType & _maxDist,OBJPTRCONTAINER & _objectPtrs,
00379             DISTCONTAINER & _distances, POINTCONTAINER & _points)
00380         {
00381             return (vcg::GridGetKClosest<SpatialHashType,
00382                 OBJPOINTDISTFUNCTOR,OBJMARKER,OBJPTRCONTAINER,DISTCONTAINER,POINTCONTAINER>
00383                 (*this,_getPointDistance,_marker,_k,_p,_maxDist,_objectPtrs,_distances,_points));
00384         }
00385 
00386         template <class OBJPOINTDISTFUNCTOR, class OBJMARKER, class OBJPTRCONTAINER, class DISTCONTAINER, class POINTCONTAINER>
00387         unsigned int GetInSphere(OBJPOINTDISTFUNCTOR & _getPointDistance,
00388         OBJMARKER & _marker,
00389         const CoordType & _p,
00390         const ScalarType & _r,
00391         OBJPTRCONTAINER & _objectPtrs,
00392         DISTCONTAINER & _distances,
00393         POINTCONTAINER & _points)
00394         {
00395             return(vcg::GridGetInSphere<SpatialHashType,
00396                 OBJPOINTDISTFUNCTOR,OBJMARKER,OBJPTRCONTAINER,DISTCONTAINER,POINTCONTAINER>
00397                 (*this,_getPointDistance,_marker,_p,_r,_objectPtrs,_distances,_points));
00398         }
00399 
00400         template <class OBJMARKER, class OBJPTRCONTAINER>
00401             unsigned int GetInBox(OBJMARKER & _marker,
00402             const Box3x _bbox,
00403             OBJPTRCONTAINER & _objectPtrs)
00404         {
00405             return(vcg::GridGetInBox<SpatialHashType,OBJMARKER,OBJPTRCONTAINER>
00406                   (*this,_marker,_bbox,_objectPtrs));
00407         }
00408 
00409         template <class OBJRAYISECTFUNCTOR, class OBJMARKER>
00410             ObjPtr DoRay(OBJRAYISECTFUNCTOR & _rayIntersector, OBJMARKER & _marker, const Ray3<ScalarType> & _ray, const ScalarType & _maxDist, ScalarType & _t)
00411         {
00412             return(vcg::GridDoRay<SpatialHashType,OBJRAYISECTFUNCTOR,OBJMARKER>
00413                   (*this,_rayIntersector,_marker,_ray,_maxDist,_t));
00414         }
00415 
00416 
00417     }; // end class
00418 
00423     template < typename ContainerType,class FLT=double>
00424     class DynamicSpatialHashTable: public SpatialHashTable<ContainerType,FLT>
00425     {
00426     public:
00427         typedef typename SpatialHashTable<ContainerType,FLT>::CoordType CoordType;
00428         typedef typename SpatialHashTable<ContainerType,FLT>::ObjType ObjType;
00429         typedef typename SpatialHashTable<ContainerType,FLT>::ObjPtr ObjPtr;
00430         typedef typename SpatialHashTable<ContainerType,FLT>::Box3x Box3x;
00431         typedef typename SpatialHashTable<ContainerType,FLT>::CellIterator CellIterator;
00432 
00433         void _UpdateHMark(ObjType* s){ s->HMark() = this->tempMark;}
00434 
00435         void getInCellUpdated(vcg::Point3i cell,std::vector<ObjPtr> &elems)
00436         {
00437             CellIterator first,last,l;
00438             Grid(cell,first,last);
00439             for (l=first;l!=last;l++)
00440             {
00441                 if ((l->second)>=(**l).HMark())
00442                     elems.push_back(&(**l));
00443             }
00444         }
00445 
00446     };
00447 
00448 
00449 
00450 
00451 
00452 }// end namespace
00453 
00454 #endif


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