// Copyright (c) 2002,2011 Utrecht University (The Netherlands). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // You can redistribute it and/or modify it under the terms of the GNU // General Public License as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // // // Authors : Hans Tangelder () #ifndef CGAL_KD_TREE_NODE_H #define CGAL_KD_TREE_NODE_H #include #include namespace CGAL { template class Kd_tree; template < class TreeTraits, class Splitter, class UseExtendedNode > class Kd_tree_node { friend class Kd_tree; typedef typename Kd_tree::Node_handle Node_handle; typedef typename Kd_tree::Node_const_handle Node_const_handle; typedef typename Kd_tree::Internal_node_handle Internal_node_handle; typedef typename Kd_tree::Internal_node_const_handle Internal_node_const_handle; typedef typename Kd_tree::Leaf_node_handle Leaf_node_handle; typedef typename Kd_tree::Leaf_node_const_handle Leaf_node_const_handle; typedef typename TreeTraits::Point_d Point_d; typedef typename TreeTraits::FT FT; typedef typename Kd_tree::Separator Separator; typedef typename Kd_tree::Point_d_iterator Point_d_iterator; typedef typename Kd_tree::D D; bool leaf; public : Kd_tree_node(bool leaf_) :leaf(leaf_){} bool is_leaf() const{ return leaf; } std::size_t num_items() const { if (is_leaf()){ Leaf_node_const_handle node = static_cast(this); return node->size(); } else { Internal_node_const_handle node = static_cast(this); return node->lower()->num_items() + node->upper()->num_items(); } } std::size_t num_nodes() const { if (is_leaf()) return 1; else { Internal_node_const_handle node = static_cast(this); return node->lower()->num_nodes() + node->upper()->num_nodes(); } } int depth(const int current_max_depth) const { if (is_leaf()){ return current_max_depth; } else { Internal_node_const_handle node = static_cast(this); return (std::max)( node->lower()->depth(current_max_depth + 1), node->upper()->depth(current_max_depth + 1)); } } int depth() const { return depth(1); } template OutputIterator tree_items(OutputIterator it) const { if (is_leaf()) { Leaf_node_const_handle node = static_cast(this); if (node->size()>0) for (Point_d_iterator i=node->begin(); i != node->end(); i++) {*it=**i; ++it;} } else { Internal_node_const_handle node = static_cast(this); it=node->lower()->tree_items(it); it=node->upper()->tree_items(it); } return it; } void indent(int d) const { for(int i = 0; i < d; i++){ std::cout << " "; } } void print(int d = 0) const { if (is_leaf()) { Leaf_node_const_handle node = static_cast(this); indent(d); std::cout << "leaf" << std::endl; if (n>0) for (Point_d_iterator i=node->begin(); i != node->end(); i++) {indent(d);std::cout << **i << std::endl;} } else { Internal_node_const_handle node = static_cast(this); indent(d); std::cout << "lower tree" << std::endl; node->lower()->print(d+1); indent(d); std::cout << "separator: dim = " << node->cutting_dimension() << " val = " << node->cutting_value() << std::endl; indent(d); std::cout << "upper tree" << std::endl; node->upper()->print(d+1); } } template OutputIterator search(OutputIterator it, const FuzzyQueryItem& q, Kd_tree_rectangle& b) const { if (is_leaf()) { Leaf_node_const_handle node = static_cast(this); if (node->size()>0) for (Point_d_iterator i=node->begin(); i != node->end(); i++) if (q.contains(**i)) {*it=**i; ++it;} } else { Internal_node_const_handle node = static_cast(this); // after splitting b denotes the lower part of b Kd_tree_rectangle b_upper(b); b.split(b_upper, node->cutting_dimension(), node->cutting_value()); if (q.outer_range_contains(b)) it=node->lower()->tree_items(it); else if (q.inner_range_intersects(b)) it=node->lower()->search(it,q,b); if (q.outer_range_contains(b_upper)) it=node->upper()->tree_items(it); else if (q.inner_range_intersects(b_upper)) it=node->upper()->search(it,q,b_upper); }; return it; } }; template < class TreeTraits, class Splitter, class UseExtendedNode > class Kd_tree_leaf_node : public Kd_tree_node< TreeTraits, Splitter, UseExtendedNode >{ friend class Kd_tree; typedef typename TreeTraits::FT FT; typedef typename Kd_tree::Point_d_iterator Point_d_iterator; private: // private variables for leaf nodes unsigned int n; // denotes number of items in a leaf node Point_d_iterator data; // iterator to data in leaf node public: // default constructor Kd_tree_leaf_node() {} Kd_tree_leaf_node(bool leaf_ ) : leaf(leaf_) {} Kd_tree_leaf_node(bool leaf_,unsigned int n_ ) : Kd_tree_node(leaf_), n(n_) {} // members for all nodes // members for leaf nodes only inline unsigned int size() const { return n; } inline Point_d_iterator begin() const { return data; } inline Point_d_iterator end() const { return data + n; } }; //leaf node template < class TreeTraits, class Splitter, class UseExtendedNode > class Kd_tree_internal_node : public Kd_tree_node< TreeTraits, Splitter, UseExtendedNode >{ friend class Kd_tree; typedef typename Kd_tree::Node_handle Node_handle; typedef typename Kd_tree::Node_const_handle Node_const_handle; typedef typename TreeTraits::Point_d Point_d; typedef typename TreeTraits::FT FT; typedef typename Kd_tree::Separator Separator; typedef typename Kd_tree::Point_d_iterator Point_d_iterator; private: // private variables for internal nodes Node_handle lower_ch, upper_ch; Separator sep; // private variables for extended internal nodes FT low_val; FT high_val; public: // default constructor Kd_tree_internal_node() {} Kd_tree_internal_node(bool leaf_) : Kd_tree_node(leaf_) {} // members for internal node and extended internal node inline Node_const_handle lower() const { return lower_ch; } inline Node_const_handle upper() const { return upper_ch; } inline Node_handle lower() { return lower_ch; } inline Node_handle upper() { return upper_ch; } // inline Separator& separator() {return sep; } // use instead inline FT cutting_value() const { return sep.cutting_value(); } inline int cutting_dimension() const { return sep.cutting_dimension(); } // members for extended internal node only inline FT low_value() const { return low_val; } inline FT high_value() const { return high_val; } Separator& separator() { return sep; } };//internal node } // namespace CGAL #endif // CGAL_KDTREE_NODE_H