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_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 };
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
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
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);
00217 this->bbox.Offset(t);
00218 this->dim = this->bbox.max - this->bbox.min;
00219 }
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
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
00268
00269
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
00298
00299
00300
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
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
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
00333 grid.resize( this->siz[0]*this->siz[1]*this->siz[2]+1 );
00334
00335
00336 links.clear();
00337 for(i=_oBegin; i!=_oEnd; ++i)
00338 {
00339 Box3x bb;
00340 (*i).GetBBox(bb);
00341 bb.Intersect(this->bbox);
00342 if(! bb.IsNull() )
00343 {
00344
00345 Box3i ib;
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
00356
00357 links.push_back( Link(&(*i),by+x) );
00358 }
00359 }
00360 }
00361 }
00362
00363
00364
00365
00366 links.push_back( Link( NULL, int(grid.size())-1) );
00367
00368
00369 sort( links.begin(), links.end() );
00370
00371
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() )
00380 {
00381 ++pl;
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
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
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) {
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 };
00506
00507 }
00508
00509 #endif