UGDK
|
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