cgal/Spatial_searching/include/CGAL/Kd_tree_node.h

364 lines
9.0 KiB
C++

// 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 (<hanst@cs.uu.nl>)
#ifndef CGAL_KD_TREE_NODE_H
#define CGAL_KD_TREE_NODE_H
#include <CGAL/Splitters.h>
#include <CGAL/Compact_container.h>
namespace CGAL {
template <class SearchTraits, class Splitter, class UseExtendedNode>
class Kd_tree;
template < class TreeTraits, class Splitter, class UseExtendedNode >
class Kd_tree_node {
friend class Kd_tree<TreeTraits,Splitter,UseExtendedNode>;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Node_handle Node_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Node_const_handle Node_const_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Internal_node_handle Internal_node_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Internal_node_const_handle Internal_node_const_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Leaf_node_handle Leaf_node_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Leaf_node_const_handle Leaf_node_const_handle;
typedef typename TreeTraits::Point_d Point_d;
typedef typename TreeTraits::FT FT;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Separator Separator;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Point_d_iterator Point_d_iterator;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::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<Leaf_node_const_handle>(this);
return node->size();
}
else {
Internal_node_const_handle node =
static_cast<Internal_node_const_handle>(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<Internal_node_const_handle>(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<Internal_node_const_handle>(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 <class OutputIterator>
OutputIterator
tree_items(OutputIterator it) const {
if (is_leaf()) {
Leaf_node_const_handle node =
static_cast<Leaf_node_const_handle>(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<Internal_node_const_handle>(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<Leaf_node_const_handle>(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<Internal_node_const_handle>(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 <class OutputIterator, class FuzzyQueryItem>
OutputIterator
search(OutputIterator it, const FuzzyQueryItem& q,
Kd_tree_rectangle<FT,D>& b) const
{
if (is_leaf()) {
Leaf_node_const_handle node =
static_cast<Leaf_node_const_handle>(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<Internal_node_const_handle>(this);
// after splitting b denotes the lower part of b
Kd_tree_rectangle<FT,D> 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<TreeTraits,Splitter,UseExtendedNode>;
typedef typename TreeTraits::FT FT;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::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<TreeTraits,Splitter,UseExtendedNode>;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Node_handle Node_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Node_const_handle Node_const_handle;
typedef typename TreeTraits::Point_d Point_d;
typedef typename TreeTraits::FT FT;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Separator Separator;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::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