52 #ifndef __PCL_QuadTree_h
53 #define __PCL_QuadTree_h
71 #define __PCL_QUADTREE_DEFAULT_BUCKET_CAPACITY 40
76 #define __PCL_QUADTREE_DEFAULT_EPSILON 1.0e-08
166 #ifdef __PCL_QUADTREE_STRUCTURAL_NODE_HAS_DATA
167 void* data =
nullptr;
194 return nw ==
nullptr &&
ne ==
nullptr &&
sw ==
nullptr &&
se ==
nullptr;
277 #ifndef __PCL_QUADTREE_STRUCTURAL_NODE_HAS_DATA
347 int bucketCapacity = __PCL_QUADTREE_DEFAULT_BUCKET_CAPACITY,
348 double epsilon = __PCL_QUADTREE_DEFAULT_EPSILON )
350 Build( points, bucketCapacity, epsilon );
374 int bucketCapacity = __PCL_QUADTREE_DEFAULT_BUCKET_CAPACITY,
375 double epsilon = __PCL_QUADTREE_DEFAULT_EPSILON )
377 Build( rect, points, bucketCapacity, epsilon );
399 , m_bucketCapacity( x.m_bucketCapacity )
400 , m_epsilon( x.m_epsilon )
401 , m_length( x.m_length )
414 DestroyTree( m_root );
416 m_bucketCapacity = x.m_bucketCapacity;
417 m_epsilon = x.m_epsilon;
418 m_length = x.m_length;
438 DestroyTree( m_root );
464 int bucketCapacity = __PCL_QUADTREE_DEFAULT_BUCKET_CAPACITY,
465 double epsilon = __PCL_QUADTREE_DEFAULT_EPSILON )
468 m_bucketCapacity =
Max( 1, bucketCapacity );
469 m_epsilon =
Max( 2*std::numeric_limits<coordinate>::epsilon(), epsilon );
476 for (
const point& p : points )
489 m_root = BuildTree( rect, points );
519 int bucketCapacity = __PCL_QUADTREE_DEFAULT_BUCKET_CAPACITY,
520 double epsilon = __PCL_QUADTREE_DEFAULT_EPSILON )
523 m_bucketCapacity =
Max( 1, bucketCapacity );
524 m_epsilon =
Max( 2*std::numeric_limits<coordinate>::epsilon(), epsilon );
526 m_root = BuildTree( rect.
Ordered(), points );
540 SearchTree( found, rect.
Ordered(), m_root );
563 SearchTree( rect.
Ordered(), callback, data, m_root );
571 if ( m_root !=
nullptr )
572 InsertTree( pt, m_root );
586 DeleteTree( pt, m_root );
595 DeleteTree( rect.
Ordered(), m_root );
605 return m_bucketCapacity;
621 return m_root ==
nullptr;
652 return SearchLeafNode( p, m_root );
662 return SearchLeafNode( p, m_root );
676 return SearchNode( p, m_root );
690 return SearchNode( p, m_root );
705 Node* node = SearchDeepestStructuralNodeAt( p, m_root );
706 if ( node !=
nullptr )
708 Node** leaf =
nullptr;
711 else if ( node->
ne !=
nullptr && node->
ne->
Includes( p ) )
713 else if ( node->
sw !=
nullptr && node->
sw->
Includes( p ) )
715 else if ( node->
se !=
nullptr && node->
se->
Includes( p ) )
718 if ( leaf !=
nullptr )
720 Node* newNode = SplitLeafNode( *leaf );
721 if ( newNode !=
nullptr )
723 delete static_cast<LeafNode*
>( *leaf );
755 if ( node !=
nullptr )
791 if ( node !=
nullptr )
841 GetNumberOfNodes( N, node );
861 GetNumberOfLeafNodes( N, node );
878 return TreeHeight( node, 0 );
895 pcl::Swap( x1.m_bucketCapacity, x2.m_bucketCapacity );
902 Node* m_root =
nullptr;
903 int m_bucketCapacity = 0;
904 double m_epsilon = 0;
909 m_length += points.Length();
910 return new LeafNode( rect, points );
913 LeafNode* SearchLeafNode(
const rectangle::point& p,
const Node* node )
const
915 if ( node !=
nullptr )
916 if ( node->Includes( p ) )
918 if ( node->IsLeaf() )
919 return const_cast<LeafNode*
>(
static_cast<const LeafNode*
>( node ) );
921 LeafNode* child = SearchLeafNode( p, node->nw );
922 if ( child ==
nullptr )
924 child = SearchLeafNode( p, node->ne );
925 if ( child ==
nullptr )
927 child = SearchLeafNode( p, node->sw );
928 if ( child ==
nullptr )
929 child = SearchLeafNode( p, node->se );
940 if ( node !=
nullptr )
941 if ( node->Includes( p ) )
943 if ( node->IsLeaf() )
944 return const_cast<Node*
>( node );
946 Node* child = SearchNode( p, node->nw );
947 if ( child ==
nullptr )
949 child = SearchNode( p, node->ne );
950 if ( child ==
nullptr )
952 child = SearchNode( p, node->sw );
953 if ( child ==
nullptr )
955 child = SearchNode( p, node->se );
956 if ( child ==
nullptr )
957 return const_cast<Node*
>( node );
967 Node* SearchDeepestStructuralNodeAt(
const rectangle::point& p,
const Node* node )
const
969 if ( node !=
nullptr )
970 if ( !node->IsLeaf() )
971 if ( node->Includes( p ) )
973 Node* child = SearchDeepestStructuralNodeAt( p, node->nw );
974 if ( child ==
nullptr )
976 child = SearchDeepestStructuralNodeAt( p, node->ne );
977 if ( child ==
nullptr )
979 child = SearchDeepestStructuralNodeAt( p, node->sw );
980 if ( child ==
nullptr )
982 child = SearchDeepestStructuralNodeAt( p, node->se );
983 if ( child ==
nullptr )
984 return const_cast<Node*
>( node );
996 if ( points.IsEmpty() )
999 if ( points.Length() <=
size_type( m_bucketCapacity ) )
1000 return NewLeafNode( rect, points );
1002 double x2 = (rect.x0 + rect.x1)/2;
1003 double y2 = (rect.y0 + rect.y1)/2;
1007 if ( x2 - rect.x0 < m_epsilon || rect.x1 - x2 < m_epsilon ||
1008 y2 - rect.y0 < m_epsilon || rect.y1 - y2 < m_epsilon )
1010 return NewLeafNode( rect, points );
1014 for (
const point& p : points )
1034 Node* node =
new Node( rect );
1035 node->nw = BuildTree(
rectangle( rect.x0, rect.y0, x2, y2 ), nw );
1036 node->ne = BuildTree(
rectangle( x2, rect.y0, rect.x1, y2 ), ne );
1037 node->sw = BuildTree(
rectangle( rect.x0, y2, x2, rect.y1 ), sw );
1038 node->se = BuildTree(
rectangle( x2, y2, rect.x1, rect.y1 ), se );
1042 if ( node->IsLeaf() )
1045 return NewLeafNode( rect, points );
1051 Node* SplitLeafNode(
const Node* node )
1053 if ( node ==
nullptr || !node->IsLeaf() )
1056 double x2 = (node->rect.x0 + node->rect.x1)/2;
1057 double y2 = (node->rect.y0 + node->rect.y1)/2;
1061 if ( x2 - node->rect.x0 < m_epsilon || node->rect.x1 - x2 < m_epsilon ||
1062 y2 - node->rect.y0 < m_epsilon || node->rect.y1 - y2 < m_epsilon )
1067 const LeafNode* leaf =
static_cast<const LeafNode*
>( node );
1069 for (
const point& p : leaf->points )
1090 Node* newNode =
new Node( node->rect );
1091 newNode->nw = BuildTree(
rectangle( node->rect.x0, node->rect.y0, x2, y2 ), nw );
1092 newNode->ne = BuildTree(
rectangle( x2, node->rect.y0, node->rect.x1, y2 ), ne );
1093 newNode->sw = BuildTree(
rectangle( node->rect.x0, y2, x2, node->rect.y1 ), sw );
1094 newNode->se = BuildTree(
rectangle( x2, y2, node->rect.x1, node->rect.y1 ), se );
1095 m_length = savedLength;
1099 if ( newNode->IsLeaf() )
1110 if ( node !=
nullptr )
1111 if ( node->Intersects( rect ) )
1112 if ( node->IsLeaf() )
1114 const LeafNode* leaf =
static_cast<const LeafNode*
>( node );
1115 for (
const point& p : leaf->points )
1130 SearchTree( found, rect, node->nw );
1131 SearchTree( found, rect, node->ne );
1132 SearchTree( found, rect, node->sw );
1133 SearchTree( found, rect, node->se );
1138 void SearchTree(
const rectangle& rect, F callback,
void* data,
const Node* node )
const
1140 if ( node !=
nullptr )
1141 if ( node->Intersects( rect ) )
1142 if ( node->IsLeaf() )
1144 const LeafNode* leaf =
static_cast<const LeafNode*
>( node );
1145 for (
const point& p : leaf->points )
1154 callback( p, data );
1160 SearchTree( rect, callback, data, node->nw );
1161 SearchTree( rect, callback, data, node->ne );
1162 SearchTree( rect, callback, data, node->sw );
1163 SearchTree( rect, callback, data, node->se );
1167 void InsertTree(
const point& pt, Node*& node )
1169 PCL_CHECK( node !=
nullptr )
1174 if ( x < node->rect.x0 )
1176 else if ( x > node->rect.x1 )
1179 if ( y < node->rect.y0 )
1181 else if ( y > node->rect.y1 )
1184 if ( node->IsLeaf() )
1186 LeafNode* leaf =
static_cast<LeafNode*
>( node );
1187 if ( leaf->Length() < m_bucketCapacity )
1192 double x2 = (rect.x0 + rect.x1)/2;
1193 double y2 = (rect.y0 + rect.y1)/2;
1197 if ( x2 - rect.x0 < m_epsilon || rect.x1 - x2 < m_epsilon ||
1198 y2 - rect.y0 < m_epsilon || rect.y1 - y2 < m_epsilon )
1205 for (
const point& p : leaf->points )
1242 node =
new Node( rect );
1244 if ( !nw.IsEmpty() )
1245 node->nw =
new LeafNode(
rectangle( rect.x0, rect.y0, x2, y2 ), nw );
1246 if ( !ne.IsEmpty() )
1247 node->ne =
new LeafNode(
rectangle( x2, rect.y0, rect.x1, y2 ), ne );
1248 if ( !sw.IsEmpty() )
1249 node->sw =
new LeafNode(
rectangle( rect.x0, y2, x2, rect.y1 ), sw );
1250 if ( !se.IsEmpty() )
1251 node->se =
new LeafNode(
rectangle( x2, y2, rect.x1, rect.y1 ), se );
1260 double x2 = (rect.x0 + rect.x1)/2;
1261 double y2 = (rect.y0 + rect.y1)/2;
1266 if ( node->nw ==
nullptr )
1267 node->nw =
new LeafNode(
rectangle( rect.x0, rect.y0, x2, y2 ), pt );
1269 InsertTree( pt, node->nw );
1273 if ( node->sw ==
nullptr )
1274 node->sw =
new LeafNode(
rectangle( rect.x0, y2, x2, rect.y1 ), pt );
1276 InsertTree( pt, node->sw );
1283 if ( node->ne ==
nullptr )
1284 node->ne =
new LeafNode(
rectangle( x2, rect.y0, rect.x1, y2 ), pt );
1286 InsertTree( pt, node->ne );
1290 if ( node->se ==
nullptr )
1291 node->se =
new LeafNode(
rectangle( x2, y2, rect.x1, rect.y1 ), pt );
1293 InsertTree( pt, node->se );
1299 void DeleteTree(
const rectangle& rect, Node*& node )
1301 if ( node !=
nullptr )
1302 if ( node->Intersects( rect ) )
1304 if ( node->IsLeaf() )
1306 LeafNode* leaf =
static_cast<LeafNode*
>( node );
1308 for (
const point& p : leaf->points )
1325 if ( points.IsEmpty() )
1331 leaf->points = points;
1335 DeleteTree( rect, node->nw );
1336 DeleteTree( rect, node->ne );
1337 DeleteTree( rect, node->sw );
1338 DeleteTree( rect, node->se );
1340 if ( node->IsLeaf() )
1349 void DeleteTree(
const point& pt, Node*& node )
1351 if ( node !=
nullptr )
1353 component x = pt[0];
1354 component y = pt[1];
1355 if ( node->Includes( x, y ) )
1356 if ( node->IsLeaf() )
1358 LeafNode* leaf =
static_cast<LeafNode*
>( node );
1360 for (
const point& p : leaf->points )
1371 if ( points.IsEmpty() )
1377 leaf->points = points;
1381 DeleteTree( pt, node->nw );
1382 DeleteTree( pt, node->ne );
1383 DeleteTree( pt, node->sw );
1384 DeleteTree( pt, node->se );
1386 if ( node->IsLeaf() )
1395 void DestroyTree( Node* node )
1397 if ( node !=
nullptr )
1398 if ( node->IsLeaf() )
1399 delete static_cast<LeafNode*
>( node );
1402 DestroyTree( node->nw );
1403 DestroyTree( node->ne );
1404 DestroyTree( node->sw );
1405 DestroyTree( node->se );
1410 static void GetNumberOfNodes(
size_type& N,
const Node* node )
1412 if ( node !=
nullptr )
1415 GetNumberOfNodes( N, node->nw );
1416 GetNumberOfNodes( N, node->ne );
1417 GetNumberOfNodes( N, node->sw );
1418 GetNumberOfNodes( N, node->se );
1422 static void GetNumberOfLeafNodes(
size_type& N,
const Node* node )
1424 if ( node !=
nullptr )
1426 if ( node->IsLeaf() )
1428 GetNumberOfLeafNodes( N, node->nw );
1429 GetNumberOfLeafNodes( N, node->ne );
1430 GetNumberOfLeafNodes( N, node->sw );
1431 GetNumberOfLeafNodes( N, node->se );
1435 static int TreeHeight(
const Node* node,
int h )
1437 if ( node ==
nullptr )
1439 return h + 1 +
Max(
Max(
Max( TreeHeight( node->nw, h ),
1440 TreeHeight( node->ne, h ) ),
1441 TreeHeight( node->sw, h ) ),
1442 TreeHeight( node->se, h ) );
bool IsEmpty() const noexcept
size_type Length() const noexcept
A generic point in the two-dimensional space.
component x
Abscissa (horizontal, or X-axis coordinate).
component y
Ordinate (vertical, or Y-axis coordinate).
A generic rectangle in the two-dimensional space.
point BottomRight() const noexcept
component x1
Horizontal coordinate of the lower right corner.
point CenterLeft() const noexcept
component y1
Vertical coordinate of the lower right corner.
point TopLeft() const noexcept
point Center() const noexcept
point CenterBottom() const noexcept
GenericPoint< component > point
component y0
Vertical coordinate of the upper left corner.
component x0
Horizontal coordinate of the upper left corner.
point CenterTop() const noexcept
point CenterRight() const noexcept
GenericRectangle Ordered() const noexcept
Bucket PR quadtree for two-dimensional point data.
QuadTree(const rectangle &rect, const point_list &points, int bucketCapacity=__PCL_QUADTREE_DEFAULT_BUCKET_CAPACITY, double epsilon=__PCL_QUADTREE_DEFAULT_EPSILON)
const LeafNode * LeafNodeAt(rectangle::point p) const
LeafNode * LeafNodeAt(rectangle::point p)
QuadTree(const QuadTree &)=delete
size_type NumberOfNodes() const
size_type NumberOfLeafNodes() const
static void Traverse(const Node *node, F f)
QuadTree & operator=(const QuadTree &)=delete
const Node * NodeAt(rectangle::point p) const
void Delete(const rectangle &rect)
friend void Swap(QuadTree &x1, QuadTree &x2)
typename point::component component
static int Height(const Node *node)
void Search(const rectangle &rect, F callback, void *data) const
void Insert(const point &pt)
static size_type NumberOfNodes(const Node *node)
rectangle::component coordinate
Array< point > point_list
Node * NodeAt(rectangle::point p)
int BucketCapacity() const
void Build(const rectangle &rect, const point_list &points, int bucketCapacity=__PCL_QUADTREE_DEFAULT_BUCKET_CAPACITY, double epsilon=__PCL_QUADTREE_DEFAULT_EPSILON)
static void Traverse(Node *node, F f)
const Node * Root() const
void Delete(const point &pt)
Node * SplitAt(rectangle::point p)
static size_type NumberOfLeafNodes(const Node *node)
QuadTree(const point_list &points, int bucketCapacity=__PCL_QUADTREE_DEFAULT_BUCKET_CAPACITY, double epsilon=__PCL_QUADTREE_DEFAULT_EPSILON)
void Build(const point_list &points, int bucketCapacity=__PCL_QUADTREE_DEFAULT_BUCKET_CAPACITY, double epsilon=__PCL_QUADTREE_DEFAULT_EPSILON)
point_list Search(const rectangle &rect) const
void Swap(GenericPoint< T > &p1, GenericPoint< T > &p2) noexcept
constexpr const T & Max(const T &a, const T &b) noexcept
Quadtree leaf node structure.
LeafNode(const rectangle &r, const point &p)
LeafNode(const rectangle &r, const point_list &p)
bool Includes(coordinate x, coordinate y) const
bool Includes(const rectangle::point &p) const
Node * se
South-East child node, representing the bottom-right subregion.
Node * ne
North-East child node, representing the top-right subregion.
Node * nw
North-West child node, representing the top-left subregion.
rectangle rect
The rectangular region represented by this node.
Node * sw
South-West child node, representing the bottom-left subregion.
bool Intersects(const rectangle &r) const