BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Kd_tree.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines