00001
00002
00003
00004
00005 #ifndef BALL_DATATYPE_HASHGRID_H
00006 #define BALL_DATATYPE_HASHGRID_H
00007
00008 #ifndef BALL_COMMON_H
00009 # include <BALL/common.h>
00010 #endif
00011
00012 #ifndef BALL_CONCEPT_FORWARDITERATOR_H
00013 # include <BALL/CONCEPT/forwardIterator.h>
00014 #endif
00015
00016 #ifndef BALL_CONCEPT_VISITOR_H
00017 # include <BALL/CONCEPT/visitor.h>
00018 #endif
00019
00020 #ifndef BALL_CONCEPT_PROCESSOR_H
00021 # include <BALL/CONCEPT/processor.h>
00022 #endif
00023
00024 #ifndef BALL_MATHS_VECTOR3_H
00025 # include <BALL/MATHS/vector3.h>
00026 #endif
00027
00028 #ifdef BALL_HAS_GNU_SLIST
00029 #include <ext/slist>
00030 #else
00031 #include <list>
00032 #endif
00033
00034 #include <algorithm>
00035
00036 namespace BALL
00037 {
00038 namespace __private
00039 {
00040 extern const char BALL_EXPORT neighbour_table_[27][3];
00041 }
00042
00043 template <typename Item> class HashGrid3;
00044
00049
00058 template <typename Item>
00059 class HashGridBox3
00060 {
00061 public:
00062
00066
00068 HashGridBox3(HashGrid3<Item>* parent);
00069
00071 void clear();
00072
00076 void destroy();
00077
00079
00082
00084
00087
00088 void setParent(HashGrid3<Item>* p);
00089
00093 void getIndices(Position& x, Position& y, Position& z);
00094
00100 Item* find(const Item &item);
00101
00103 const Item* find(const Item& item) const;
00104
00108 Size getSize() const;
00109
00113 void insert(const Item& item);
00114
00120 bool remove(const Item& item);
00121
00127 bool removeAll(const Item& item);
00128
00130
00133
00135 void host(Visitor<HashGridBox3> &visitor);
00137
00140
00142 bool operator == (const HashGridBox3& box) const;
00143
00145 bool operator != (const HashGridBox3& box) const;
00146
00151 bool has(const Item& item) const;
00152
00156 bool isEmpty() const;
00157
00159
00162
00164 bool isValid() const;
00166 void dump(std::ostream& s = std::cout, Size depth = 0) const;
00167
00169
00172
00174 bool apply(UnaryProcessor<Item>& processor);
00175
00177 bool apply(UnaryProcessor< HashGridBox3<Item> >& processor);
00178
00180
00183 typedef Position BoxIteratorPosition;
00184
00185 class BoxIteratorTraits
00186 {
00187 public:
00188
00189 BALL_CREATE_DEEP(BoxIteratorTraits)
00190
00191 virtual ~BoxIteratorTraits() throw () {}
00192
00193 BoxIteratorTraits()
00194 : bound_(0),
00195 position_(0),
00196 x_(0), y_(0), z_(0)
00197 {
00198 }
00199
00200 BoxIteratorTraits(const HashGridBox3& box)
00201 : bound_((HashGridBox3 *)&box),
00202 position_(0)
00203 {
00204 bound_->getIndices(x_, y_, z_);
00205 }
00206
00207 BoxIteratorTraits(const BoxIteratorTraits& traits, bool = true)
00208 : bound_(traits.bound_),
00209 position_(traits.position_)
00210 {
00211 }
00212
00213 HashGridBox3* getContainer()
00214 {
00215 return bound_;
00216 }
00217
00218 const HashGridBox3* getContainer() const
00219 {
00220 return bound_;
00221 }
00222
00223 bool isSingular() const
00224 {
00225 return (bound_ == 0);
00226 }
00227
00228 BoxIteratorPosition& getPosition()
00229 {
00230 return position_;
00231 }
00232
00233 const BoxIteratorPosition& getPosition() const
00234 {
00235 return position_;
00236 }
00237
00238 bool operator == (const BoxIteratorTraits& traits) const
00239 {
00240 return (position_ == traits.position_);
00241 }
00242
00243 bool operator != (const BoxIteratorTraits& traits) const
00244 {
00245 return (position_ != traits.position_);
00246 }
00247
00248 bool isValid() const
00249 {
00250 return (bound_ != 0 && position_ < 27);
00251 }
00252
00253 void invalidate()
00254 {
00255 bound_ = 0;
00256 position_ = 100;
00257 }
00258
00259 void toBegin()
00260 {
00261 position_ = 0;
00262 cur_box_ = bound_;
00263 }
00264
00265 bool isBegin() const
00266 {
00267 return (position_ == 0);
00268 }
00269
00270 void toEnd()
00271 {
00272 position_ = 27;
00273 cur_box_ = 0;
00274 }
00275
00276 bool isEnd() const
00277 {
00278 return (position_ == 27);
00279 }
00280
00281 HashGridBox3<Item>& getData()
00282 {
00283 return *cur_box_;
00284 }
00285
00286 const HashGridBox3<Item>& getData() const
00287 {
00288 return *cur_box_;
00289 }
00290
00291 void forward()
00292 {
00293 ++position_;
00294
00295 while ( position_ < 27
00296 && !(cur_box_ = bound_->parent->getBox(x_ + __private::neighbour_table_[position_][0],
00297 y_ + __private::neighbour_table_[position_][1],
00298 z_ + __private::neighbour_table_[position_][2])))
00299 {
00300 ++position_;
00301 }
00302 }
00303
00304 private:
00305
00306 HashGridBox3<Item> *bound_;
00307 HashGridBox3<Item> *cur_box_;
00308 BoxIteratorPosition position_;
00309 Position x_, y_, z_;
00310 };
00311
00312 friend class BoxIteratorTraits;
00313
00318 typedef ForwardIterator
00319 <HashGridBox3<Item>, HashGridBox3<Item>,
00320 BoxIteratorPosition, BoxIteratorTraits>
00321 BoxIterator;
00322
00324 BoxIterator beginBox()
00325 {
00326 return BoxIterator::begin(*this);
00327 }
00328
00330 BoxIterator endBox()
00331 {
00332 return BoxIterator::end(*this);
00333 }
00334
00335
00337 typedef ConstForwardIterator
00338 <HashGridBox3<Item>, HashGridBox3<Item>,
00339 BoxIteratorPosition, BoxIteratorTraits>
00340 ConstBoxIterator;
00341
00343 ConstBoxIterator beginBox() const
00344 {
00345 return ConstBoxIterator::begin(*this);
00346 }
00347
00349 ConstBoxIterator endBox() const
00350 {
00351 return ConstBoxIterator::end(*this);
00352 }
00353
00354 #ifdef BALL_HAS_GNU_SLIST
00355 typedef typename __gnu_cxx::slist<Item> DataContainer;
00356 #else
00357 typedef typename std::list<Item> DataContainer;
00358 #endif
00359
00360 typedef typename DataContainer::iterator DataIteratorPosition;
00361
00362 class DataIteratorTraits
00363 {
00364 public:
00365
00366 BALL_CREATE_DEEP(DataIteratorTraits)
00367
00368 virtual ~DataIteratorTraits() {}
00369
00370 DataIteratorTraits()
00371 : bound_(0),
00372 position_()
00373 {
00374 }
00375
00376 DataIteratorTraits(const HashGridBox3& box)
00377 : bound_((HashGridBox3 *)&box),
00378 position_(bound_->data.begin())
00379 {
00380 }
00381
00382 DataIteratorTraits(const DataIteratorTraits& traits, bool = true)
00383 : bound_(traits.bound_),
00384 position_(traits.position_)
00385 {
00386 }
00387
00388 const DataIteratorTraits& operator = (const DataIteratorTraits &traits)
00389 {
00390 bound_ = traits.bound_;
00391 position_ = traits.position_;
00392 return *this;
00393 }
00394
00395 HashGridBox3* getContainer()
00396 {
00397 return bound_;
00398 }
00399
00400 const HashGridBox3* getContainer() const
00401 {
00402 return bound_;
00403 }
00404
00405 bool isSingular() const
00406 {
00407 return (bound_ == 0);
00408 }
00409
00410 DataIteratorPosition& getPosition()
00411 {
00412 return position_;
00413 }
00414
00415 const DataIteratorPosition& getPosition() const
00416 {
00417 return position_;
00418 }
00419
00420 bool operator == (const DataIteratorTraits &traits) const
00421 {
00422 return (position_ == traits.position_);
00423 }
00424
00425 bool operator != (const DataIteratorTraits &traits) const
00426 {
00427 return (position_ != traits.position_);
00428 }
00429
00430 bool isValid() const
00431 {
00432 return (bound_ != 0 && position_ != bound_->data.end());
00433 }
00434
00435 void invalidate()
00436 {
00437 bound_ = 0;
00438 position_ = bound_->data.end();
00439 }
00440
00441 void toBegin()
00442 {
00443 position_ = bound_->data.begin();
00444 }
00445
00446 bool isBegin() const
00447 {
00448 return (position_ == bound_->data.begin());
00449 }
00450
00451 void toEnd()
00452 {
00453 position_ = bound_->data.end();
00454 }
00455
00456 bool isEnd() const
00457 {
00458 return (position_ == bound_->data.end());
00459 }
00460
00461 Item& getData()
00462 {
00463 return *position_;
00464 }
00465
00466 const Item& getData() const
00467 {
00468 return *position_;
00469 }
00470
00471 void forward()
00472 {
00473 ++position_;
00474 }
00475
00476 private:
00477
00478 HashGridBox3<Item>* bound_;
00479 DataIteratorPosition position_;
00480 };
00481
00482 friend class DataIteratorTraits;
00483
00487 typedef ForwardIterator
00488 <HashGridBox3<Item>, Item,
00489 DataIteratorPosition, DataIteratorTraits>
00490 DataIterator;
00491
00493 DataIterator beginData()
00494 {
00495 return DataIterator::begin(*this);
00496 }
00497
00499 DataIterator endData()
00500 {
00501 return DataIterator::end(*this);
00502 }
00503
00504
00508 typedef ConstForwardIterator
00509 <HashGridBox3<Item>, Item,
00510 DataIteratorPosition, DataIteratorTraits>
00511 ConstDataIterator;
00512
00514 ConstDataIterator beginData() const
00515 {
00516 return ConstDataIterator::begin(*this);
00517 }
00518
00520 ConstDataIterator endData() const
00521 {
00522 return ConstDataIterator::end(*this);
00523 }
00524
00526
00527 HashGrid3<Item>* parent;
00528
00529 DataContainer data;
00530 };
00531
00532 template<typename Item>
00533 HashGridBox3<Item>::HashGridBox3(HashGrid3<Item>* p)
00534 : parent(p)
00535 {
00536 }
00537
00538 template<typename Item>
00539 void HashGridBox3<Item>::clear()
00540 {
00541 data.clear();
00542 }
00543
00544 template<typename Item>
00545 BALL_INLINE
00546 void HashGridBox3<Item>::destroy()
00547 {
00548 clear();
00549 }
00550
00551 template<typename Item>
00552 BALL_INLINE void HashGridBox3<Item>::setParent(HashGrid3<Item>* p)
00553 {
00554 parent = p;
00555 }
00556
00557 template<typename Item>
00558 BALL_INLINE
00559 void HashGridBox3<Item>::getIndices(Position& x, Position& y, Position& z)
00560 {
00561 parent->getIndices(*this, x, y, z);
00562 }
00563
00564 template<typename Item>
00565 Item* HashGridBox3<Item>::find(const Item& item)
00566 {
00567 typename DataContainer::iterator found = std::find(data.begin(), data.end(), item);
00568
00569 if (found != data.end())
00570 {
00571 return &(*found);
00572 }
00573
00574 return 0;
00575 }
00576
00577 template<typename Item>
00578 BALL_INLINE
00579 const Item* HashGridBox3<Item>::find(const Item& item) const
00580 {
00581 return const_cast<HashGridBox3*>(this)->find(item);
00582 }
00583
00584 template<typename Item>
00585 Size HashGridBox3<Item>::getSize() const
00586 {
00587 return data.size();
00588 }
00589
00590 template<typename Item>
00591 BALL_INLINE
00592 void HashGridBox3<Item>::insert(const Item& item)
00593 {
00594 data.push_front(item);
00595 }
00596
00597 template<typename Item>
00598 bool HashGridBox3<Item>::remove(const Item& item)
00599 {
00600 #ifdef BALL_HAS_GNU_SLIST
00601 if(*data.begin() == item)
00602 {
00603 data.pop_front();
00604 return true;
00605 }
00606
00607 DataIteratorPosition prev = data.begin();
00608 DataIteratorPosition pos = prev;
00609 for(++pos; pos != data.end(); ++pos)
00610 {
00611 if(*pos == item)
00612 {
00613 data.erase_after(prev);
00614 return true;
00615 }
00616
00617 prev = pos;
00618 }
00619 return false;
00620 #else
00621 DataIteratorPosition pos = std::find(data.begin(), data.end(), item);
00622
00623 if (pos != data.end())
00624 {
00625 data.erase(pos);
00626
00627 return true;
00628 }
00629
00630 return false;
00631 #endif
00632 }
00633
00634 template<typename Item>
00635 bool HashGridBox3<Item>::removeAll(const Item& item)
00636 {
00637 data.remove(item);
00638
00639 return true;
00640 }
00641
00642 template <typename Item>
00643 BALL_INLINE
00644 void HashGridBox3<Item>::host(Visitor< HashGridBox3<Item> >& visitor)
00645 {
00646 visitor.visit(*this);
00647 }
00648
00649 template<typename Item>
00650 bool HashGridBox3<Item>::operator == (const HashGridBox3<Item>& box) const
00651 {
00652 return (data == box.data);
00653 }
00654
00655 template<typename Item>
00656 BALL_INLINE
00657 bool HashGridBox3<Item>::operator != (const HashGridBox3<Item>& box) const
00658 {
00659 return !(*this == box);
00660 }
00661
00662 template<typename Item>
00663 BALL_INLINE
00664 bool HashGridBox3<Item>::has(const Item& item) const
00665 {
00666 return (std::find(data.begin(), data.end(), item) != data.end());
00667 }
00668
00669 template<typename Item>
00670 BALL_INLINE
00671 bool HashGridBox3<Item>::isEmpty() const
00672 {
00673 return data.empty();
00674 }
00675
00676 template<typename Item>
00677 bool HashGridBox3<Item>::isValid() const
00678 {
00679
00680 return true;
00681 }
00682
00683 template<typename Item>
00684 void HashGridBox3<Item>::dump(std::ostream& s, Size depth) const
00685 {
00686 BALL_DUMP_STREAM_PREFIX(s);
00687
00688 BALL_DUMP_DEPTH(s, depth);
00689
00690 BALL_DUMP_DEPTH(s, depth);
00691 s << " size: " << getSize() << std::endl;
00692
00693 BALL_DUMP_DEPTH(s, depth);
00694 s << " data:" << std::endl;
00695 for (typename DataContainer::const_iterator d_it = data.begin(); d_it != data.end(); ++d_it)
00696 {
00697 BALL_DUMP_DEPTH(s, depth);
00698 s << " " << *d_it << std::endl;
00699 }
00700
00701 BALL_DUMP_STREAM_SUFFIX(s);
00702 }
00703
00704 template <typename Item>
00705 bool HashGridBox3<Item>::apply(UnaryProcessor<Item>& processor)
00706 {
00707 if (processor.start() == false)
00708 {
00709 return false;
00710 }
00711
00712 Processor::Result result;
00713
00714 for (typename DataContainer::iterator d_it = data.begin(); d_it != data.end(); ++d_it)
00715 {
00716 result = processor(*d_it);
00717
00718 if (result <= Processor::BREAK)
00719 {
00720 return (result == Processor::BREAK) ? true : false;
00721 }
00722 }
00723
00724 return processor.finish();
00725 }
00726
00727 template <typename Item>
00728 bool HashGridBox3<Item>::apply(UnaryProcessor< HashGridBox3<Item> >& processor)
00729 {
00730 if (processor.start() == false)
00731 {
00732 return false;
00733 }
00734
00735 Processor::Result result;
00736
00737 for (BoxIterator it = beginBox(); +it; ++it)
00738 {
00739 result = processor(*it);
00740
00741 if (result <= Processor::BREAK)
00742 {
00743 return (result == Processor::BREAK) ? true : false;
00744 }
00745 }
00746
00747 return processor.finish();
00748 }
00749
00754 template <typename Item>
00755 class HashGrid3
00756 {
00757 public:
00758
00759 BALL_CREATE(HashGrid3)
00760
00761
00764
00766 HashGrid3();
00767
00778 HashGrid3(const Vector3& origin, Size dimension_x, Size dimension_y,
00779 Size dimension_z, float spacing_x, float spacing_y, float spacing_z);
00780
00784 HashGrid3(const Vector3& origin, Size dimension_x, Size dimension_y,
00785 Size dimension_z, float spacing);
00786
00796 HashGrid3(const Vector3& origin, const Vector3& size, float spacing);
00797
00799 HashGrid3(const HashGrid3& grid, bool deep = true);
00800
00802 virtual ~HashGrid3();
00803
00805 virtual void clear();
00806
00808 void clear(Position x, Position y, Position z);
00809
00811 void clear(const Vector3 &vector);
00812
00814 void destroy();
00815
00817 void destroy(Position x, Position y, Position z);
00818
00820 void destroy(const Vector3& vector);
00821
00823
00826
00828 void set(const Vector3& origin, const Vector3& unit,
00829 Size dimension_x, Size dimension_y, Size dimension_z);
00830
00832 void set(const Vector3& origin, float unit, Size size);
00833
00835 void set(const HashGrid3& grid, bool deep = true);
00836
00838 const HashGrid3& operator = (const HashGrid3& grid);
00839
00841 void get(Vector3& origin, Vector3& unit, Size& dimension_x, Size& dimension_y, Size& dimension_z) const;
00842
00844 void get(HashGrid3& grid, bool deep = true) const;
00845
00847
00850
00852 Size countNonEmptyBoxes() const;
00853
00855 Size getSize() const;
00856
00858 Vector3& getOrigin();
00859
00861 const Vector3& getOrigin() const;
00862
00864 Vector3& getUnit();
00865
00867 const Vector3& getUnit() const;
00868
00870 Size getSizeX() const;
00871
00873 Size getSizeY() const;
00874
00876 Size getSizeZ() const;
00877
00879 HashGridBox3<Item>* getBox(Position x, Position y, Position z);
00880
00882 const HashGridBox3<Item>* getBox(Position x, Position y, Position z) const;
00883
00885 HashGridBox3<Item>* getBox(const Vector3& vector);
00886
00888 const HashGridBox3<Item>* getBox(const Vector3 &vector) const;
00889
00891 bool getIndices(const HashGridBox3<Item>& box,
00892 Position& x, Position& y, Position& z) const;
00893
00895 void insert(Position x, Position y, Position z, const Item& item);
00896
00898 void insert(const Vector3& vector, const Item& item);
00899
00901 bool remove(Position x, Position y, Position z, const Item& item);
00902
00904 bool remove(const Vector3& vector, const Item& item);
00905
00907
00910
00912 void host(Visitor<HashGrid3>& visitor);
00913
00915
00918
00920 bool operator == (const HashGrid3& grid) const;
00921
00923 bool operator != (const HashGrid3& grid) const;
00924
00926 bool isEmpty() const;
00927
00929
00932
00934 virtual bool isValid() const;
00935
00937 virtual void dump(std::ostream& s = std::cout, Size depth = 0) const;
00938
00940
00944
00946 bool apply(UnaryProcessor<Item> &processor);
00947
00949 bool apply(UnaryProcessor< HashGridBox3<Item> > &processor);
00950
00954 const Item* getClosestItem(const Vector3& point, Size distance) const;
00955
00962 static float calculateMinSpacing(LongIndex memory, const Vector3& size);
00963
00965
00968
00969 typedef Position BoxIteratorPosition;
00970
00971 class BoxIteratorTraits
00972 {
00973 public:
00974
00975 BALL_CREATE_DEEP(BoxIteratorTraits)
00976
00977 virtual ~BoxIteratorTraits() {}
00978
00979 BoxIteratorTraits()
00980 : bound_(0),
00981 position_(0)
00982 {
00983 }
00984
00985 BoxIteratorTraits(const HashGrid3 &grid)
00986 : bound_((HashGrid3 *)&grid),
00987 position_(0)
00988 {
00989 }
00990
00991 BoxIteratorTraits(const BoxIteratorTraits& traits, bool = true)
00992 : bound_(traits.bound_),
00993 position_(traits.position_)
00994 {
00995 }
00996
00997 const BoxIteratorTraits& operator = (const BoxIteratorTraits& traits)
00998 {
00999 bound_ = traits.bound_;
01000 position_ = traits.position_;
01001 return *this;
01002 }
01003
01004 HashGrid3* getContainer()
01005 {
01006 return bound_;
01007 }
01008
01009 const HashGrid3* getContainer() const
01010 {
01011 return bound_;
01012 }
01013
01014 bool isSingular() const
01015 {
01016 return (bound_ == 0);
01017 }
01018
01019 BoxIteratorPosition& getPosition()
01020 {
01021 return position_;
01022 }
01023
01024 const BoxIteratorPosition& getPosition() const
01025 {
01026 return position_;
01027 }
01028
01029 bool operator == (const BoxIteratorTraits& traits) const
01030 {
01031 return (position_ == traits.position_);
01032 }
01033
01034 bool operator != (const BoxIteratorTraits& traits) const
01035 {
01036 return (position_ != traits.position_);
01037 }
01038
01039 bool isValid() const
01040 {
01041 return (bound_ != 0 && position_ < bound_->getSize());
01042 }
01043
01044 void invalidate()
01045 {
01046 bound_ = 0;
01047 position_ = bound_->getSize()+1;
01048 }
01049
01050 void toBegin()
01051 {
01052 position_ = 0;
01053 }
01054
01055 bool isBegin() const
01056 {
01057 return (position_ == 0);
01058 }
01059
01060 void toEnd()
01061 {
01062 position_ = bound_->getSize();
01063 }
01064
01065 bool isEnd() const
01066 {
01067 return (position_ == bound_->getSize());
01068 }
01069
01070 HashGridBox3<Item>& getData()
01071 {
01072 return bound_->box_[position_];
01073 }
01074
01075 const HashGridBox3<Item>& getData() const
01076 {
01077 return bound_->box_[position_];
01078 }
01079
01080 void forward()
01081 {
01082 ++position_;
01083 }
01084
01085 private:
01086
01087 HashGrid3<Item>* bound_;
01088 BoxIteratorPosition position_;
01089 };
01090
01091 friend class BoxIteratorTraits;
01092
01094 typedef ForwardIterator
01095 <HashGrid3<Item>, HashGridBox3<Item>,
01096 BoxIteratorPosition, BoxIteratorTraits>
01097 BoxIterator;
01098
01100 BoxIterator beginBox()
01101 {
01102 return BoxIterator::begin(*this);
01103 }
01104
01106 BoxIterator endBox()
01107 {
01108 return BoxIterator::end(*this);
01109 }
01110
01111
01113 typedef ConstForwardIterator
01114 <HashGrid3<Item>, HashGridBox3<Item>,
01115 BoxIteratorPosition, BoxIteratorTraits>
01116 ConstBoxIterator;
01117
01119 ConstBoxIterator beginBox() const
01120 {
01121 return ConstBoxIterator::begin(*this);
01122 }
01123
01125 ConstBoxIterator endBox() const
01126 {
01127 return ConstBoxIterator::end(*this);
01128 }
01129
01131
01132 private:
01133
01134
01135 Index getIndex_(const HashGridBox3<Item>& box) const;
01136
01137
01138 Vector3 origin_;
01139
01140 Vector3 unit_;
01141
01142 Size dimension_x_;
01143
01144 Size dimension_y_;
01145
01146 Size dimension_z_;
01147
01148 vector<HashGridBox3<Item> > box_;
01149 };
01150
01151
01153
01154
01155 template <typename Item>
01156 HashGrid3<Item>::HashGrid3()
01157 : origin_(0,0,0),
01158 unit_(0,0,0),
01159 dimension_x_(0),
01160 dimension_y_(0),
01161 dimension_z_(0)
01162 {
01163 }
01164
01165 template <typename Item>
01166 HashGrid3<Item>::HashGrid3
01167 (const Vector3 &originvector,
01168 Size dimension_x, Size dimension_y, Size dimension_z,
01169 float spacing_x, float spacing_y, float spacing_z)
01170 : origin_(originvector),
01171 unit_(spacing_x, spacing_y, spacing_z),
01172 dimension_x_(dimension_x),
01173 dimension_y_(dimension_y),
01174 dimension_z_(dimension_z),
01175 box_(dimension_x * dimension_y * dimension_z, HashGridBox3<Item>(this))
01176 {
01177 }
01178
01179 template <typename Item>
01180 HashGrid3<Item>::HashGrid3
01181 (const Vector3& origin,
01182 Size dimension_x, Size dimension_y, Size dimension_z, float spacing)
01183 : origin_(origin),
01184 unit_(spacing, spacing, spacing),
01185 dimension_x_(dimension_x),
01186 dimension_y_(dimension_y),
01187 dimension_z_(dimension_z),
01188 box_(dimension_x * dimension_y * dimension_z, HashGridBox3<Item>(this))
01189 {
01190 }
01191
01192
01193 template <typename Item>
01194 HashGrid3<Item>::HashGrid3(const Vector3& origin, const Vector3& size,
01195 float spacing)
01196 : origin_(origin),
01197 unit_(spacing, spacing, spacing),
01198 dimension_x_((Size)(size.x / spacing + 1.0)),
01199 dimension_y_((Size)(size.y / spacing + 1.0)),
01200 dimension_z_((Size)(size.z / spacing + 1.0)),
01201 box_(dimension_x_ * dimension_y_ * dimension_z_, HashGridBox3<Item>(this))
01202 {
01203 }
01204
01205 template <typename Item>
01206 HashGrid3<Item>::HashGrid3(const HashGrid3<Item>& grid, bool deep)
01207 {
01208 set(grid, deep);
01209 }
01210
01211 template <typename Item>
01212 HashGrid3<Item>::~HashGrid3()
01213 {
01214 }
01215
01216 template <typename Item>
01217 void HashGrid3<Item>::clear()
01218 {
01219 Size size = dimension_x_ * dimension_y_ * dimension_z_;
01220
01221 for (Position index = 0; index < (Position)size; ++index)
01222 {
01223 box_[index].clear();
01224 }
01225 }
01226
01227 template <typename Item>
01228 BALL_INLINE
01229 void HashGrid3<Item>::clear(Position x, Position y, Position z)
01230 {
01231 HashGridBox3<Item>* box = getBox(x, y, z);
01232
01233 if (box != 0)
01234 {
01235 box->clear();
01236 }
01237 }
01238
01239 template <typename Item>
01240 BALL_INLINE
01241 void HashGrid3<Item>::clear(const Vector3& vector)
01242 {
01243 HashGridBox3<Item>* box = getBox(vector);
01244
01245 if (box != 0)
01246 {
01247 box->clear();
01248 }
01249 }
01250
01251 template <typename Item>
01252 BALL_INLINE
01253 void HashGrid3<Item>::destroy()
01254 {
01255 clear();
01256 }
01257
01258 template <typename Item>
01259 BALL_INLINE
01260 void HashGrid3<Item>::destroy(Position x, Position y, Position z)
01261 {
01262 clear(x, y, z);
01263 }
01264
01265 template <typename Item>
01266 BALL_INLINE
01267 void HashGrid3<Item>::destroy(const Vector3 &vector)
01268 {
01269 clear(vector);
01270 }
01271
01272 template <typename Item>
01273 void HashGrid3<Item>::set
01274 (const Vector3& origin, const Vector3& unit,
01275 Size dimension_x, Size dimension_y, Size dimension_z)
01276 {
01277 origin_.set(origin);
01278 unit_.set(unit);
01279 dimension_x_ = dimension_x;
01280 dimension_y_ = dimension_y;
01281 dimension_z_ = dimension_z;
01282 box_.assign(getSize(), HashGridBox3<Item>(this));
01283 }
01284
01285 template <typename Item>
01286 void HashGrid3<Item>::set(const Vector3& origin, float unit, Size size)
01287 {
01288 origin_.set(origin);
01289 unit_.set(unit, unit, unit);
01290 dimension_x_ = size;
01291 dimension_y_ = size;
01292 dimension_z_ = size;
01293 box_.assign(getSize(), HashGridBox3<Item>(this));
01294 }
01295
01296 template <typename Item>
01297 void HashGrid3<Item>::set(const HashGrid3<Item>& grid, bool )
01298 {
01299 origin_.set(grid.origin_);
01300 unit_.set(grid.unit_);
01301 dimension_x_ = grid.dimension_x_;
01302 dimension_y_ = grid.dimension_y_;
01303 dimension_z_ = grid.dimension_z_;
01304 box_ = grid.box_;
01305
01306 for(Position i = 0; i < box_.size(); ++i)
01307 {
01308 box_[i].setParent(this);
01309 }
01310 }
01311
01312 template <typename Item>
01313 BALL_INLINE
01314 const HashGrid3<Item>& HashGrid3<Item>::operator = (const HashGrid3<Item> &grid)
01315 {
01316 set(grid);
01317
01318 return *this;
01319 }
01320
01321 template <typename Item>
01322 BALL_INLINE
01323 void HashGrid3<Item>::get(Vector3 &origin, Vector3 &unit,
01324 Size& dimension_x, Size& dimension_y, Size& dimension_z) const
01325 {
01326 origin.set(origin_);
01327 unit.set(unit_);
01328 dimension_x = dimension_x_;
01329 dimension_y = dimension_y_;
01330 dimension_z = dimension_z_;
01331 }
01332
01333 template <typename Item>
01334 BALL_INLINE void
01335 HashGrid3<Item>::get(HashGrid3<Item> &grid, bool deep) const
01336 {
01337 grid.set(*this, deep);
01338 }
01339
01340 template <typename Item>
01341 Size
01342 HashGrid3<Item>::countNonEmptyBoxes() const
01343 {
01344 Size size = 0;
01345
01346 for (Position i=0; i<27; ++i)
01347 {
01348 if (!box_[i].isEmpty())
01349 ++size;
01350 }
01351
01352 return size;
01353 }
01354
01355 template <typename Item>
01356 BALL_INLINE
01357 Size HashGrid3<Item>::getSize() const
01358 {
01359 return (dimension_x_ * dimension_y_ * dimension_z_);
01360 }
01361
01362 template <typename Item>
01363 BALL_INLINE
01364 Vector3& HashGrid3<Item>::getOrigin()
01365 {
01366 return origin_;
01367 }
01368
01369 template <typename Item>
01370 BALL_INLINE
01371 const Vector3& HashGrid3<Item>::getOrigin() const
01372 {
01373 return origin_;
01374 }
01375
01376 template <typename Item>
01377 BALL_INLINE
01378 Vector3& HashGrid3<Item>::getUnit()
01379 {
01380 return unit_;
01381 }
01382
01383 template <typename Item>
01384 BALL_INLINE
01385 const Vector3& HashGrid3<Item>::getUnit() const
01386 {
01387 return unit_;
01388 }
01389
01390 template <typename Item>
01391 BALL_INLINE
01392 Size HashGrid3<Item>::getSizeX() const
01393 {
01394 return dimension_x_;
01395 }
01396
01397 template <typename Item>
01398 BALL_INLINE
01399 Size HashGrid3<Item>::getSizeY() const
01400 {
01401 return dimension_y_;
01402 }
01403
01404 template <typename Item>
01405 BALL_INLINE
01406 Size HashGrid3<Item>::getSizeZ() const
01407 {
01408 return dimension_z_;
01409 }
01410
01411 template <typename Item>
01412 const Item* HashGrid3<Item>::getClosestItem(const Vector3& point, Size dist) const
01413 {
01414 const HashGridBox3<Item>* box = getBox(point);
01415 if (!box) return 0;
01416
01417 Position x, y, z;
01418 getIndices(*box, x, y, z);
01419
01420 const Item* item = 0;
01421 float distance = FLT_MAX;
01422
01423
01424 for (Index xi = -(Index)dist; xi <= (Index)dist; xi++)
01425 {
01426 const Index xn = x + xi;
01427 for (Index yi = -(Index)dist; yi <= (Index)dist; yi++)
01428 {
01429 const Index yn = y + yi;
01430 for (Index zi = -(Index)dist; zi <= (Index)dist; zi++)
01431 {
01432
01433 const HashGridBox3<Item>* const box_ptr = getBox(xn, yn, z+zi);
01434 if (box_ptr != 0 && !box_ptr->isEmpty())
01435 {
01436 typename HashGridBox3<Item>::ConstDataIterator hit = box_ptr->beginData();
01437 for (;hit != box_ptr->endData(); hit++)
01438 {
01439 const float new_dist = ((*hit)->getPosition() - point).getSquareLength();
01440 if (new_dist < distance)
01441 {
01442 item = &*hit;
01443 distance = new_dist;
01444 }
01445 }
01446 }
01447 }
01448 }
01449 }
01450
01451 return item;
01452 }
01453
01454 template <typename Item>
01455 BALL_INLINE
01456 float HashGrid3<Item>::calculateMinSpacing(LongIndex memory, const Vector3& size)
01457 {
01458 LongSize memory_for_box = sizeof(HashGridBox3<Item>) + sizeof(HashGridBox3<Item>*);
01459 LongSize nr_boxes =(LongSize)floor((float)(memory / memory_for_box));
01460
01461 return pow((double)((size.x * size.y * size.z) / nr_boxes), (double)(1.0 / 3.0));
01462 }
01463
01464 template <typename Item>
01465 BALL_INLINE
01466 HashGridBox3<Item>* HashGrid3<Item>::getBox(Position x, Position y, Position z)
01467 {
01468 if (x >= (Position)dimension_x_ ||
01469 y >= (Position)dimension_y_ ||
01470 z >= (Position)dimension_z_)
01471 {
01472 return 0;
01473 }
01474 else
01475 {
01476 return &(box_[x * dimension_y_ * dimension_z_ + y * dimension_z_ + z]);
01477 }
01478 }
01479
01480 template <typename Item>
01481 BALL_INLINE
01482 const HashGridBox3<Item>* HashGrid3<Item>::getBox(Position x, Position y, Position z) const
01483 {
01484 return ((HashGrid3*)this)->getBox(x, y, z);
01485 }
01486
01487 template <typename Item>
01488 BALL_INLINE
01489 HashGridBox3<Item>* HashGrid3<Item>::getBox(const Vector3& vector)
01490 {
01491 float x = (vector.x - origin_.x) / unit_.x;
01492 float y = (vector.y - origin_.y) / unit_.y;
01493 float z = (vector.z - origin_.z) / unit_.z;
01494
01495
01496 Index x1 = (Index) Maths::floor(x);
01497 Index y1 = (Index) Maths::floor(y);
01498 Index z1 = (Index) Maths::floor(z);
01499
01500 return getBox(x1, y1, z1);
01501 }
01502
01503 template <typename Item>
01504 BALL_INLINE
01505 const HashGridBox3<Item>* HashGrid3<Item>::getBox(const Vector3& vector) const
01506 {
01507 return ((HashGrid3 *)this)->getBox(vector);
01508 }
01509
01510 template <typename Item>
01511 BALL_INLINE
01512 bool HashGrid3<Item>::getIndices
01513 (const HashGridBox3<Item>& box,
01514 Position& x, Position& y, Position& z) const
01515 {
01516 Index index = getIndex_(box);
01517
01518 if (index == INVALID_INDEX)
01519 {
01520 x = y = z = INVALID_POSITION;
01521
01522 return false;
01523 }
01524
01525 x = index / (dimension_y_ * dimension_z_);
01526 index -= x * dimension_y_ * dimension_z_;
01527 y = index / dimension_z_;
01528 z = index - y * dimension_z_;
01529
01530 return true;
01531 }
01532
01533 template <typename Item>
01534 BALL_INLINE
01535 void HashGrid3<Item>::insert
01536 (Position x, Position y, Position z, const Item& item)
01537 {
01538 HashGridBox3<Item>* box = getBox(x, y, z);
01539
01540 if (box != 0)
01541 {
01542 box->insert(item);
01543 }
01544 }
01545
01546 template <typename Item>
01547 BALL_INLINE
01548 void HashGrid3<Item>::insert(const Vector3& vector, const Item& item)
01549 {
01550 HashGridBox3<Item> *box = getBox(vector);
01551
01552 if (box != 0)
01553 {
01554 box->insert(item);
01555 }
01556 }
01557
01558 template <typename Item>
01559 BALL_INLINE
01560 bool HashGrid3<Item>::remove(Position x, Position y, Position z, const Item& item)
01561 {
01562 HashGridBox3<Item>* box = getBox(x, y, z);
01563
01564 if (box != 0)
01565 {
01566 return box->remove(item);
01567 }
01568
01569 return false;
01570 }
01571
01572 template <typename Item>
01573 BALL_INLINE
01574 bool HashGrid3<Item>::remove(const Vector3& vector, const Item& item)
01575 {
01576 HashGridBox3<Item>* box = getBox(vector);
01577
01578 if (box != 0)
01579 {
01580 return box->remove(item);
01581 }
01582
01583 return false;
01584 }
01585
01586 template <typename Item>
01587 BALL_INLINE
01588 void HashGrid3<Item>::host(Visitor< HashGrid3<Item> >& visitor)
01589 {
01590 visitor.visit(*this);
01591 }
01592
01593 template <typename Item>
01594 BALL_INLINE
01595 bool HashGrid3<Item>::operator == (const HashGrid3<Item>& grid) const
01596 {
01597 if (getSize() != grid.getSize()
01598 || origin_ != grid.origin_
01599 || unit_ != grid.unit_
01600 || dimension_x_ != grid.dimension_x_
01601 || dimension_y_ != grid.dimension_y_
01602 || dimension_z_ != grid.dimension_z_)
01603 {
01604 return false;
01605 }
01606
01607 return box_ == grid.box_;
01608 }
01609
01610 template <typename Item>
01611 BALL_INLINE
01612 bool HashGrid3<Item>::operator != (const HashGrid3<Item>& grid) const
01613 {
01614 return !(*this == grid);
01615 }
01616
01617 template <typename Item>
01618 BALL_INLINE
01619 bool HashGrid3<Item>::isEmpty() const
01620 {
01621 return (getSize() == 0);
01622 }
01623
01624 template <typename Item>
01625 bool HashGrid3<Item>::isValid() const
01626 {
01627 Size size = getSize();
01628
01629 for (Position index = 0; index < (Position)size; ++index)
01630 {
01631 if (box_[index].isValid() == false)
01632 {
01633 return false;
01634 }
01635 }
01636
01637 return true;
01638 }
01639
01640 template <typename Item>
01641 void HashGrid3<Item>::dump(std::ostream& s, Size depth) const
01642 {
01643 BALL_DUMP_STREAM_PREFIX(s);
01644
01645 BALL_DUMP_DEPTH(s, depth);
01646
01647 BALL_DUMP_DEPTH(s, depth);
01648 s << " origin: " << origin_ << std::endl;
01649
01650 BALL_DUMP_DEPTH(s, depth);
01651 s << " unit: " << unit_.z << std::endl;
01652
01653 BALL_DUMP_DEPTH(s, depth);
01654 s << " dimension: " << dimension_x_ << " "
01655 << dimension_y_ << " "
01656 << dimension_z_ << std::endl;
01657
01658 Size size = getSize();
01659 BALL_DUMP_DEPTH(s, depth);
01660 s << " size: " << size << std::endl;
01661
01662 BALL_DUMP_DEPTH(s, depth);
01663 s << " non empty boxes: " << countNonEmptyBoxes() << std::endl;
01664
01665 BALL_DUMP_DEPTH(s, depth);
01666 s << " boxes:" << std::endl;
01667 Position x, y, z;
01668 for (Position index = 0; index < (Position)size; ++index)
01669 {
01670 BALL_DUMP_DEPTH(s, depth);
01671 getIndices(box_[index], x, y, z);
01672 s << " " << index << ". box: ("
01673 << x << ',' << y << ',' << z << ')' << std::endl;
01674 box_[index].dump(s, 1);
01675 }
01676
01677 BALL_DUMP_DEPTH(s, depth);
01678 s << " non-empty boxes:" << std::endl;
01679
01680 for (Position i=0; i<27; ++i)
01681 {
01682 if (!box_[i].isEmpty())
01683 s << " " << getIndex_(box_[i]) << std::endl;
01684 }
01685 BALL_DUMP_STREAM_SUFFIX(s);
01686 }
01687
01688 template <typename Item>
01689 bool HashGrid3<Item>::apply(UnaryProcessor<Item>& processor)
01690 {
01691 if (processor.start() == false)
01692 {
01693 return false;
01694 }
01695 Processor::Result result;
01696
01697 for (Position i=0; i<27; ++i)
01698 {
01699 HashGridBox3<Item>* box = &box_[i];
01700 for (typename HashGridBox3<Item>::DataIterator *item = box->beginData(); +item; ++item)
01701 {
01702 result = processor(*item);
01703
01704 if (result <= Processor::BREAK)
01705 {
01706 return (result == Processor::BREAK) ? true : false;
01707 }
01708 }
01709 }
01710
01711 return processor->finish();
01712 }
01713
01714 template <typename Item>
01715 bool HashGrid3<Item>::apply(UnaryProcessor< HashGridBox3<Item> >& processor)
01716 {
01717 if (processor.start() == false)
01718 {
01719 return false;
01720 }
01721
01722 Processor::Result result;
01723
01724 for (Position i=0; i<27; ++i)
01725 {
01726 HashGridBox3<Item>* box = &box_[i];
01727 result = processor(*box);
01728
01729 if (result <= Processor::BREAK)
01730 {
01731 return (result == Processor::BREAK) ? true : false;
01732 }
01733 }
01734
01735 return processor->finish();
01736 }
01737
01738 template <typename Item>
01739 BALL_INLINE
01740 Index HashGrid3<Item>::getIndex_(const HashGridBox3<Item>& box) const
01741 {
01742 if (&box < &box_[0] ||& box >= &box_[getSize()])
01743 {
01744 return INVALID_INDEX;
01745 }
01746 else
01747 {
01748 return (Index)(&box - &box_[0]);
01749 }
01750 }
01751 }
01752
01753 #endif // BALL_DATATYPE_HASHGRID_H