From 66921c752be4d51d1675eed794ee4771f82cfd03 Mon Sep 17 00:00:00 2001 From: nicopietroni Date: Tue, 2 Aug 2005 11:18:36 +0000 Subject: [PATCH] exetended form BasicGrid, changed type of t in class Link (from Iterator to Pointer to the object) --- vcg/space/index/grid_static_ptr.h | 757 +++++++++++++++--------------- 1 file changed, 374 insertions(+), 383 deletions(-) diff --git a/vcg/space/index/grid_static_ptr.h b/vcg/space/index/grid_static_ptr.h index 485c102e..87e62cda 100644 --- a/vcg/space/index/grid_static_ptr.h +++ b/vcg/space/index/grid_static_ptr.h @@ -21,9 +21,12 @@ * * ****************************************************************************/ /**************************************************************************** - History +History $Log: not supported by cvs2svn $ +Revision 1.13 2005/04/14 17:23:08 ponchio +*** empty log message *** + Revision 1.12 2005/03/15 11:43:18 cignoni Removed BestDim function from the grid_static_ptr class and moved to a indipendent file (grid_util.h) for sake of generality. @@ -75,400 +78,388 @@ Initial commit #include #include #include + namespace vcg { - - /** Static Uniform Grid - A spatial search structure for a accessing a container of objects. - It is based on a uniform grid overlayed over a protion of space. - The grid partion the space into cells. Cells contains just pointers - to the object that are stored elsewhere. - The set of objects is meant to be static and pointer stable. - Useful for situation were many space related query are issued over - the same dataset (ray tracing, measuring distances between meshes, - re-detailing ecc.). - Works well for distribution that ar reasonably uniform. - How to use it: - ContainerType must have a 'value_type' typedef inside. - (stl containers already have it) + /** Static Uniform Grid + A spatial search structure for a accessing a container of objects. + It is based on a uniform grid overlayed over a protion of space. + The grid partion the space into cells. Cells contains just pointers + to the object that are stored elsewhere. + The set of objects is meant to be static and pointer stable. - Objects pointed by cells (of kind 'value_type') must have - a 'ScalarType' typedef (float or double usually) - and 2 member functions: - - bool Dist(const Point3f &point, ScalarType &mindist, Point3f &result); - which return true if the distance from point to the object is < mindist - and set mindist to said distance, and result must be set as the closest - point of the object to point) + Useful for situation were many space related query are issued over + the same dataset (ray tracing, measuring distances between meshes, + re-detailing ecc.). + Works well for distribution that ar reasonably uniform. + How to use it: + ContainerType must have a 'value_type' typedef inside. + (stl containers already have it) - void GetBBox(Box3 &b) - which return the bounding box of the object - - */ - -template < typename ContainerType > -class GridStaticPtr -{ - public: + Objects pointed by cells (of kind 'value_type') must have + a 'ScalarType' typedef (float or double usually) + and 2 member functions: - /** Internal class for keeping the first pointer of object. - Definizione Link dentro la griglia. Classe di supporto per GridStaticObj. - */ - class Link - { - public: - /// Costruttore di default - inline Link(){}; - /// Costruttore con inizializzatori - inline Link( typename ContainerType::iterator const nt, const int ni ){ - assert(ni>=0); - t = nt; - i = ni; - }; - - - inline bool operator < ( const Link & l ) const{ return i < l.i; } - inline bool operator <= ( const Link & l ) const{ return i <= l.i; } - inline bool operator > ( const Link & l ) const{ return i > l.i; } - inline bool operator >= ( const Link & l ) const{ return i >= l.i; } - inline bool operator == ( const Link & l ) const{ return i == l.i; } - inline bool operator != ( const Link & l ) const{ return i != l.i; } - - inline typename ContainerType::iterator & Elem() { - return t; - } - inline int & Index() { - return i; - } - - private: - /// Puntatore all'elemento T - typename ContainerType::iterator t; - /// Indirizzo del voxel dentro la griglia - int i; - - - };//end class Link - - typedef typename ContainerType::value_type ObjType; - typedef ObjType* ObjPtr; - typedef typename ObjType::ScalarType ScalarType; - typedef Point3 Point3x; - typedef Box3 Box3x; - typedef Line3 Line3x; - typedef Link* Cell; - - Box3x bbox; - Point3x dim; /// Dimensione spaziale (lunghezza lati) del bbox - Point3i siz; /// Dimensioni griglia in celle - Point3x voxel; /// Dimensioni di una cella - + bool Dist(const Point3f &point, ScalarType &mindist, Point3f &result); + which return true if the distance from point to the object is < mindist + and set mindist to said distance, and result must be set as the closest + point of the object to point) - std::vector links; /// Insieme di tutti i links - std::vector grid; /// Griglia vera e propria - - /// Dato un punto, ritorna la cella che lo contiene - inline Cell* Grid( const Point3d & p ) - { - int x = int( (p[0]-bbox.min[0])/voxel[0] ); - int y = int( (p[1]-bbox.min[1])/voxel[1] ); - int z = int( (p[2]-bbox.min[2])/voxel[2] ); - -#ifndef NDEBUG - if ( x<0 || x>=siz[0] || y<0 || y>=siz[1] || z<0 || z>=siz[2] ) - return NULL; - else -#endif - - return grid.begin() + ( x+siz[0]*(y+siz[1]*z) ); - } - /// Date le coordinate ritorna la cella - inline Cell* Grid( const int x, const int y, const int z ) - { -#ifndef NDEBUG - if ( x<0 || x>=siz[0] || y<0 || y>=siz[1] || z<0 || z>=siz[2] ) - assert(0); - //return NULL; - else -#endif - assert(((unsigned int)x+siz[0]*y+siz[1]*z) & cl) - { -#ifndef NDEBUG - if ( p[0]<0 || p[0]>siz[0] || - p[1]<0 || p[1]>siz[1] || - p[2]<0 || p[2]>siz[2] ) - assert(0); - //return NULL; - else -#endif - assert(((unsigned int) p[0]+siz[0]*p[1]+siz[1]*p[2])0.5) radius=(1.0-radius); radius*=voxel[0]; - - ScalarType tmp=dy-ScalarType(iy); - if (tmp>0.5) tmp=1.0-tmp; - tmp*=voxel[1]; - if (radius>tmp) radius=tmp; - tmp=dz-ScalarType(iz); - if (tmp>0.5) tmp=1.0-tmp; - tmp*=voxel[2]; - if (radius>tmp) radius=tmp; - - Point3x t_res; - //ScalarType min_dist=1e10; - ObjPtr winner=NULL; + void GetBBox(Box3 &b) + which return the bounding box of the object - Link *first, *last; - Link *l; - if ((ix>=0) && (iy>=0) && (iz>=0) && - (ixElem()->IsD() && l->Elem()->Dist(p,min_dist,t_res)) { - winner=&*(l->Elem()); - res=t_res; - - } - }; - }; - - //return winner; - - Point3i done_min=Point3i(ix,iy,iz), done_max=Point3i(ix,iy,iz); + */ - //printf("."); - - while (min_dist>radius) { - //if (dy-ScalarType(iy)) - done_min[0]--; if (done_min[0]<0) done_min[0]=0; - done_min[1]--; if (done_min[1]<0) done_min[1]=0; - done_min[2]--; if (done_min[2]<0) done_min[2]=0; - done_max[0]++; if (done_max[0]>=siz[0]-1) done_max[0]=siz[0]-1; - done_max[1]++; if (done_max[1]>=siz[1]-1) done_max[1]=siz[1]-1; - done_max[2]++; if (done_max[2]>=siz[2]-1) done_max[2]=siz[2]-1; - radius+=voxel_min; - //printf("+"); - for (ix=done_min[0]; ix<=done_max[0]; ix++) - for (iy=done_min[1]; iy<=done_max[1]; iy++) - for (iz=done_min[2]; iz<=done_max[2]; iz++) - { - Grid( ix, iy, iz, first, last ); - for(l=first;l!=last;++l) - { - if (!l->Elem()->IsD() && l->Elem()->Dist(p,min_dist,t_res)) { - winner=&*(l->Elem()); - res=t_res; - }; - }; - } - }; - return winner; - }; - - /// Inserisce una mesh nella griglia. Nota: prima bisogna - /// chiamare SetBBox che setta dim in maniera corretta - void Set( ContainerType & s ) - { - Set(s,s.size()); - } - - - /// Inserisce una mesh nella griglia. Nota: prima bisogna - /// chiamare SetBBox che setta dim in maniera corretta - void Set( ContainerType & s,int _size ) - { - Point3i _siz; - - BestDim( _size, dim, _siz ); - Set(s,_siz); - } - void Set(ContainerType & s, Point3i _siz) - { - siz=_siz; - // Calcola la dimensione della griglia - voxel[0] = dim[0]/siz[0]; - voxel[1] = dim[1]/siz[1]; - voxel[2] = dim[2]/siz[2]; - - // "Alloca" la griglia: +1 per la sentinella - grid.resize( siz[0]*siz[1]*siz[2]+1 ); - - // Ciclo inserimento dei tetraedri: creazione link - links.clear(); - typename ContainerType::iterator pt; - for(pt=s.begin(); pt!=s.end(); ++pt) + template < typename ContainerType,class FLT=float > + class GridStaticPtr:public BasicGrid { - Box3x bb; // Boundig box del tetraedro corrente - (*pt).GetBBox(bb); - bb.Intersect(bbox); - if(! bb.IsNull() ) - { + public: - Box3i ib; // Boundig box in voxels - BoxToIBox( bb,ib ); - int x,y,z; - for(z=ib.min[2];z<=ib.max[2];++z) + typedef typename ContainerType::value_type ObjType; + typedef ObjType* ObjPtr; + typedef typename ObjType::ScalarType ScalarType; + typedef Point3 CoordType; + typedef Box3 Box3x; + typedef Line3 Line3x; + + + /** Internal class for keeping the first pointer of object. + Definizione Link dentro la griglia. Classe di supporto per GridStaticObj. + */ + class Link { - int bz = z*siz[1]; - for(y=ib.min[1];y<=ib.max[1];++y) - { - int by = (y+bz)*siz[0]; - for(x=ib.min[0];x<=ib.max[0];++x) - // Inserire calcolo cella corrente - // if( pt->Intersect( ... ) - links.push_back( Link(pt,by+x) ); - } + public: + /// Costruttore di default + inline Link(){}; + /// Costruttore con inizializzatori + inline Link(ObjPtr nt, const int ni ){ + assert(ni>=0); + t = nt; + i = ni; + }; + + + inline bool operator < ( const Link & l ) const{ return i < l.i; } + inline bool operator <= ( const Link & l ) const{ return i <= l.i; } + inline bool operator > ( const Link & l ) const{ return i > l.i; } + inline bool operator >= ( const Link & l ) const{ return i >= l.i; } + inline bool operator == ( const Link & l ) const{ return i == l.i; } + inline bool operator != ( const Link & l ) const{ return i != l.i; } + + inline typename ObjPtr & Elem() { + return t; + } + inline int & Index() { + return i; + } + + private: + /// Puntatore all'elemento T + ObjPtr t; + /// Indirizzo del voxel dentro la griglia + int i; + + + };//end class Link + + typedef Link* Cell; + typedef typename Cell CellIterator; + + std::vector links; /// Insieme di tutti i links + std::vector grid; /// Griglia vera e propria + + + /// Dato un punto, ritorna la cella che lo contiene + inline Cell* Grid( const Point3d & p ) + { + int x = int( (p[0]-bbox.min[0])/voxel[0] ); + int y = int( (p[1]-bbox.min[1])/voxel[1] ); + int z = int( (p[2]-bbox.min[2])/voxel[2] ); + +#ifndef NDEBUG + if ( x<0 || x>=siz[0] || y<0 || y>=siz[1] || z<0 || z>=siz[2] ) + return NULL; + else +#endif + + return grid.begin() + ( x+siz[0]*(y+siz[1]*z) ); } - } - } - // Push della sentinella - links.push_back( Link((typename ContainerType::iterator)NULL, - (grid.size()-1))); - - // Ordinamento dei links - sort( links.begin(), links.end() ); - - // Creazione puntatori ai links - typename std::vector::iterator pl; - unsigned int pg; - pl = links.begin(); - for(pg=0;pgIndex() ) // Trovato inizio - { - ++pl; // Ricerca prossimo blocco - if(pl==links.end()) - break; - } - } - - } - - - int MemUsed() - { - return sizeof(GridStaticPtr)+ sizeof(Link)*links.size() + - sizeof(Cell) * grid.size(); - } -}; //end class GridStaticObj - + /// Date le coordinate ritorna la cella + inline Cell* Grid( const int x, const int y, const int z ) + { +#ifndef NDEBUG + if ( x<0 || x>=siz[0] || y<0 || y>=siz[1] || z<0 || z>=siz[2] ) + assert(0); + //return NULL; + else +#endif + assert(((unsigned int)x+siz[0]*y+siz[1]*z) & cl) + { +#ifndef NDEBUG + if ( p[0]<0 || p[0]>siz[0] || + p[1]<0 || p[1]>siz[1] || + p[2]<0 || p[2]>siz[2] ) + assert(0); + //return NULL; + else +#endif + assert(((unsigned int) p[0]+siz[0]*p[1]+siz[1]*p[2])0.5) radius=(1.0-radius); radius*=voxel[0]; + + ScalarType tmp=dy-ScalarType(iy); + if (tmp>0.5) tmp=1.0-tmp; + tmp*=voxel[1]; + if (radius>tmp) radius=tmp; + tmp=dz-ScalarType(iz); + if (tmp>0.5) tmp=1.0-tmp; + tmp*=voxel[2]; + if (radius>tmp) radius=tmp; + + CoordType t_res; + //ScalarType min_dist=1e10; + ObjPtr winner=NULL; + + Link *first, *last; + Link *l; + if ((ix>=0) && (iy>=0) && (iz>=0) && + (ixElem()->IsD() && l->Elem()->Dist(p,min_dist,t_res)) { + winner=&*(l->Elem()); + res=t_res; + + } + }; + }; + + //return winner; + + Point3i done_min=Point3i(ix,iy,iz), done_max=Point3i(ix,iy,iz); + + //printf("."); + + while (min_dist>radius) { + //if (dy-ScalarType(iy)) + done_min[0]--; if (done_min[0]<0) done_min[0]=0; + done_min[1]--; if (done_min[1]<0) done_min[1]=0; + done_min[2]--; if (done_min[2]<0) done_min[2]=0; + done_max[0]++; if (done_max[0]>=siz[0]-1) done_max[0]=siz[0]-1; + done_max[1]++; if (done_max[1]>=siz[1]-1) done_max[1]=siz[1]-1; + done_max[2]++; if (done_max[2]>=siz[2]-1) done_max[2]=siz[2]-1; + radius+=voxel_min; + //printf("+"); + for (ix=done_min[0]; ix<=done_max[0]; ix++) + for (iy=done_min[1]; iy<=done_max[1]; iy++) + for (iz=done_min[2]; iz<=done_max[2]; iz++) + { + Grid( ix, iy, iz, first, last ); + for(l=first;l!=last;++l) + { + if (!l->Elem()->IsD() && l->Elem()->Dist(p,min_dist,t_res)) { + winner=&*(l->Elem()); + res=t_res; + }; + }; + } + }; + return winner; + }; + + /// Inserisce una mesh nella griglia. Nota: prima bisogna + /// chiamare SetBBox che setta dim in maniera corretta + void Set( ContainerType & s ) + { + Set(s,s.size()); + } + + + /// Inserisce una mesh nella griglia. Nota: prima bisogna + /// chiamare SetBBox che setta dim in maniera corretta + void Set( ContainerType & s,int _size ) + { + Point3i _siz; + + BestDim( _size, dim, _siz ); + Set(s,_siz); + } + void Set(ContainerType & s, Point3i _siz) + { + siz=_siz; + // Calcola la dimensione della griglia + voxel[0] = dim[0]/siz[0]; + voxel[1] = dim[1]/siz[1]; + voxel[2] = dim[2]/siz[2]; + + // "Alloca" la griglia: +1 per la sentinella + grid.resize( siz[0]*siz[1]*siz[2]+1 ); + + // Ciclo inserimento dei tetraedri: creazione link + links.clear(); + typename ContainerType::iterator pt; + for(pt=s.begin(); pt!=s.end(); ++pt) + { + Box3x bb; // Boundig box del tetraedro corrente + (*pt).GetBBox(bb); + bb.Intersect(bbox); + if(! bb.IsNull() ) + { + + Box3i ib; // Boundig box in voxels + BoxToIBox( bb,ib ); + int x,y,z; + for(z=ib.min[2];z<=ib.max[2];++z) + { + int bz = z*siz[1]; + for(y=ib.min[1];y<=ib.max[1];++y) + { + int by = (y+bz)*siz[0]; + for(x=ib.min[0];x<=ib.max[0];++x) + // Inserire calcolo cella corrente + // if( pt->Intersect( ... ) + links.push_back( Link(&(*pt),by+x) ); + } + } + } + } + // Push della sentinella + /*links.push_back( Link((typename ContainerType::iterator)NULL, + (grid.size()-1)));*/ + + links.push_back( Link(NULL, + (grid.size()-1))); + + // Ordinamento dei links + sort( links.begin(), links.end() ); + + // Creazione puntatori ai links + typename std::vector::iterator pl; + unsigned int pg; + pl = links.begin(); + for(pg=0;pgIndex() ) // Trovato inizio + { + ++pl; // Ricerca prossimo blocco + if(pl==links.end()) + break; + } + } + + } + + + int MemUsed() + { + return sizeof(GridStaticPtr)+ sizeof(Link)*links.size() + + sizeof(Cell) * grid.size(); + } + }; //end class GridStaticObj + }; // end namespace #endif