degate 0.1.1
QuadTree.h
Go to the documentation of this file.
00001 /* -*-c++-*-
00002 
00003    This file is part of the IC reverse engineering tool degate.
00004 
00005    Copyright 2008, 2009, 2010 by Martin Schobert
00006 
00007    Degate is free software: you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation, either version 3 of the License, or
00010    any later version.
00011 
00012    Degate is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with degate. If not, see <http://www.gnu.org/licenses/>.
00019 
00020 */
00021 
00022 
00023 #ifndef __QUADTREE_H__
00024 #define __QUADTREE_H__
00025 
00026 #include "Rectangle.h"
00027 #include "TypeTraits.h"
00028 
00029 #include <vector>
00030 #include <list>
00031 #include <assert.h>
00032 #include "globals.h"
00033 #include <iostream>
00034 
00035 namespace degate {
00036 
00037 
00038   template<bool b>
00039   struct get_bbox_trait_selector {
00040     template<typename T>
00041     static BoundingBox const & get_bounding_box_for_object(T object) {
00042       return object.get_bounding_box();
00043     }
00044   };
00045 
00046   template <>
00047   struct get_bbox_trait_selector<true> {
00048     template<typename T>
00049     static BoundingBox const & get_bounding_box_for_object(T object) {
00050       return object->get_bounding_box();
00051     }
00052   };
00053 
00054 
00055   template <typename T> class QuadTree;
00056 }
00057 
00058 //#include "QuadTreeDownIterator.h"
00059 #include "QuadTreeRegionIterator.h"
00060 
00061 namespace degate {
00062 
00063   /**
00064    * Quad tree to store objects and to accesss them with a two dimensional access path.
00065    */
00066   template <typename T>
00067   class QuadTree {
00068 
00069     friend class region_iterator<T>;
00070     //    friend class down_iterator<T>;
00071 
00072   private:
00073 
00074     const static int NW = 0;
00075     const static int NE = 1;
00076     const static int SW = 2;
00077     const static int SE = 3;
00078 
00079     const static unsigned int bbox_min_size = 10;
00080 
00081     unsigned int max_entries;
00082 
00083     BoundingBox box;
00084     std::vector<QuadTree<T> > subtree_nodes;
00085     std::list<T> children;
00086 
00087     QuadTree * parent;
00088 
00089     std::string node_name;
00090 
00091     QuadTree(BoundingBox const & box, QuadTree * parent, std::string node_name, int max_entries = 50);
00092 
00093     QuadTree<T> * traverse_downto_bounding_box(BoundingBox const & box);
00094 
00095     ret_t split();
00096     ret_t reinsert_objects();
00097 
00098     bool is_splitable() const;
00099 
00100   public:
00101 
00102     const std::string get_name() const { return node_name; }
00103 
00104     /**
00105      * Create a new quadtree.
00106      * @param box The bounding box defines the dimension of the quadtree.
00107      * @param max_entries Defines how many objects should be stored in a quadtree node, before
00108      *    the node is splitted. This value is not a hard limit. The quadtree can ignore this
00109      *    parameter, if it has no choice.
00110      */
00111 
00112     QuadTree(BoundingBox const & box, int max_entries = 50);
00113 
00114     /**
00115      * Destruct a quadtree.
00116      */
00117 
00118     ~QuadTree();
00119 
00120     /**
00121      * Check if the quadtree or a quadtree node is a leaf node.
00122      */
00123 
00124     bool is_leave() const;
00125 
00126     /**
00127      * Insert an object into the quadtree.
00128      */
00129 
00130     ret_t insert(T object);
00131 
00132     /**
00133      * Remove an object from the quadtree.
00134      */
00135 
00136     ret_t remove(T object);
00137 
00138 
00139     /**
00140      * Notify that the bounding box of an object changed.
00141      * It might be neccessary to adjust the objects position in the quadtree.
00142      */
00143 
00144     void notify_shape_change(T object);
00145 
00146     /**
00147      * Get the number of objects that are stored in a quadtree node and in all child nodes.
00148      */
00149 
00150     unsigned int total_size() const;
00151 
00152     /**
00153      * Get the number of layers, that quadtree has.
00154      */
00155 
00156     unsigned int depth() const;
00157 
00158     /*
00159      * Check if there are objects stored in the quadtree.
00160      */
00161 
00162     bool is_empty() const { return total_size() == 0; }
00163 
00164     /**
00165      * Get the dimension of the quadtree.
00166      */
00167 
00168     unsigned int get_width() const;
00169 
00170     /**
00171      * Get the dimension of the quadtree.
00172      */
00173 
00174     unsigned int get_height() const;
00175 
00176 
00177     /**
00178      * Get an interator to iterate over quadtree nodes down to the leafes.
00179      */
00180 
00181     //    down_iterator<T> down_iter_begin();
00182 
00183     /**
00184      * Get an end marker for the iteration
00185      * @see down_iter_begin()
00186      */
00187 
00188     //    down_iterator<T> down_iter_end();
00189 
00190     /**
00191      * Get a region iterator to iterate over quatree objects.
00192      */
00193 
00194 
00195     region_iterator<T> region_iter_begin(int min_x, int max_x, int min_y, int max_y);
00196 
00197     /**
00198      * Get a region iterator to iterate over quatree objects.
00199      */
00200 
00201     region_iterator<T> region_iter_begin(BoundingBox const & bbox);
00202 
00203     /**
00204      * Get a region iterator to iterate over the complete quatree.
00205      */
00206 
00207     region_iterator<T> region_iter_begin();
00208 
00209     /**
00210      * Get an end marker for the region iteration.
00211      */
00212 
00213     region_iterator<T> region_iter_end();
00214 
00215 
00216     /**
00217      * Get the bounding box for a quad tree layer.
00218      */
00219     BoundingBox const& get_bounding_box() const;
00220       
00221     /**
00222      * Print the quadtree.
00223      */
00224     void print(std::ostream & os = std::cout, int tabs = 0, bool recursive = false);
00225 
00226   };
00227 
00228 
00229 
00230 
00231   template <typename T>
00232   QuadTree<T>::QuadTree(BoundingBox const & box, int max_entries) {
00233     this->box = box;
00234     this->max_entries = max_entries;
00235     parent = NULL;
00236     node_name = "/";
00237   }
00238 
00239   template <typename T>
00240   QuadTree<T>::QuadTree(BoundingBox const & box, QuadTree * parent, std::string _node_name, int max_entries) {
00241     this->box = box;
00242     this->max_entries = max_entries;
00243     this->parent = parent;
00244 
00245     node_name = parent->node_name + std::string("/") + _node_name;
00246   }
00247 
00248   template <typename T>
00249   QuadTree<T>::~QuadTree() {
00250   }
00251 
00252   template <typename T>
00253   unsigned int QuadTree<T>::get_width() const {
00254     return box.get_width();
00255   }
00256 
00257   template <typename T>
00258   unsigned int QuadTree<T>::get_height() const {
00259     return box.get_height();
00260   }
00261 
00262 
00263   template <typename T>
00264   bool QuadTree<T>::is_splitable() const {
00265     return box.get_width() > bbox_min_size &&
00266       box.get_height() > bbox_min_size &&
00267       is_leave();
00268   }
00269 
00270   template <typename T>
00271   ret_t QuadTree<T>::split() {
00272     if(is_splitable()) {
00273 
00274       BoundingBox nw(box.get_min_x(), box.get_center_x(),
00275                      box.get_min_y(), box.get_center_y());
00276 
00277 
00278       BoundingBox sw(box.get_min_x(), box.get_center_x(),
00279                      box.get_center_y() + 1, box.get_max_y());
00280 
00281 
00282       BoundingBox ne(box.get_center_x() + 1, box.get_max_x(),
00283                      box.get_min_y(), box.get_center_y());
00284 
00285 
00286       BoundingBox se(box.get_center_x() + 1, box.get_max_x(),
00287                      box.get_center_y() + 1,  box.get_max_y());
00288 
00289 
00290       QuadTree<T> node_nw(nw, this, "NW", max_entries);
00291       QuadTree<T> node_ne(ne, this, "NE", max_entries);
00292       QuadTree<T> node_sw(sw, this, "SW", max_entries);
00293       QuadTree<T> node_se(se, this, "SE", max_entries);
00294 
00295 
00296       subtree_nodes.push_back(node_nw);
00297       subtree_nodes.push_back(node_ne);
00298       subtree_nodes.push_back(node_sw);
00299       subtree_nodes.push_back(node_se);
00300 
00301       return RET_OK;
00302     }
00303 
00304     debug(TM, "Failed to split a quadtree node of width %d and height %d that is %sa leave",
00305           box.get_width(),
00306           box.get_height(),
00307           is_leave() ? "" : "not ");
00308     assert(1 == 0);
00309     return RET_ERR;
00310   }
00311 
00312   template <typename T>
00313   ret_t QuadTree<T>::reinsert_objects() {
00314 
00315     typename std::list<T> children_copy = children;
00316 
00317     children.clear();
00318 
00319     for(typename std::list<T>::iterator it = children_copy.begin();
00320         it != children_copy.end();
00321         ++it) {
00322       insert(*it);
00323     }
00324 
00325     return RET_OK;
00326   }
00327 
00328   template <typename T>
00329   ret_t QuadTree<T>::insert(T object) {
00330 
00331     ret_t ret;
00332     const BoundingBox & bbox =
00333       get_bbox_trait_selector<is_pointer<T>::value>::get_bounding_box_for_object(object);
00334 
00335     QuadTree<T> * found = traverse_downto_bounding_box(bbox);
00336     assert(found != NULL);
00337 
00338     if(found != NULL) {
00339 
00340       if((found->children.size() >= max_entries) && found->is_splitable()) {
00341 
00342         if(RET_IS_NOT_OK(ret = found->split())) return ret;
00343         if(RET_IS_NOT_OK(ret = found->reinsert_objects())) return ret;
00344         if(RET_IS_NOT_OK(ret = found->insert(object))) return ret;
00345         return RET_OK;
00346       }
00347       else {
00348         found->children.push_back(object);
00349         return RET_OK;
00350       }
00351     }
00352     return RET_ERR;
00353   }
00354 
00355   template <typename T>
00356   void QuadTree<T>::notify_shape_change(T object) {
00357     remove(object);
00358     insert(object);
00359   }
00360 
00361   template <typename T>
00362   ret_t QuadTree<T>::remove(T object) {
00363     const BoundingBox & bbox =
00364       get_bbox_trait_selector<is_pointer<T>::value>::get_bounding_box_for_object(object);
00365 
00366     QuadTree<T> * found = traverse_downto_bounding_box(bbox);
00367     assert(found != NULL);
00368     if(found != NULL) {
00369       found->children.remove(object);
00370 
00371       if(!found->is_leave() &&
00372          found->subtree_nodes[NW].children.size() == 0 &&
00373          found->subtree_nodes[NE].children.size() == 0 &&
00374          found->subtree_nodes[SW].children.size() == 0 &&
00375          found->subtree_nodes[SE].children.size() == 0) {
00376         found->subtree_nodes.clear();
00377       }
00378 
00379       return RET_OK;
00380     }
00381     return RET_ERR;
00382   }
00383 
00384 
00385   template <typename T>
00386   bool QuadTree<T>::is_leave() const {
00387     return subtree_nodes.size() == 4 ? false : true;
00388   }
00389 
00390   template <typename T>
00391   QuadTree<T> * QuadTree<T>::traverse_downto_bounding_box(BoundingBox const & box) {
00392 
00393     if(is_leave()) return this;
00394 
00395     for(typename std::vector< QuadTree<T> >::iterator it = subtree_nodes.begin();
00396         it != subtree_nodes.end();
00397         ++it) {
00398 
00399       const BoundingBox & sub_bbox = (*it).box.get_bounding_box();
00400 
00401       //if(sub_bbox.in_bounding_box(box)) { // sub_bbox within box?
00402         if(box.in_bounding_box(sub_bbox)) { // box within sub_bbox?
00403         return (*it).traverse_downto_bounding_box(box);
00404       }
00405     }
00406     //    assert(1 == 0);
00407     return this;
00408   }
00409 
00410   template <typename T>
00411   unsigned int QuadTree<T>::total_size() const {
00412     unsigned int this_node = children.size();
00413     unsigned int sub_nodes = 0;
00414     if(!is_leave()) {
00415       for(typename std::vector< QuadTree<T> >::const_iterator it = subtree_nodes.begin();
00416           it != subtree_nodes.end();
00417           ++it) {
00418         sub_nodes += (*it).total_size();
00419       }
00420     }
00421     return this_node + sub_nodes;
00422   }
00423 
00424   template <typename T>
00425   unsigned int QuadTree<T>::depth() const {
00426 
00427     unsigned int max_d = 0;
00428     if(!is_leave()) {
00429       for(typename std::vector< QuadTree<T> >::const_iterator it = subtree_nodes.begin();
00430           it != subtree_nodes.end();
00431           ++it) {
00432 
00433         unsigned int d = (*it).depth();
00434         max_d = std::max(max_d, d);
00435       }
00436     }
00437     return 1 + max_d;
00438   }
00439 
00440 
00441   /*
00442   template <typename T>
00443   down_iterator<T> QuadTree<T>::down_iter_begin() {
00444     return down_iterator<T>(this);
00445   }
00446 
00447   template <typename T>
00448   down_iterator<T> QuadTree<T>::down_iter_end() {
00449     return down_iterator<T>();
00450   }
00451   */
00452 
00453   template <typename T>
00454   region_iterator<T> QuadTree<T>::region_iter_begin(int min_x, int max_x, int min_y, int max_y) {
00455 
00456     BoundingBox bbox(min_x, max_x, min_y, max_y);
00457     return region_iter_begin(bbox);
00458   }
00459 
00460   template <typename T>
00461   region_iterator<T> QuadTree<T>::region_iter_begin(BoundingBox const & bbox) {
00462     return region_iterator<T>(this, bbox);
00463   }
00464 
00465   template <typename T>
00466   region_iterator<T> QuadTree<T>::region_iter_begin() {
00467     return region_iterator<T>(this, box);
00468   }
00469 
00470   template <typename T>
00471   region_iterator<T> QuadTree<T>::region_iter_end() {
00472     return region_iterator<T>();
00473   }
00474 
00475 
00476   template <typename T>
00477   BoundingBox const& QuadTree<T>::get_bounding_box() const {
00478     return box;
00479   }
00480 
00481   template <typename T>
00482   void QuadTree<T>::print(std::ostream & os, int tabs, bool recursive) {
00483 
00484     os
00485       << gen_tabs(tabs) << "Node name                      : " << get_name() << std::endl
00486       << gen_tabs(tabs) << "Bounding box                   : x = "
00487       << box.get_min_x() << " .. " << box.get_max_x()
00488       << " / y = "
00489       << box.get_min_y() << " .. " << box.get_max_y()
00490       << std::endl
00491 
00492       << gen_tabs(tabs) << "Num elements in this node      : " << children.size() << std::endl
00493       << gen_tabs(tabs) << "Preferred max num of elements : " << max_entries << std::endl
00494       << std::endl
00495       ;
00496 
00497     if(parent == NULL /* || children.size() < 5 */ ) {
00498 
00499       for(typename std::list<T>::iterator c_iter = children.begin();
00500           c_iter != children.end(); ++c_iter) {
00501 
00502         const BoundingBox & e_bb =
00503           get_bbox_trait_selector<is_pointer<T>::value>::get_bounding_box_for_object(*c_iter);
00504 
00505         os
00506           << gen_tabs(tabs) << "    + Element bounding box           : x = "
00507           << e_bb.get_min_x() << " .. " << e_bb.get_max_x()
00508           << " / y = "
00509           << e_bb.get_min_y() << " .. " << e_bb.get_max_y()
00510           << std::endl;
00511       }
00512 
00513       os << std::endl;
00514     }
00515 
00516     if(recursive) {
00517       for(typename std::vector<QuadTree<T> >::iterator stn_iter = subtree_nodes.begin();
00518           stn_iter != subtree_nodes.end(); ++stn_iter) {
00519         (*stn_iter).print(os, tabs+1);
00520       }
00521     }
00522 
00523 
00524   }
00525 
00526   /* missing:
00527      - get object(s) at
00528      - find object (?)
00529   */
00530 
00531 }
00532 
00533 #endif