|
degate 0.1.1
|
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
1.7.4