00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef ESBTL_GRID_OF_CUBES_H
00036 #define ESBTL_GRID_OF_CUBES_H
00037
00038
00039 #include <boost/tuple/tuple.hpp>
00040 #include <boost/tuple/tuple_comparison.hpp>
00041 #include <list>
00042 #include <map>
00043
00044
00045 namespace ESBTL{
00046
00047 using boost::tuple;
00048 using boost::make_tuple;
00049
00054 template<class Point_,class Iterator_>
00055 struct Traits_for_grid{
00056 typedef double NT;
00057 typedef Iterator_ Iterator;
00058 typedef Point_ Point;
00059
00069 static void init_grid(const Iterator& begin,const Iterator& end,int& xlim,int& ylim,int& zlim,double& rmax,Point& lower_corner){
00070 Point min,max;
00071 boost::tie(min,max)=ESBTL::bounding_box<Point>(begin,end);
00072
00073
00074 rmax = 3.;
00075 xlim=static_cast<int>( ceil( ( max.x()-min.x() + 2*rmax )/rmax) );
00076 ylim=static_cast<int>( ceil( ( max.y()-min.y() + 2*rmax )/rmax) );
00077 zlim=static_cast<int>( ceil( ( max.z()-min.z() + 2*rmax )/rmax) );
00078 lower_corner=min;
00079 };
00080
00092 template<class Any_iterator>
00093 static boost::tuple<int,int,int>
00094 locate_cube(Any_iterator it,const int& xlim,const int& ylim,const int& zlim,const double& cubel,const Point& lower_corner){
00095 int x=static_cast<int>( floor( ( it->x()-lower_corner.x() )/cubel ) );
00096 int y=static_cast<int>( floor( ( it->y()-lower_corner.y() )/cubel ) );
00097 int z=static_cast<int>( floor( ( it->z()-lower_corner.z() )/cubel ) );
00098
00099
00100
00101
00102
00103 if (x==xlim) x=xlim-1;
00104 if (y==ylim) y=ylim-1;
00105 if (z==zlim) z=zlim-1;
00106 if (x==-1) x=0;
00107 if (y==-1) y=0;
00108 if (z==-1) z=0;
00109
00110 assert(!(x<0) && x < xlim);
00111 assert(!(y<0) && y < ylim);
00112 assert(!(z<0) && z < zlim);
00113 return boost::make_tuple(x,y,z);
00114 };
00115
00126 template<class Any_iterator>
00127 static bool
00128 is_outside_grid(Any_iterator it,const int& xlim,const int& ylim,const int& zlim,const double& cubel,const Point& lower_corner){
00129 int x=static_cast<int>( floor( ( it->x()-lower_corner.x() )/cubel ) );
00130 int y=static_cast<int>( floor( ( it->y()-lower_corner.y() )/cubel ) );
00131 int z=static_cast<int>( floor( ( it->z()-lower_corner.z() )/cubel ) );
00132 if (x<-1 || x > xlim) return true;
00133 if (y<-1 || y > ylim) return true;
00134 if (z<-1 || z > zlim) return true;
00135 return false;
00136 };
00137 };
00138
00145 template<class Traits>
00146 struct Grid_of_cubes
00147 {
00148 typedef tuple<int,int,int> Cube_coordinates;
00149
00150 typedef typename Traits::Iterator Object_iterator;
00151
00152 struct Cube_unit{
00153 typedef typename std::list<Object_iterator>::iterator In_cube_iterator;
00154 std::list<Object_iterator> objects;
00155 Cube_unit(Object_iterator V){ objects.push_front(V); }
00156 void insert(Object_iterator V){ objects.push_front(V); }
00157 unsigned size() const { return objects.size(); }
00158 In_cube_iterator begin(){ return objects.begin(); }
00159 In_cube_iterator end(){ return objects.end(); }
00160 };
00161
00162
00163 typedef typename Grid_of_cubes<Traits>::Cube_unit::In_cube_iterator In_cube_iterator;
00164
00165 typedef std::map<Cube_coordinates,Cube_unit*> Cube_container;
00166
00167
00168 Cube_container cube_container;
00169 int xlim,ylim,zlim;
00170 typename Traits::NT cube_edge_length;
00171 typename Traits::Point lower_corner;
00172
00173
00174
00175 void init(const Object_iterator& it_beg,const Object_iterator& it_end){
00176 Traits::init_grid(it_beg,it_end,xlim,ylim,zlim,cube_edge_length,lower_corner);
00177 }
00178
00179 void fill(Object_iterator it_beg,Object_iterator it_end){
00180 for(Object_iterator it=it_beg;it!=it_end;++it)
00181 insert_in_cube(it);
00182 }
00183
00184 Grid_of_cubes(){}
00185
00186 Grid_of_cubes(const Object_iterator& it_beg,const Object_iterator& it_end){
00187 init(it_beg,it_end);
00188 fill(it_beg,it_end);
00189 }
00190
00191 ~Grid_of_cubes(){
00192 for(typename Cube_container::iterator it=cube_container.begin();it!=cube_container.end();++it)
00193 delete (*it).second;
00194 }
00195
00196
00197 unsigned nb_element() const {
00198 unsigned i=0;
00199 for(typename Cube_container::const_iterator it=cube_container.begin();it!=cube_container.end();++it)
00200 i+=it->second->size();
00201 return i;
00202 }
00203
00204 Cube_unit*
00205 get_cube(const Cube_coordinates& t) {
00206 typename Cube_container::iterator it=cube_container.find(t);
00207 return (it==cube_container.end())?(NULL):(it->second);
00208 }
00209
00210 template <class Any_iterator>
00211 Cube_coordinates
00212 locate_cube(Any_iterator v) const {
00213 return Traits::locate_cube(v,xlim,ylim,zlim,cube_edge_length,lower_corner);
00214 }
00215
00216 template <class Any_iterator>
00217 Cube_unit*
00218 get_cube(Any_iterator v) {
00219 return get_cube( locate_cube(v) );
00220 }
00221
00222 void insert_in_cube(Object_iterator V){
00223 Cube_coordinates T=Traits::locate_cube(V,xlim,ylim,zlim,cube_edge_length,lower_corner);
00224 typename Cube_container::iterator it=cube_container.find(T);
00225 if (it==cube_container.end())
00226 cube_container[T]=new Cube_unit(V);
00227 else
00228 (*it).second->insert(V);
00229 };
00230
00231 template <class Any_iterator>
00232 bool is_outside_grid(Any_iterator v) const {
00233 return Traits::is_outside_grid(v,xlim,ylim,zlim,cube_edge_length,lower_corner);
00234 }
00235
00236 bool valid_tuple(const Cube_coordinates& T) const {
00237 return cube_container.find(T)!=cube_container.end();
00238 }
00239
00240 class object_iterator;
00241
00242 class iterator{
00243 friend class Grid_of_cubes<Traits>::object_iterator;
00244 friend void Grid_of_cubes<Traits>::erase(const object_iterator& it);
00245 protected:
00246 Cube_coordinates current;
00247 Grid_of_cubes* grid_ptr;
00248 Cube_coordinates
00249 get_next(){
00250 assert(current!=make_tuple(-1,-1,-1));
00251 Cube_coordinates ret=current;
00252 if (current.get<0>() < grid_ptr->xlim-1)
00253 ret.get<0>()++;
00254 else{
00255 if (current.get<1>() < grid_ptr->ylim-1){
00256 ret.get<1>()++;
00257 ret.get<0>()=0;
00258 }
00259 else{
00260 if (current.get<2>() < grid_ptr->zlim-1){
00261 ret.get<2>()++;
00262 ret.get<0>()=0;
00263 ret.get<1>()=0;
00264 }
00265 else{
00266 return Cube_coordinates(-1,-1,-1);
00267 }
00268 }
00269 }
00270 if (grid_ptr->valid_tuple(ret)) return ret;
00271 current=ret;
00272 return get_next();
00273 }
00274 public:
00275 iterator(){};
00276 iterator(const Cube_coordinates& C):current(C),grid_ptr(NULL){};
00277 iterator(Grid_of_cubes* Grd):grid_ptr(Grd){current=make_tuple(-1,-1,-1);};
00278 iterator(Grid_of_cubes* Grd,const Cube_coordinates& C):current(C),grid_ptr(Grd){};
00279 iterator& operator++(){
00280 current=get_next();
00281 assert(grid_ptr->valid_tuple(current) || current==make_tuple(-1,-1,-1));
00282 return *this;
00283 }
00284 Cube_unit& operator*(){
00285 typename Cube_container::iterator it=grid_ptr->cube_container.find(current);
00286 assert(current!=make_tuple(-1,-1,-1));
00287 assert(it!=grid_ptr->cube_container.end());
00288 return *(*it).second;
00289 }
00290 Cube_unit* operator->(){
00291 typename Cube_container::iterator it=grid_ptr->cube_container.find(current);
00292 assert(it!=grid_ptr->cube_container.end());
00293 return (*it).second;
00294 }
00295 bool operator==(const iterator& it){
00296 return this->current==it.current;
00297 }
00298 bool operator!=(const iterator& it){
00299 return this->current!=it.current;
00300 }
00301 };
00302
00303 class neighbor_iterator : public iterator
00304 {
00305 using iterator::current;
00306 using iterator::grid_ptr;
00307 private:
00308 Cube_coordinates center;
00309
00310 Cube_coordinates get_next(){
00311 Cube_coordinates ret=current;
00312 assert(current!=make_tuple(-1,-1,-1));
00313 if ( (current.template get<0>() < center.get<0>() + 1) && (current.template get<0>() < grid_ptr->xlim - 1) )
00314 ret.get<0>()++;
00315 else{
00316 if ( (current.template get<1>() < center.get<1>() + 1 ) && (current.template get<1>() < grid_ptr->ylim-1) ){
00317 ret.get<1>()++;
00318 ret.get<0>()=((center.get<0>() == 0)?(center.get<0>()):(center.get<0>()-1));
00319 }
00320 else{
00321 if ( (current.template get<2>() < center.get<2>()+1) && (current.template get<2>() < grid_ptr->zlim-1) ){
00322 ret.get<2>()++;
00323 ret.get<0>()=((center.get<0>() == 0)?(center.get<0>()):(center.get<0>()-1));
00324 ret.get<1>()=((center.get<1>() == 0)?(center.get<1>()):(center.get<1>()-1));
00325 }
00326 else{
00327 return make_tuple(-1,-1,-1);
00328 }
00329 }
00330 }
00331 if (ret==center){
00332 current=ret;
00333 return get_next();
00334 }
00335 if (grid_ptr->valid_tuple(ret)) return ret;
00336 current=ret;
00337 return get_next();
00338 }
00339
00340 public:
00341 neighbor_iterator(){}
00342 neighbor_iterator(const Cube_coordinates& C):iterator(C){}
00343 neighbor_iterator(const Cube_coordinates& C,Grid_of_cubes* Grd):iterator(Grd),center(C){
00344 current=grid_ptr->get_first_neighbor(center);
00345 if (!grid_ptr->valid_tuple(current))
00346 current=this->get_next();
00347 }
00348
00349 Cube_coordinates& get_current(){
00350 return current;
00351 }
00352
00353 neighbor_iterator& operator++(){
00354 current=this->get_next();
00355 return *this;
00356 }
00357 };
00358
00359 iterator begin(){
00360 iterator ret=iterator(this,make_tuple(0,0,0));
00361 return (this->valid_tuple(make_tuple(0,0,0)))?(ret):(++ret);
00362 }
00363 iterator end(){
00364 return iterator(this,make_tuple(-1,-1,-1));
00365 }
00366 neighbor_iterator nend(){
00367 return neighbor_iterator(make_tuple(-1,-1,-1));
00368 }
00369
00370 class object_iterator{
00371 friend void Grid_of_cubes<Traits>::erase(const object_iterator& it);
00372 protected:
00373 iterator current_cube;
00374 In_cube_iterator current_object;
00375
00376 public:
00377 object_iterator(){};
00378 object_iterator(iterator it,In_cube_iterator itc):current_cube(it),current_object(itc){};
00379 object_iterator(iterator it):current_cube(it),current_object(NULL){};
00380
00381 object_iterator& operator++(){
00382 if (++current_object==(*current_cube).end()){
00383 ++current_cube;
00384 if (current_cube!=current_cube.grid_ptr->end())
00385 current_object=(*current_cube).begin();
00386 }
00387 return *this;
00388 }
00389
00390
00391 object_iterator operator++(int ){
00392 object_iterator tmp=*this;
00393 if (++current_object==(*current_cube).end()){
00394 ++current_cube;
00395 if (current_cube!=current_cube.grid_ptr->end())
00396 current_object=(*current_cube).begin();
00397 }
00398 return tmp;
00399 }
00400
00401 Object_iterator& operator*(){ return (*current_object);};
00402 Cube_unit* operator->(){ return *(*current_object); };
00403 bool operator==(const object_iterator& it){
00404 bool ret=(this->current_cube==it.current_cube);
00405 if (!ret)
00406 return false;
00407 return (this->current_cube==this->current_cube.grid_ptr->end())?(true):(this->current_object==it.current_object);
00408 }
00409 bool operator!=(const object_iterator& it){
00410 bool ret=(this->current_cube!=it.current_cube);
00411 if (ret)
00412 return true;
00413 return (this->current_cube==this->current_cube.grid_ptr->end())?(false):(this->current_object!=it.current_object);
00414 }
00415 };
00416
00417 object_iterator last_object(){return object_iterator(this->end());}
00418 object_iterator first_object(){
00419 if (this->begin()!=this->end())
00420 return object_iterator(this->begin(),(*(this->begin())).begin());
00421 else
00422 return object_iterator(this->end());
00423 }
00424
00425 void erase(const object_iterator& it){
00426 #ifndef NDEBUG
00427 int k=get_cube(it.current_cube.current)->size();
00428 #endif
00429 get_cube(it.current_cube.current)->objects.erase(it.current_object);
00430 #ifndef NDEBUG
00431 assert(k==(int) get_cube(it.current_cube.current)->objects.size()+1);
00432 #endif
00433 if (get_cube(it.current_cube.current)->objects.size()==0){
00434 typename Cube_container::iterator Iterator=cube_container.find(it.current_cube.current);
00435 delete (*Iterator).second;
00436 cube_container.erase(Iterator);
00437 }
00438 }
00439
00440 Cube_coordinates get_first_neighbor(Cube_coordinates& T)
00441 {
00442 int a,b,c;
00443 int pb=0;
00444 if (T.get<0>()>0)
00445 a=T.get<0>()-1;
00446 else{
00447 a=T.get<0>();
00448 ++pb;
00449 }
00450 if (T.get<1>()>0)
00451 b=T.get<1>()-1;
00452 else{
00453 b=T.get<1>();
00454 ++pb;
00455 }
00456 if (T.get<2>()>0)
00457 c=T.get<2>()-1;
00458 else{
00459 c=T.get<2>();
00460 ++pb;
00461 }
00462 return (pb==3)?(Cube_coordinates(1,0,0)):(Cube_coordinates(a,b,c));
00463 }
00464
00465 neighbor_iterator first_neighbor(const Cube_coordinates& C) {
00466 return neighbor_iterator(C,this);
00467 }
00468
00469 neighbor_iterator first_neighbor(iterator& it){
00470 return neighbor_iterator(it.get_current(),this);
00471 }
00472 };
00473
00474 }
00475
00476 #endif //ESBTL_GRID_OF_CUBES_H