UGDK
src/ugdk/util/intervalkdtree.h
Go to the documentation of this file.
00001 #ifndef UGDK_UTIL_INTERVALKDTREE_H_
00002 #define UGDK_UTIL_INTERVALKDTREE_H_
00003 
00004 #include <cassert>
00005 #include <cstddef>
00006 #include <map>
00007 #include <list>
00008 #include <vector>
00009 #include <climits>
00010 #ifdef DEBUG
00011 #include <iostream>
00012 #endif
00013 
00014 namespace ugdk {
00015 
00016 namespace ikdtree {
00017 
00018 template <int DIMENSIONS>
00019 class Box;
00020 
00021 template <class T, int DIMENSIONS>
00022 class Node;
00023 
00024 template <class T, int DIMENSIONS>
00025 class Item;
00026 
00027 typedef double Coordinate;
00028 
00029 template <class T, int DIMENSIONS>
00030 class IntervalKDTree {
00031     public:
00032         IntervalKDTree (const Box<DIMENSIONS>& tree_bounding_box,
00033                         unsigned int max_elements_per_leaf);
00034         ~IntervalKDTree ();
00035         void Clear ();
00036         void Insert (Box<DIMENSIONS> bounding_box, T element);
00037         void Remove (T element);
00038         void Update (const Box<DIMENSIONS>& new_bounding_box, T element);
00039         std::vector<T>* getIntersectingItems (const Box<DIMENSIONS>& boundary) const;
00040         unsigned int max_elements_per_leaf ();
00041 #ifdef DEBUG
00042         unsigned int max_height_;
00043         void PrintTree ();
00044 #endif
00045     private:
00046         unsigned int max_elements_per_leaf_;
00047         Box<DIMENSIONS> tree_bounding_box_;
00048         std::map<T,Item<T, DIMENSIONS>* > container_items_;
00049         Node<T, DIMENSIONS> * root_;
00050         void UpdateItem (Item<T, DIMENSIONS> * item);
00051 };
00052 
00053 template <int DIMENSIONS>
00054 class Box {
00055     public:
00056         Box (const Coordinate *min_coordinates, const Coordinate *max_coordinates);
00057         Box (const Box& box);
00058         void setBox (const Box& box);
00059         ~Box ();
00060         bool IsBelow (int depth, Coordinate boundary) const;
00061         bool IsAbove (int depth, Coordinate boundary) const;
00062         bool Contains (const Box& box) const;
00063         bool Intersects (const Box *box) const;
00064     protected:
00065         Coordinate min_coordinates_[DIMENSIONS];
00066         Coordinate max_coordinates_[DIMENSIONS];
00067 };
00068 
00069 //************* Implementation **************
00070 
00071 //**** Classes needed for implementation ****
00072 
00073 template <class T, int DIMENSIONS>
00074 class Item : public Box<DIMENSIONS> {
00075     public :
00076         Item (Box<DIMENSIONS> bounding_box, T element);
00077         ~Item ();
00078         T element ();
00079         void set_container_node (Node<T, DIMENSIONS> *container_node);
00080         Node<T, DIMENSIONS> *container_node ();
00081 #ifdef DEBUG
00082         void Print ();
00083 #endif
00084     private:
00085         typedef Box<DIMENSIONS> super;
00086         T element_;
00087         Node<T, DIMENSIONS> *container_node_;
00088 };
00089 
00090 template <class T, int DIMENSIONS>
00091 class Node : public Box<DIMENSIONS> {
00092     public:
00093         Node (IntervalKDTree<T, DIMENSIONS> * const tree, Node *parent, int depth,
00094                 Coordinate *min_coordinates, Coordinate *max_coordinates);
00095         Node (IntervalKDTree<T, DIMENSIONS> * const tree, Node *parent, int depth,
00096                 const Box<DIMENSIONS>& coordinates);
00097         ~Node ();
00098         void InsertItem (Item<T, DIMENSIONS> *item);
00099         void RemoveItem (Item<T, DIMENSIONS> *item);
00100         void getIntersectingItems (const Box<DIMENSIONS>& boundary,
00101                 std::vector<T> *items) const;
00102         void Clear ();
00103         int depth_;
00104         Coordinate division_boundary_;
00105         bool has_children_;
00106 #ifdef DEBUG
00107         void PrintTreeRootedAtThisNode ();
00108 #endif
00109     private:
00110         typedef Box<DIMENSIONS> super;
00111         IntervalKDTree<T, DIMENSIONS> *tree_;
00112         Node * parent_;
00113         Node * low_child_, * high_child_;
00114         // TODO: Test if some kind of tree is faster than a list
00115         // Maybe an interval tree along one of the other axis (not
00116         // on the axis that this node divides)
00117         // Maybe even another KD-Interval-Tree. (but taking care to not
00118         // have infinite recursive trees)
00119         std::list<Item<T, DIMENSIONS> *> items_;
00120 
00121         void Divide ();
00122         void Merge ();
00123 };
00124 
00125 // IntervalKDTree implementation
00126 
00127 template <class T, int DIMENSIONS>
00128 IntervalKDTree<T, DIMENSIONS>::IntervalKDTree (
00129                                     const Box<DIMENSIONS>& tree_bounding_box,
00130                                     unsigned int max_elements_per_leaf) :
00131     max_elements_per_leaf_(max_elements_per_leaf), 
00132     tree_bounding_box_(tree_bounding_box), 
00133     container_items_() {
00134         root_ = new Node<T, DIMENSIONS>(this, NULL, 0, tree_bounding_box);
00135 #ifdef DEBUG
00136     max_height_ = 0;
00137 #endif
00138 }
00139 
00140 template <class T, int DIMENSIONS>
00141 IntervalKDTree<T, DIMENSIONS>::~IntervalKDTree () {
00142     root_->Clear ();
00143     delete root_;
00144 }
00145 
00146 template <class T, int DIMENSIONS>
00147 void IntervalKDTree<T, DIMENSIONS>::Clear () {
00148     container_items_.clear ();
00149     root_->Clear ();
00150     delete root_;
00151     root_ = new Node<T,DIMENSIONS> (this, NULL, 0, tree_bounding_box_);
00152 }
00153 
00154 template <class T, int DIMENSIONS>
00155 void IntervalKDTree<T, DIMENSIONS>::Insert (Box<DIMENSIONS> bounding_box, T element) {
00156     // Shouldn't insert an element twice!
00157     assert (!container_items_.count (element));
00158     Item<T, DIMENSIONS> * item = new Item<T, DIMENSIONS> (bounding_box, element);
00159     root_->InsertItem (item);
00160     container_items_[element] = item;
00161 }
00162 
00163 template <class T, int DIMENSIONS>
00164 void IntervalKDTree<T, DIMENSIONS>::Remove (T element) {
00165     assert (container_items_.count (element));
00166     if (container_items_.count (element)) {
00167         Item<T, DIMENSIONS> *item = container_items_[element];
00168         Node<T, DIMENSIONS> *node = item->container_node();
00169         node->RemoveItem (item);
00170         container_items_.erase (element);
00171         delete item;
00172     }
00173 }
00174 
00175 template <class T, int DIMENSIONS>
00176 void IntervalKDTree<T, DIMENSIONS>::Update (const Box<DIMENSIONS>& new_bounding_box,
00177         T element) {
00178     // Shouldn't update an unexisting element!
00179     assert (container_items_.count(element));
00180     Item<T, DIMENSIONS> * item = container_items_[element];
00181     item->setBox (new_bounding_box);
00182     UpdateItem (item);
00183 }
00184 
00185 template <class T, int DIMENSIONS>
00186 void IntervalKDTree<T, DIMENSIONS>::UpdateItem (Item<T, DIMENSIONS> * item) {
00187     Node<T, DIMENSIONS> *container_node = item->container_node ();
00188 
00189     if ((container_node->has_children_ &&
00190              (item->IsBelow (container_node->depth_,
00191                              container_node->division_boundary_)
00192               || item->IsAbove (container_node->depth_,
00193                                 container_node->division_boundary_))
00194         ) || !container_node->Contains (*item)) {
00195         // We need to place it in a different node
00196         // Remove and add item
00197         container_node->RemoveItem (item);
00198         root_->InsertItem (item);
00199     }
00200 }
00201 
00202 template <class T, int DIMENSIONS>
00203 std::vector<T>* IntervalKDTree<T, DIMENSIONS>::getIntersectingItems (
00204         const Box<DIMENSIONS>& boundary) const {
00205     std::vector<T>* items = new std::vector<T>;
00206     root_->getIntersectingItems (boundary, items);
00207     return items;
00208 }
00209 
00210 template <class T, int DIMENSIONS>
00211 unsigned int IntervalKDTree<T, DIMENSIONS>::max_elements_per_leaf () {
00212     return max_elements_per_leaf_;
00213 }
00214 
00215 #ifdef DEBUG
00216 template <class T, int DIMENSIONS>
00217 void IntervalKDTree<T, DIMENSIONS>::PrintTree () {
00218     root_->PrintTreeRootedAtThisNode ();
00219 }
00220 #endif
00221 
00222 // Box implementation
00223 
00224 template <int DIMENSIONS>
00225 Box<DIMENSIONS>::Box (const Coordinate *min_coordinates, const Coordinate *max_coordinates) {
00226     if (min_coordinates != NULL && max_coordinates != NULL) {
00227         for (int k = 0; k < DIMENSIONS; ++k) {
00228             min_coordinates_[k] = min_coordinates[k];
00229             max_coordinates_[k] = max_coordinates[k];
00230         }
00231     }
00232 }
00233 
00234 template <int DIMENSIONS>
00235 Box<DIMENSIONS>::Box (const Box& box) {
00236     for (int k = 0; k < DIMENSIONS; ++k) {
00237         min_coordinates_[k] = box.min_coordinates_[k];
00238         max_coordinates_[k] = box.max_coordinates_[k];
00239     }
00240 }
00241 
00242 template <int DIMENSIONS>
00243 Box<DIMENSIONS>::~Box () {}
00244 
00245 template <int DIMENSIONS>
00246 void Box<DIMENSIONS>::setBox (const Box& box) {
00247     for (int k = 0; k < DIMENSIONS; ++k) {
00248         min_coordinates_[k] = box.min_coordinates_[k];
00249         max_coordinates_[k] = box.max_coordinates_[k];
00250     }
00251 }
00252 
00253 template <int DIMENSIONS>
00254 bool Box<DIMENSIONS>::IsBelow (int depth, Coordinate boundary) const {
00255     return max_coordinates_[depth % DIMENSIONS] <= boundary;
00256 }
00257 
00258 template <int DIMENSIONS>
00259 bool Box<DIMENSIONS>::IsAbove (int depth, Coordinate boundary) const {
00260     return boundary < min_coordinates_[depth % DIMENSIONS];
00261 }
00262 
00263 template <int DIMENSIONS>
00264 bool Box<DIMENSIONS>::Contains (const Box& box) const {
00265     for (int k = 0; k < DIMENSIONS; ++k) {
00266         // first comparison is a strict inequality
00267         // because of the way IsBelow and IsAbove are
00268         // defined.
00269         if (!(       min_coordinates_[k] <  box.min_coordinates_[k]
00270               && box.max_coordinates_[k] <=     max_coordinates_[k]))
00271             return false;
00272     }
00273     return true;
00274 }
00275 
00276 template <int DIMENSIONS>
00277 bool Box<DIMENSIONS>::Intersects (const Box *box) const {
00278     for (int k = 0; k < DIMENSIONS; ++k) {
00279         if (!(        min_coordinates_[k] <= box->max_coordinates_[k]
00280               && box->min_coordinates_[k] <=      max_coordinates_[k]))
00281             // found separating axis
00282             return false;
00283     }
00284     return true;
00285 }
00286 
00287 // Item Implementation
00288 
00289 template <class T, int DIMENSIONS>
00290 Item<T, DIMENSIONS>::Item (Box<DIMENSIONS> bounding_box, T element) :
00291     super (bounding_box), element_(element) {}
00292 
00293 template <class T, int DIMENSIONS>
00294 Item<T, DIMENSIONS>::~Item () {}
00295 
00296 template <class T, int DIMENSIONS>
00297 Node<T, DIMENSIONS>* Item<T, DIMENSIONS>::container_node () {
00298     return container_node_;
00299 }
00300 
00301 template <class T, int DIMENSIONS>
00302 void Item<T, DIMENSIONS>::set_container_node (Node<T, DIMENSIONS> *container_node) {
00303     container_node_ = container_node;
00304 }
00305 
00306 template <class T, int DIMENSIONS>
00307 T Item<T, DIMENSIONS>::element () {
00308     return element_;
00309 }
00310 
00311 #ifdef DEBUG
00312 template <class T, int DIMENSIONS>
00313 void Item<T, DIMENSIONS>::Print () {
00314     std::cout << element_;
00315 }
00316 #endif
00317 
00318 // Node Implementation
00319 
00320 template <class T, int DIMENSIONS>
00321 Node<T, DIMENSIONS>::Node (IntervalKDTree<T, DIMENSIONS> * const tree,
00322     Node *parent, int depth,
00323     Coordinate *min_coordinates, Coordinate *max_coordinates) :
00324     super (min_coordinates, max_coordinates), depth_(depth), has_children_(false), 
00325     tree_(tree), parent_(parent), low_child_(NULL), high_child_(NULL) {}
00326 
00327 template <class T, int DIMENSIONS>
00328 Node<T, DIMENSIONS>::Node (IntervalKDTree<T, DIMENSIONS> * const tree,
00329     Node *parent, int depth, const Box<DIMENSIONS>& coordinates) :
00330     super (coordinates), depth_(depth), has_children_(false), 
00331     tree_(tree), parent_(parent), low_child_(NULL), high_child_(NULL) {}
00332 
00333 template <class T, int DIMENSIONS>
00334 Node<T, DIMENSIONS>::~Node () {
00335     if (low_child_)
00336         delete low_child_;
00337     if (high_child_)
00338         delete high_child_;
00339 }
00340 
00341 template <class T, int DIMENSIONS>
00342 void Node<T, DIMENSIONS>::InsertItem (Item<T, DIMENSIONS> *item) {
00343 #ifdef DEBUG
00344     if (static_cast<unsigned int>(depth_) > tree_->max_height_) {
00345         tree_->max_height_ = depth_;
00346     }
00347 #endif
00348     if (has_children_) {
00349         if (item->IsBelow (depth_, division_boundary_)) {
00350             assert (low_child_);
00351             low_child_->InsertItem (item);
00352             return;
00353         } else if (item->IsAbove (depth_, division_boundary_)) {
00354             assert (high_child_);
00355             high_child_->InsertItem (item);
00356             return;
00357         }
00358     }
00359     items_.push_back (item);
00360     item->set_container_node (this);
00361     if (!has_children_ && items_.size() > tree_->max_elements_per_leaf()) {
00362         Divide ();
00363     }
00364 }
00365 
00366 template <class T, int DIMENSIONS>
00367 void Node<T, DIMENSIONS>::RemoveItem (Item<T, DIMENSIONS> *item) {
00368     items_.remove (item);
00369     if (parent_)
00370         parent_->Merge ();
00371 }
00372 
00373 template <class T, int DIMENSIONS>
00374 void Node<T, DIMENSIONS>::getIntersectingItems (const Box<DIMENSIONS>& boundary,
00375         std::vector<T> *intersecting_items) const {
00376     for (typename std::list<Item<T, DIMENSIONS> *>::const_iterator it = items_.begin();
00377             it != items_.end(); ++it) {
00378         if (boundary.Intersects (*it)) {
00379             intersecting_items->push_back ((*it)->element ());
00380         }
00381     }
00382     if (has_children_) {
00383         if (boundary.IsBelow (depth_, division_boundary_)) {
00384             low_child_->getIntersectingItems (boundary, intersecting_items);
00385         } else if (boundary.IsAbove (depth_, division_boundary_)) {
00386             high_child_->getIntersectingItems (boundary, intersecting_items);
00387         } else {
00388             low_child_->getIntersectingItems (boundary, intersecting_items);
00389             high_child_->getIntersectingItems (boundary, intersecting_items);
00390         }
00391     }
00392 }
00393 
00394 template <class T, int DIMENSIONS>
00395 void Node<T, DIMENSIONS>::Divide () {
00396     assert (!has_children_);
00397     has_children_ = true;
00398 
00399     int dimension = depth_ % DIMENSIONS;
00400     // TODO: Test other strategies for dividing space
00401     division_boundary_ = (  this->min_coordinates_[dimension]
00402                           + this->max_coordinates_[dimension]) / 2;
00403 
00404     Coordinate new_min_coordinates[DIMENSIONS],
00405                new_max_coordinates[DIMENSIONS];
00406     for (int k = 0; k < DIMENSIONS; ++k) {
00407         if (k == dimension) {
00408             new_min_coordinates[k] = new_max_coordinates[k]
00409                 = division_boundary_;
00410         } else {
00411             new_min_coordinates[k] = this->min_coordinates_[k];
00412             new_max_coordinates[k] = this->max_coordinates_[k];
00413         }
00414     }
00415     low_child_ = new Node (tree_, this, depth_ + 1,
00416             this->min_coordinates_, new_max_coordinates);
00417     high_child_ = new Node (tree_, this, depth_ + 1,
00418             new_min_coordinates, this->max_coordinates_);
00419 
00420     std::list<Item<T, DIMENSIONS> *> old_items_list = items_;
00421     items_.clear();
00422     for (typename std::list<Item<T, DIMENSIONS> *>::iterator it
00423             = old_items_list.begin(); it != old_items_list.end(); ++it) {
00424         InsertItem (*it);
00425     }
00426 }
00427 
00428 template <class T, int DIMENSIONS>
00429 void Node<T, DIMENSIONS>::Merge () {
00430     assert (has_children_);
00431     if (   !low_child_->has_children_
00432         && !high_child_->has_children_
00433          && (items_.size ()
00434              + low_child_->items_.size ()
00435              + high_child_->items_.size ()
00436                < tree_->max_elements_per_leaf () )) {
00437         for (typename std::list<Item<T, DIMENSIONS> *>::iterator it
00438                 = low_child_->items_.begin(); it != low_child_->items_.end();
00439                 ++it) {
00440             items_.push_back (*it);
00441             (*it)->set_container_node (this);
00442         }
00443         for (typename std::list<Item<T, DIMENSIONS> *>::iterator it
00444                 = high_child_->items_.begin(); it != high_child_->items_.end();
00445                 ++it) {
00446             items_.push_back (*it);
00447             (*it)->set_container_node (this);
00448         }
00449         delete low_child_;
00450         low_child_ = NULL;
00451         delete high_child_;
00452         high_child_ = NULL;
00453         has_children_ = false;
00454         if (parent_)
00455             parent_->Merge();
00456     }
00457 }
00458 
00459 template <class T, int DIMENSIONS>
00460 void Node<T, DIMENSIONS>::Clear () {
00461     if (has_children_) {
00462         low_child_->Clear ();
00463         high_child_->Clear ();
00464         delete low_child_;
00465         low_child_ = NULL;
00466         delete high_child_;
00467         high_child_ = NULL;
00468     }
00469     for (typename std::list<Item<T, DIMENSIONS> *>::iterator it
00470                 = items_.begin(); it != items_.end(); ++it) {
00471         delete *it;
00472     }
00473 }
00474 
00475 #ifdef DEBUG
00476 template <class T, int DIMENSIONS>
00477 void Node<T, DIMENSIONS>::PrintTreeRootedAtThisNode () {
00478     if (has_children_) {
00479         high_child_->PrintTreeRootedAtThisNode ();
00480     }
00481     for (int i = 0; i < depth_; ++i) {
00482         std::cout << "\t";
00483     }
00484     int i = 0;
00485     for (typename std::list<Item<T, DIMENSIONS> *>::iterator it
00486             = items_.begin(); it != items_.end(); ++it, ++i) {
00487         std::cout << "[" << i << "] = ";
00488         (*it)->Print ();
00489         std::cout << "; ";
00490     }
00491     std::cout << std::endl;
00492     if (has_children_) {
00493         low_child_->PrintTreeRootedAtThisNode ();
00494     }
00495 }
00496 #endif
00497 
00498 } // namespace ikdtree
00499 
00500 } // namespace ugdk
00501 
00502 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines