grid_static_ptr.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_UGRID
00025 #define __VCGLIB_UGRID
00026 
00027 #include <vector>
00028 #include <algorithm>
00029 #include <stdio.h>
00030 
00031 #include <vcg/space/box3.h>
00032 #include <vcg/space/line3.h>
00033 #include <vcg/space/index/grid_util.h>
00034 #include <vcg/space/index/grid_closest.h>
00035 #include <vcg/simplex/face/distance.h>
00036 
00037 namespace vcg {
00038 
00071         template < class OBJTYPE, class FLT=float >
00072         class GridStaticPtr: public BasicGrid<FLT>, SpatialIndex<OBJTYPE,FLT>
00073         {
00074         public:
00075                 typedef OBJTYPE ObjType;
00076                 typedef ObjType* ObjPtr;
00077                 typedef typename ObjType::ScalarType ScalarType;
00078                 typedef Point3<ScalarType> CoordType;
00079                 typedef Box3<ScalarType> Box3x;
00080                 typedef Line3<ScalarType> Line3x;
00081                 typedef GridStaticPtr<OBJTYPE,FLT> GridPtrType;
00082     typedef BasicGrid<FLT> BT;
00083 
00087                 class Link
00088                 {
00089                 public:
00091                         inline Link(){};
00093                         inline Link(ObjPtr nt, const int ni ){
00094                                 assert(ni>=0);
00095                                 t = nt;
00096                                 i = ni;
00097                         };
00098 
00099 
00100                         inline bool operator <  ( const Link & l ) const{ return i <   l.i; } 
00101                         inline bool operator <= ( const Link & l ) const{ return i <=  l.i; }
00102                         inline bool operator >  ( const Link & l ) const{ return i >   l.i; }
00103                         inline bool operator >= ( const Link & l ) const{ return i >=  l.i; }
00104                         inline bool operator == ( const Link & l ) const{ return i ==  l.i; }
00105                         inline bool operator != ( const Link & l ) const{ return i !=  l.i; }
00106 
00107                         inline ObjPtr & Elem() {
00108                                 return t;
00109                         }
00110 
00111                         ObjType &operator *(){return *(t);}
00112 
00113                         inline int & Index() {
00114                                 return i;
00115                         }
00116 
00117                 private:
00119                         ObjPtr t;
00121                         int i;
00122 
00123 
00124                 };//end class Link
00125 
00126                 typedef Link* Cell;
00127                 typedef Cell CellIterator;
00128 
00129                 std::vector<Link>   links;   
00130 
00131                 std::vector<Cell> grid;   
00132 
00133 
00134 
00135     bool Empty() const {return links.empty();}
00136 
00139                 inline void Grid( Point3i p, const int axis,
00140                         std::vector<Cell*> & cl) 
00141                 {
00142 #ifndef NDEBUG
00143       if ( p[0]<0 || p[0] > BT::siz[0] || 
00144                                 p[1]<0 || p[1]> BT::siz[1] || 
00145                                 p[2]<0 || p[2]> BT::siz[2] )
00146                                 assert(0);
00147                         //return NULL;
00148                         else
00149 #endif
00150         assert(((unsigned int) p[0]+BT::siz[0]*p[1]+BT::siz[1]*p[2])<grid.size());
00151 
00152                         int axis0 = (axis+1)%3;
00153                         int axis1 = (axis+2)%3;
00154                         int i,j,x,y;
00155                         x = p[axis0];
00156                         y = p[axis1];
00157                         for(i = std::max(x-1,0); i <= std::min( x,BT::siz[axis0]-1);++i)        
00158                                 for(j = std::max(y-1,0); j <= std::min( y,this->siz[axis1]-1);++j){
00159                                         p[axis0]=i;
00160                                         p[axis1]=j;
00161                                         cl.push_back(Grid(p[0]+BT::siz[0]*(p[1]+BT::siz[1]*p[2])));
00162                                 }
00163                 }
00164 
00165 
00167                 // Official access functions
00170                 Cell* Grid(const  int i) {
00171                         return &grid[i];
00172                 }
00173 
00174                 void Grid( const Cell* g, Cell & first, Cell & last )
00175                 {
00176                         first = *g;
00177                         last  = *(g+1);
00178                 }
00179 
00181                 inline Cell* Grid( const int x, const int y, const int z )
00182                 {
00183                         assert(!( x<0 || x>=BT::siz[0] || y<0 || y>=BT::siz[1] || z<0 || z>=BT::siz[2] ));
00184                         assert(grid.size()>0);
00185                         return &*grid.begin() + ( x+BT::siz[0]*(y+BT::siz[1]*z) );
00186                 }
00187 
00188                 inline Cell* Grid( const Point3i &pi)
00189                 {
00190                         return Grid(pi[0],pi[1],pi[2]);
00191                 }
00192 
00193                 void Grid( const int x, const int y, const int z, Cell & first, Cell & last )
00194                 {
00195                         Cell* g = Grid(x,y,z);
00196                         first = *g;
00197                         last  = *(g+1);
00198                 }
00199 
00200                 void Grid( const Point3<ScalarType> & p, Cell & first, Cell & last )
00201                 {
00202                         Cell* g = Grid(GridP(p));
00203 
00204                         first = *g;
00205                         last  = *(g+1);
00206                 }
00207 
00208 
00211                 template <class Box3Type>
00212                         void SetBBox( const Box3Type & b )
00213                 {
00214       this->bbox.Import( b );
00215                         ScalarType t = this->bbox.Diag()/100.0;
00216                         if(t == 0) t = ScalarType(1e-20);  // <--- Some doubts on this (Cigno 5/1/04)
00217                         this->bbox.Offset(t);
00218                         this->dim  = this->bbox.max - this->bbox.min;
00219                 }
00220 
00221 
00222 
00223 //              void ShowStats(FILE *fp)
00224 //              {
00225 //                      // Conto le entry
00226 //                      //int nentry = 0;
00227 //                      //Hist H;
00228 //                      //H.SetRange(0,1000,1000);
00229 //                      //int pg;
00230 //                      //for(pg=0;pg<grid.size()-1;++pg)
00231 //                      //      if( grid[pg]!=grid[pg+1] )
00232 //                      //      {
00233 //                      //              ++nentry;
00234 //                      //              H.Add(grid[pg+1]-grid[pg]);
00235 //                      //      }
00236 
00237 //                      //      fprintf(fp,"Uniform Grid: %d x %d x %d (%d voxels), %.1f%% full, %d links \nNon empty Cell Occupancy Distribution Avg: %f (%4.0f %4.0f %4.0f) \n",
00238 //                      //      siz[0],siz[1],siz[2],grid.size()-1,
00239 //                      //      double(nentry)*100.0/(grid.size()-1),links.size(),H.Avg(),H.Percentile(.25),H.Percentile(.5),H.Percentile(.75)
00240 //                      //
00241 //                      //);
00242 //              }
00243 
00244                 template <class OBJITER>
00245                 inline void Set(const OBJITER & _oBegin, const OBJITER & _oEnd, int _size=0)
00246                 {
00247                         Box3<FLT> _bbox;
00248                         Box3<FLT> b;
00249                         for(OBJITER i = _oBegin; i!= _oEnd; ++i)
00250                         {
00251                                 (*i).GetBBox(b);
00252                                 _bbox.Add(b);                           
00253                         }
00254                         if(_size ==0) 
00255                                         _size=(int)std::distance<OBJITER>(_oBegin,_oEnd);
00256 
00258                         ScalarType infl=_bbox.Diag()/_size;
00259                         _bbox.min-=vcg::Point3<FLT>(infl,infl,infl);
00260                         _bbox.max+=vcg::Point3<FLT>(infl,infl,infl);
00261                         
00262                         Set(_oBegin,_oEnd,_bbox,_size);
00263                 }                       
00264     
00265                         
00266                         
00267                         // This function automatically compute a reasonable size for the uniform grid providing the side (radius) of the cell
00268                         //
00269                         // Note that the bbox must be already 'inflated' so to be sure that no object will fall on the border of the grid.
00270                         
00271                         template <class OBJITER>
00272                                 inline void SetWithRadius(const OBJITER & _oBegin, const OBJITER & _oEnd, FLT _cellRadius)
00273                         {
00274                                   Box3<FLT> _bbox;
00275                                   Box3<FLT> b;
00276                                   for(OBJITER i = _oBegin; i!= _oEnd; ++i)
00277                                   {
00278                                           (*i).GetBBox(b);
00279                                           _bbox.Add(b);
00280                                   }
00281 
00282                                   _bbox.min-=vcg::Point3<FLT>(_cellRadius,_cellRadius,_cellRadius);
00283                                   _bbox.max+=vcg::Point3<FLT>(_cellRadius,_cellRadius,_cellRadius);
00284 
00285                                   Point3i _siz;
00286                                   Point3<FLT> _dim = _bbox.max - _bbox.min;
00287                                   _dim/=_cellRadius;
00288                                   assert(_dim[0]>0 && _dim[1]>0 && _dim[2]>0 );
00289                                   _siz[0] = (int)ceil(_dim[0]);
00290                                   _siz[1] = (int)ceil(_dim[1]);
00291                                   _siz[2] = (int)ceil(_dim[2]);
00292 
00293                                   Set(_oBegin,_oEnd, _bbox,_siz);
00294                         }                       
00295                         
00296                         
00297                 // This function automatically compute a reasonable size for the uniform grid such that the number of cells is
00298                 // the same of the nubmer of elements to be inserted in the grid.
00299                 //
00300                 // Note that the bbox must be already 'inflated' so to be sure that no object will fall on the border of the grid.
00301                 
00302                         template <class OBJITER>
00303                         inline void Set(const OBJITER & _oBegin, const OBJITER & _oEnd, const Box3x &_bbox, int _size=0)
00304                         {
00305                           if(_size==0)
00306                                 _size=(int)std::distance<OBJITER>(_oBegin,_oEnd);
00307                           Point3<FLT> _dim = _bbox.max - _bbox.min;
00308                           Point3i _siz;
00309                           BestDim( _size, _dim, _siz );
00310 
00311                           Set(_oBegin,_oEnd,_bbox,_siz);
00312                         }
00313 
00314 
00315                 // This is the REAL LOW LEVEL function
00316                         
00317                 template <class OBJITER>
00318     inline void Set(const OBJITER & _oBegin, const OBJITER & _oEnd, const Box3x &_bbox, Point3i _siz)
00319                 {
00320                         OBJITER i;
00321                         
00322                         this->bbox=_bbox;
00323                         this->siz=_siz;
00324                         
00325                         // find voxel size starting from the provided bbox and grid size. 
00326                         
00327                         this->dim  = this->bbox.max - this->bbox.min;
00328                         this->voxel[0] = this->dim[0]/this->siz[0];
00329                         this->voxel[1] = this->dim[1]/this->siz[1];
00330                         this->voxel[2] = this->dim[2]/this->siz[2];                     
00331                         
00332         // Allocate the grid (add one more for the final sentinel)
00333                                 grid.resize( this->siz[0]*this->siz[1]*this->siz[2]+1 );
00334 
00335         // Insert all the objects into the grid
00336                                 links.clear();
00337                                 for(i=_oBegin; i!=_oEnd; ++i)
00338                                 {
00339                                         Box3x bb;                       // Boundig box del tetraedro corrente
00340                                         (*i).GetBBox(bb);
00341                                         bb.Intersect(this->bbox);
00342                                         if(! bb.IsNull() )
00343                                         {
00344 
00345                                                 Box3i ib;               // Boundig box in voxels
00346                                                 this->BoxToIBox( bb,ib );
00347                                                 int x,y,z;
00348                                                 for(z=ib.min[2];z<=ib.max[2];++z)
00349                                                 {
00350                                                         int bz = z*this->siz[1];
00351                                                         for(y=ib.min[1];y<=ib.max[1];++y)
00352                                                         {
00353                                                                 int by = (y+bz)*this->siz[0];
00354                                                                 for(x=ib.min[0];x<=ib.max[0];++x)
00355                                                                         // Inserire calcolo cella corrente
00356                                                                         // if( pt->Intersect( ... )
00357                                                                         links.push_back( Link(&(*i),by+x) );
00358                                                         }
00359                                                 }
00360                                         }
00361                                 }
00362                                 // Push della sentinella
00363                                 /*links.push_back( Link((typename ContainerType::iterator)NULL,
00364                                 (grid.size()-1)));*/
00365 
00366                                 links.push_back( Link( NULL,    int(grid.size())-1) );
00367 
00368                                 // Ordinamento dei links
00369                                 sort( links.begin(), links.end() );
00370 
00371                                 // Creazione puntatori ai links
00372                                 typename std::vector<Link>::iterator pl;
00373                                 unsigned int pg;
00374                                 pl = links.begin();
00375                                 for(pg=0;pg<grid.size();++pg)
00376                                 {
00377                                         assert(pl!=links.end());
00378                                         grid[pg] = &*pl;
00379                                         while( (int)pg == pl->Index() ) // Trovato inizio
00380                                         {
00381                                                 ++pl;           // Ricerca prossimo blocco
00382                                                 if(pl==links.end())
00383                                                         break;
00384                                         }
00385                                 }
00386 
00387                 }               
00388 
00389 
00390                 int MemUsed()
00391                 {
00392                         return sizeof(GridStaticPtr)+ sizeof(Link)*links.size() + 
00393                                 sizeof(Cell) * grid.size();
00394                 }
00395 
00396                 template <class OBJPOINTDISTFUNCTOR, class OBJMARKER>
00397                         ObjPtr  GetClosest(OBJPOINTDISTFUNCTOR & _getPointDistance, OBJMARKER & _marker, 
00398                                 const typename OBJPOINTDISTFUNCTOR::QueryType & _p, const ScalarType & _maxDist,ScalarType & _minDist, CoordType & _closestPt)
00399                 {
00400                         return (vcg::GridClosest<GridPtrType,OBJPOINTDISTFUNCTOR,OBJMARKER>(*this,_getPointDistance,_marker, _p,_maxDist,_minDist,_closestPt));
00401                 }
00402 
00403 
00404                 template <class OBJPOINTDISTFUNCTOR, class OBJMARKER, class OBJPTRCONTAINER,class DISTCONTAINER, class POINTCONTAINER>
00405                         unsigned int GetKClosest(OBJPOINTDISTFUNCTOR & _getPointDistance,OBJMARKER & _marker, 
00406                         const unsigned int _k, const CoordType & _p, const ScalarType & _maxDist,OBJPTRCONTAINER & _objectPtrs,
00407                         DISTCONTAINER & _distances, POINTCONTAINER & _points)
00408                 {
00409                         return (vcg::GridGetKClosest<GridPtrType,
00410                                 OBJPOINTDISTFUNCTOR,OBJMARKER,OBJPTRCONTAINER,DISTCONTAINER,POINTCONTAINER>(*this,_getPointDistance,_marker,_k,_p,_maxDist,_objectPtrs,_distances,_points));
00411                 }
00412 
00413                 template <class OBJPOINTDISTFUNCTOR, class OBJMARKER, class OBJPTRCONTAINER, class DISTCONTAINER, class POINTCONTAINER>
00414                         unsigned int GetInSphere(OBJPOINTDISTFUNCTOR & _getPointDistance, 
00415                         OBJMARKER & _marker,
00416                         const CoordType & _p,
00417                         const ScalarType & _r,
00418                         OBJPTRCONTAINER & _objectPtrs,
00419                         DISTCONTAINER & _distances, 
00420                         POINTCONTAINER & _points)
00421                 {
00422                         return(vcg::GridGetInSphere<GridPtrType,
00423                                 OBJPOINTDISTFUNCTOR,OBJMARKER,OBJPTRCONTAINER,DISTCONTAINER,POINTCONTAINER>
00424                                 (*this,_getPointDistance,_marker,_p,_r,_objectPtrs,_distances,_points));
00425                 }
00426 
00427                 template <class OBJMARKER, class OBJPTRCONTAINER>
00428                         unsigned int GetInBox(OBJMARKER & _marker, 
00429                         const vcg::Box3<ScalarType> _bbox,
00430                         OBJPTRCONTAINER & _objectPtrs) 
00431                 {
00432                         return(vcg::GridGetInBox<GridPtrType,OBJMARKER,OBJPTRCONTAINER>
00433                                 (*this,_marker,_bbox,_objectPtrs));
00434                 }
00435 
00436                 template <class OBJRAYISECTFUNCTOR, class OBJMARKER>
00437                         ObjPtr DoRay(OBJRAYISECTFUNCTOR & _rayIntersector, OBJMARKER & _marker, const Ray3<ScalarType> & _ray, const ScalarType & _maxDist, ScalarType & _t) 
00438                 {
00439                         return(vcg::GridDoRay<GridPtrType,OBJRAYISECTFUNCTOR,OBJMARKER>(*this,_rayIntersector,_marker,_ray,_maxDist,_t));
00440                 }
00441                 
00442     /* If the grid has a cubic voxel of side <radius> this function
00443      process all couple of elementes in neighbouring cells.
00444                  GATHERFUNCTOR needs to expose this method:
00445        bool operator()(OBJTYPE *v1, OBJTYPE *v2);
00446        which is then called ONCE per unordered pair v1,v2.
00447      example:
00448    
00449      struct GFunctor {           
00450        double radius2, iradius2;
00451        GFunctor(double radius) { radius2 = radius*radius; iradius2 = 1/radius2; }
00452     
00453        bool operator()(CVertex *v1, CVertex *v2) {
00454          Point3d &p = v1->P();    
00455          Point3d &q = v2->P();
00456          double dist2 = (p-q).SquaredNorm();
00457          if(dist2 < radius2) {
00458            double w = exp(dist2*iradius2);
00459            //do something
00460          }              
00461        }
00462     }; */
00463                   
00464                 template <class GATHERFUNCTOR> 
00465     void Gather(GATHERFUNCTOR gfunctor) {
00466       static int corner[8*3] = { 0, 0, 0,  1, 0, 0,  0, 1, 0,  0, 0, 1,
00467                                  0, 1, 1,  1, 0, 1,  1, 1, 0,  1, 1, 1 };
00468 
00469       static int diagonals[14*2] = { 0, 0, 
00470                                      0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7,
00471                                      2, 3, 1, 3, 1, 2,                       
00472                                      1, 4, 2, 5, 3, 6 };
00473   
00474       Cell ostart, oend, dstart, dend;
00475       for(int z = 0; z < this->siz[2]; z++) {
00476         for(int y = 0; y < this->siz[1]; y++) {
00477           for(int x = 0; x < this->siz[0]; x++) {            
00478 
00479             Grid(x, y, z, ostart, oend);
00480 
00481             for(Cell c = ostart; c != oend; c++) 
00482               for(Cell s = c+1; s != oend; s++) 
00483                 gfunctor(c->Elem(), s->Elem());
00484                     
00485             for(int d = 2; d < 28; d += 2) { //skipping self
00486               int *cs = corner + 3*diagonals[d];
00487               int *ce = corner + 3*diagonals[d+1];
00488               if((x + cs[0] < this->siz[0]) && (y + cs[1] < this->siz[1]) && (z + cs[2] < this->siz[2]) &&
00489                  (x + ce[0] < this->siz[0]) && (y + ce[1] < this->siz[1]) && (z + ce[2] < this->siz[2])) {
00490 
00491                  Grid(x+cs[0], y+cs[1], z+cs[2], ostart, oend);
00492                  Grid(x+ce[0], y+ce[1], z+ce[2], dstart, dend);
00493 
00494                  for(Cell c = ostart; c != oend; c++) 
00495                    for(Cell s = dstart; s != dend; s++) 
00496                      gfunctor(c->Elem(), s->Elem());                               
00497               }
00498             }
00499           }
00500         }
00501       }
00502     }
00503 
00504 
00505         }; //end class GridStaticPtr
00506 
00507 } // end namespace
00508 
00509 #endif


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