BWAPI
|
00001 // Copyright (c) 2002 Utrecht University (The Netherlands). 00002 // All rights reserved. 00003 // 00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under 00005 // the terms of the Q Public License version 1.0. 00006 // See the file LICENSE.QPL distributed with CGAL. 00007 // 00008 // Licensees holding a valid commercial license may use this file in 00009 // accordance with the commercial license agreement provided with the software. 00010 // 00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00013 // 00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Spatial_searching/include/CGAL/Kd_tree.h $ 00015 // $Id: Kd_tree.h 40677 2007-10-20 20:51:59Z spion $ 00016 // 00017 // 00018 // Author(s) : Hans Tangelder (<hanst@cs.uu.nl>) 00019 00020 #ifndef CGAL_KD_TREE_H 00021 #define CGAL_KD_TREE_H 00022 00023 #include <CGAL/basic.h> 00024 #include <CGAL/assertions.h> 00025 #include <vector> 00026 00027 #include <CGAL/algorithm.h> 00028 #include <CGAL/Kd_tree_node.h> 00029 #include <CGAL/Splitters.h> 00030 #include <CGAL/Compact_container.h> 00031 00032 00033 namespace CGAL { 00034 00035 //template <class SearchTraits, class Splitter_=Median_of_rectangle<SearchTraits>, class UseExtendedNode = Tag_true > 00036 template <class SearchTraits, class Splitter_=Sliding_midpoint<SearchTraits>, class UseExtendedNode = Tag_true > 00037 class Kd_tree { 00038 00039 public: 00040 00041 typedef Splitter_ Splitter; 00042 typedef typename SearchTraits::Point_d Point_d; 00043 typedef typename Splitter::Container Point_container; 00044 00045 typedef typename SearchTraits::FT FT; 00046 typedef Kd_tree_node<SearchTraits, Splitter, UseExtendedNode > Node; 00047 typedef Kd_tree<SearchTraits, Splitter> Tree; 00048 00049 typedef typename Compact_container<Node>::iterator Node_handle; 00050 typedef typename std::vector<Point_d*>::iterator Point_d_iterator; 00051 typedef typename Splitter::Separator Separator; 00052 typedef typename std::vector<Point_d>::const_iterator iterator; 00053 00054 private: 00055 00056 mutable Splitter split; 00057 mutable Compact_container<Node> nodes; 00058 00059 mutable Node_handle tree_root; 00060 00061 mutable Kd_tree_rectangle<SearchTraits>* bbox; 00062 mutable std::vector<Point_d> pts; 00063 00064 // Instead of storing the points in arrays in the Kd_tree_node 00065 // we put all the data in a vector in the Kd_tree. 00066 // and we only store an iterator range in the Kd_tree_node. 00067 // 00068 mutable std::vector<Point_d*> data; 00069 SearchTraits tr; 00070 00071 00072 mutable bool built_; 00073 00074 // protected copy constructor 00075 Kd_tree(const Tree& tree) 00076 : built_(tree.built_) 00077 {}; 00078 00079 00080 // Instead of the recursive construction of the tree in the class Kd_tree_node 00081 // we do this in the tree class. The advantage is that we then can optimize 00082 // the allocation of the nodes. 00083 00084 // The leaf node 00085 Node_handle 00086 create_leaf_node(Point_container& c) const 00087 { 00088 Node_handle nh = nodes.emplace(c.size(), Node::LEAF); 00089 00090 nh->data = c.begin(); 00091 return nh; 00092 } 00093 00094 00095 // The internal node 00096 00097 Node_handle 00098 create_internal_node(Point_container& c, const Tag_true&) const 00099 { 00100 return create_internal_node_use_extension(c); 00101 } 00102 00103 Node_handle 00104 create_internal_node(Point_container& c, const Tag_false&) const 00105 { 00106 return create_internal_node(c); 00107 } 00108 00109 00110 00111 // TODO: Similiar to the leaf_init function above, a part of the code should be 00112 // moved to a the class Kd_tree_node. 00113 // It is not proper yet, but the goal was to see if there is 00114 // a potential performance gain through the Compact_container 00115 Node_handle 00116 create_internal_node_use_extension(Point_container& c) const 00117 { 00118 Node_handle nh = nodes.emplace(Node::EXTENDED_INTERNAL); 00119 00120 Point_container c_low(c.dimension()); 00121 split(nh->separator(), c, c_low); 00122 00123 int cd = nh->separator().cutting_dimension(); 00124 00125 nh->low_val = c_low.bounding_box().min_coord(cd); 00126 nh->high_val = c.bounding_box().max_coord(cd); 00127 00128 CGAL_assertion(nh->separator().cutting_value() >= nh->low_val); 00129 CGAL_assertion(nh->separator().cutting_value() <= nh->high_val); 00130 00131 if (c_low.size() > split.bucket_size()){ 00132 nh->lower_ch = create_internal_node_use_extension(c_low); 00133 }else{ 00134 nh->lower_ch = create_leaf_node(c_low); 00135 } 00136 if (c.size() > split.bucket_size()){ 00137 nh->upper_ch = create_internal_node_use_extension(c); 00138 }else{ 00139 nh->upper_ch = create_leaf_node(c); 00140 } 00141 00142 return nh; 00143 } 00144 00145 00146 // Note also that I duplicated the code to get rid if the if's for 00147 // the boolean use_extension which was constant over the construction 00148 Node_handle 00149 create_internal_node(Point_container& c) const 00150 { 00151 Node_handle nh = nodes.emplace(Node::INTERNAL); 00152 00153 Point_container c_low(c.dimension()); 00154 split(nh->separator(), c, c_low); 00155 00156 if (c_low.size() > split.bucket_size()){ 00157 nh->lower_ch = create_internal_node(c_low); 00158 }else{ 00159 nh->lower_ch = create_leaf_node(c_low); 00160 } 00161 if (c.size() > split.bucket_size()){ 00162 nh->upper_ch = create_internal_node(c); 00163 }else{ 00164 nh->upper_ch = create_leaf_node(c); 00165 } 00166 return nh; 00167 } 00168 00169 00170 00171 public: 00172 00173 Kd_tree(Splitter s = Splitter()) 00174 : split(s), built_(false) 00175 {} 00176 00177 template <class InputIterator> 00178 Kd_tree(InputIterator first, InputIterator beyond, 00179 Splitter s = Splitter()) 00180 : split(s), built_(false) 00181 { 00182 std::copy(first, beyond, std::back_inserter(pts)); 00183 } 00184 00185 void 00186 build() const 00187 { 00188 const Point_d& p = *pts.begin(); 00189 typename SearchTraits::Construct_cartesian_const_iterator_d ccci; 00190 int dim = std::distance(ccci(p), ccci(p,0)); 00191 00192 data.reserve(pts.size()); 00193 for(unsigned int i = 0; i < pts.size(); i++){ 00194 data.push_back(&pts[i]); 00195 } 00196 Point_container c(dim, data.begin(), data.end()); 00197 bbox = new Kd_tree_rectangle<SearchTraits>(c.bounding_box()); 00198 if (c.size() <= split.bucket_size()){ 00199 tree_root = create_leaf_node(c); 00200 }else { 00201 tree_root = create_internal_node(c, UseExtendedNode()); 00202 } 00203 built_ = true; 00204 } 00205 00206 bool is_built() const 00207 { 00208 return built_; 00209 } 00210 00211 void invalidate_built() 00212 { 00213 if(is_built()){ 00214 nodes.clear(); 00215 data.clear(); 00216 delete bbox; 00217 built_ = false; 00218 } 00219 } 00220 00221 void 00222 insert(const Point_d& p) 00223 { 00224 invalidate_built(); 00225 pts.push_back(p); 00226 } 00227 00228 template <class InputIterator> 00229 void 00230 insert(InputIterator first, InputIterator beyond) 00231 { 00232 invalidate_built(); 00233 std::copy(first, beyond, std::back_inserter(pts)); 00234 } 00235 00236 00237 template <class OutputIterator, class FuzzyQueryItem> 00238 OutputIterator 00239 search(OutputIterator it, const FuzzyQueryItem& q) 00240 { 00241 if(! pts.empty()){ 00242 00243 if(! is_built()){ 00244 build(); 00245 } 00246 Kd_tree_rectangle<SearchTraits> b(*bbox); 00247 tree_root->search(it,q,b); 00248 } 00249 return it; 00250 } 00251 00252 ~Kd_tree() { 00253 if(is_built()){ 00254 delete bbox; 00255 } 00256 } 00257 00258 00259 SearchTraits 00260 traits() const 00261 { 00262 return tr; 00263 } 00264 00265 Node_handle 00266 root() const 00267 { 00268 if(! is_built()){ 00269 build(); 00270 } 00271 return tree_root; 00272 } 00273 00274 void 00275 print() const 00276 { 00277 if(! is_built()){ 00278 build(); 00279 } 00280 root()->print(); 00281 } 00282 00283 const Kd_tree_rectangle<SearchTraits>& 00284 bounding_box() const 00285 { 00286 if(! is_built()){ 00287 build(); 00288 } 00289 return *bbox; 00290 } 00291 00292 iterator 00293 begin() const 00294 { 00295 return pts.begin(); 00296 } 00297 00298 iterator 00299 end() const 00300 { 00301 return pts.end(); 00302 } 00303 00304 int 00305 size() const 00306 { 00307 return pts.size(); 00308 } 00309 00310 // Print statistics of the tree. 00311 std::ostream& 00312 statistics(std::ostream& s) 00313 { 00314 if(! is_built()){ 00315 build(); 00316 } 00317 s << "Tree statistics:" << std::endl; 00318 s << "Number of items stored: " 00319 << tree_root->num_items() << std::endl; 00320 s << "Number of nodes: " 00321 << tree_root->num_nodes() << std::endl; 00322 s << " Tree depth: " << tree_root->depth() << std::endl; 00323 return s; 00324 } 00325 00326 00327 }; 00328 00329 } // namespace CGAL 00330 00331 #endif // CGAL_KD_TREE_H