52 #ifndef __PCL_KDTree_h
53 #define __PCL_KDTree_h
169 Build( points, bucketCapacity );
193 Build( points, dimension, bucketCapacity );
215 , m_dimension( x.m_dimension )
216 , m_bucketCapacity( x.m_bucketCapacity )
217 , m_length( x.m_length )
230 DestroyTree( m_root );
232 m_dimension = x.m_dimension;
233 m_bucketCapacity = x.m_bucketCapacity;
234 m_length = x.m_length;
254 DestroyTree( m_root );
283 m_bucketCapacity =
Max( 1, bucketCapacity );
286 m_dimension = points[0].
Length();
287 if ( m_dimension < 1 )
288 throw Error(
"KDTree::Build(): Invalid point space dimension." );
289 m_root = BuildTree( points, 0 );
318 m_bucketCapacity =
Max( 1, bucketCapacity );
319 if ( (m_dimension = dimension) < 1 )
320 throw Error(
"KDTree::Build(): Invalid point space dimension." );
321 m_root = BuildTree( points, 0 );
349 for (
int i = 0; i < m_dimension; ++i )
351 p0[i] = pt[i] - epsilon;
352 p1[i] = pt[i] + epsilon;
355 SearchTree( found, p0, p1, m_root, 0 );
394 for (
int i = 0; i < m_dimension; ++i )
396 p0[i] = pt[i] - epsilon;
397 p1[i] = pt[i] + epsilon;
399 SearchTree( p0, p1, callback, data, m_root, 0 );
424 return m_root ==
nullptr;
433 pcl::Swap( x1.m_dimension, x2.m_dimension );
434 pcl::Swap( x1.m_bucketCapacity, x2.m_bucketCapacity );
443 Node* left =
nullptr;
444 Node* right =
nullptr;
453 return left ==
nullptr && right ==
nullptr;
457 struct LeafNode :
public Node
461 LeafNode(
const point_list& p )
467 Node* m_root =
nullptr;
469 int m_bucketCapacity = 0;
472 LeafNode* NewLeafNode(
const point_list& points )
474 m_length += points.Length();
475 return new LeafNode( points );
478 Node* BuildTree(
const point_list& points,
int depth )
480 if ( points.IsEmpty() )
483 if ( points.Length() <=
size_type( m_bucketCapacity ) )
484 return NewLeafNode( points );
486 int index = depth % m_dimension;
488 Node* node =
new Node( SplitValue( points, index ) );
490 point_list left, right;
491 for (
const point& p : points )
492 if ( p[index] <= node->split )
499 if ( left.IsEmpty() || right.IsEmpty() )
502 return NewLeafNode( points );
505 node->left = BuildTree( left, depth+1 );
506 node->right = BuildTree( right, depth+1 );
510 if ( node->IsLeaf() )
513 return NewLeafNode( points );
519 void SearchTree( point_list& found,
const component_vector& p0,
const component_vector& p1,
const Node* node,
int depth )
const
521 if ( node !=
nullptr )
522 if ( node->IsLeaf() )
524 const LeafNode* leaf =
static_cast<const LeafNode*
>( node );
525 for (
const point& p : leaf->points )
529 if ( x < p0[j] || p1[j] < x )
531 if ( ++j == m_dimension )
540 int index = depth % m_dimension;
541 if ( p0[index] <= node->split )
542 SearchTree( found, p0, p1, node->left, depth+1 );
543 if ( p1[index] > node->split )
544 SearchTree( found, p0, p1, node->right, depth+1 );
549 void SearchTree(
const component_vector& p0,
const component_vector& p1, F callback,
void* data,
const Node* node,
int depth )
const
551 if ( node !=
nullptr )
552 if ( node->IsLeaf() )
554 const LeafNode* leaf =
static_cast<const LeafNode*
>( node );
555 for (
const point& p : leaf->points )
559 if ( x < p0[j] || p1[j] < x )
561 if ( ++j == m_dimension )
570 int index = depth % m_dimension;
571 if ( p0[index] <= node->split )
572 SearchTree( p0, p1, callback, data, node->left, depth+1 );
573 if ( p1[index] > node->split )
574 SearchTree( p0, p1, callback, data, node->right, depth+1 );
578 void DestroyTree( Node* node )
580 if ( node !=
nullptr )
581 if ( node->IsLeaf() )
582 delete static_cast<LeafNode*
>( node );
585 DestroyTree( node->left );
586 DestroyTree( node->right );
591 double SplitValue(
const point_list& points,
int index )
593 component_vector v( points.Length() );
594 for (
int i = 0; i < v.Length(); ++i )
595 v[i] = points[i][index];
bool IsEmpty() const noexcept
size_type Length() const noexcept
A simple exception with an associated error message.
Generic vector of arbitrary length.
Bucket PR K-d tree for point data in arbitrary dimensions.
point_list Search(const point &pt, component epsilon) const
KDTree(const point_list &points, int dimension, int bucketCapacity)
typename point::component component
void Build(const point_list &points, int bucketCapacity=16)
void Search(const point &pt, component epsilon, F callback, void *data) const
KDTree(const KDTree &)=delete
void Build(const point_list &points, int dimension, int bucketCapacity)
friend void Swap(KDTree &x1, KDTree &x2)
KDTree(const point_list &points, int bucketCapacity=16)
void Swap(GenericPoint< T > &p1, GenericPoint< T > &p2) noexcept
constexpr const T & Max(const T &a, const T &b) noexcept