Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
quadtree.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
45# ifndef QUADTREE_H
46# define QUADTREE_H
47
48# include <quadnode.H>
49
126{
127public:
128 using Node = QuadNode;
129
130private:
132
135
141 const Geom_Number & min_x, const Geom_Number & max_x,
142 const Geom_Number & min_y, const Geom_Number & max_y,
143 const size_t capacity)
144 {
145 ah_domain_error_if(capacity == 0)
146 << "QuadTree leaf capacity must be greater than zero";
147 return new Node(min_x, max_x, min_y, max_y);
148 }
149
151 [[nodiscard]] static bool contains_only(Node * node, const Point & p)
152 {
153 assert(node != nullptr and node->is_leaf());
154 for (const Point & point : node->get_points_set())
155 if (point != p)
156 return false;
157 return true;
158 }
159
161 [[nodiscard]] static bool has_four_leaf_children(Node * node) noexcept
162 {
163 return node != nullptr and not node->is_leaf() and
164 NW_CHILD(node) != nullptr and NW_CHILD(node)->is_leaf() and
165 NE_CHILD(node) != nullptr and NE_CHILD(node)->is_leaf() and
166 SW_CHILD(node) != nullptr and SW_CHILD(node)->is_leaf() and
167 SE_CHILD(node) != nullptr and SE_CHILD(node)->is_leaf();
168 }
169
171 [[nodiscard]] static size_t leaf_children_size(Node * node) noexcept
172 {
174 return NW_CHILD(node)->get_points_set().size() +
175 NE_CHILD(node)->get_points_set().size() +
176 SW_CHILD(node)->get_points_set().size() +
177 SE_CHILD(node)->get_points_set().size();
178 }
179
187 void split(Node * node)
188 {
189 assert(node->is_leaf()); // Only applies to leaf nodes
190
191 size_t next_level = LEVEL(node) + 1;
192
193 NW_CHILD(node) =
194 new QuadNode(node->get_min_x(), node->get_mid_x(),
195 node->get_min_y(), node->get_mid_y(), node);
196 LEVEL(NW_CHILD(node)) = next_level;
197
198 NE_CHILD(node) =
199 new QuadNode(node->get_mid_x(), node->get_max_x(),
200 node->get_min_y(), node->get_mid_y(), node);
201 LEVEL(NE_CHILD(node)) = next_level;
202
203 SW_CHILD(node) =
204 new QuadNode(node->get_min_x(), node->get_mid_x(),
205 node->get_mid_y(), node->get_max_y(), node);
206 LEVEL(SW_CHILD(node)) = next_level;
207
208 SE_CHILD(node) =
209 new QuadNode(node->get_mid_x(), node->get_max_x(),
210 node->get_mid_y(), node->get_max_y(), node);
211 LEVEL(SE_CHILD(node)) = next_level;
212
213 COLOR(node) = Node::Color::Gray;
214
215 DynList<Point> & points = node->get_points_set();
216
217 while (not points.is_empty())
218 {
219 Point point = points.remove_first();
220
221 QuadNode * child = node->get_child_to(point);
222
223 child->add_point(point);
224 }
225 }
226
234 void join(Node * node)
235 {
236 assert(not node->is_leaf()); // node is not a leaf
237 // All four children of node must be leaves
238 assert(NW_CHILD(node)->is_leaf());
239 assert(NE_CHILD(node)->is_leaf());
240 assert(SW_CHILD(node)->is_leaf());
241 assert(SE_CHILD(node)->is_leaf());
242
243 DynList<Point> & points = node->get_points_set();
244
245 DynList<Point> & nw_points = NW_CHILD(node)->get_points_set();
246
247 while(not nw_points.is_empty())
248 points.append(nw_points.remove_first());
249
250 auto & ne_points = NE_CHILD(node)->get_points_set();
251
252 while(not ne_points.is_empty())
253 points.append(ne_points.remove_first());
254
255 auto & sw_points = SW_CHILD(node)->get_points_set();
256
257 while(not sw_points.is_empty())
258 points.append(sw_points.remove_first());
259
260 auto & se_points = SE_CHILD(node)->get_points_set();
261
262 while(not se_points.is_empty())
263 points.append(se_points.remove_first());
264
265 delete NW_CHILD(node);
266 NW_CHILD(node) = nullptr;
267
268 delete NE_CHILD(node);
269 NE_CHILD(node) = nullptr;
270
271 delete SW_CHILD(node);
272 SW_CHILD(node) = nullptr;
273
274 delete SE_CHILD(node);
275 SE_CHILD(node) = nullptr;
276
278 }
279
281 Point * insert(Node *& r, const Point & p)
282 {
283 assert(r->contains(p));
284
285 if (r->is_leaf())
286 {
287 if (r->get_points_set().size() < max_num_points_per_node or
288 contains_only(r, p))
289 return &r->add_point(p);
290
291 split(r);
292 }
293
294 Node * node = r->get_child_to(p);
295
296 return insert(node, p);
297 }
298
300 void empty(Node *& r) noexcept
301 {
302 if (r == nullptr)
303 return;
304
305 empty(NW_CHILD(r));
306 empty(NE_CHILD(r));
307 empty(SW_CHILD(r));
308 empty(SE_CHILD(r));
309
310 delete r;
311 r = nullptr;
312 }
313
315 template <class Op>
316 void operate_on_nodes(Node * r, Op & op)
317 {
318 if (r == nullptr)
319 return;
320
321 op(r);
322
327 }
328
330 void copy_tree(QuadNode * src, QuadNode *& tgt,
331 QuadNode * tgt_parent = nullptr)
332 {
333 if (src == nullptr)
334 return;
335
336 if (src->get_min_x() < src->get_max_x() and
337 src->get_min_y() < src->get_max_y())
338 tgt = new QuadNode(src->get_min_x(), src->get_max_x(),
339 src->get_min_y(), src->get_max_y(), tgt_parent);
340 else
341 {
342 // Preserve the explicitly uninitialized state of a default tree.
343 tgt = new QuadNode;
344 PARENT(tgt) = tgt_parent;
345 }
346
347 tgt->get_points_set() = src->get_points_set();
348
349 COLOR(tgt) = COLOR(src);
350 LEVEL(tgt) = LEVEL(src);
351
352 copy_tree(NW_CHILD(src), NW_CHILD(tgt), tgt);
353 copy_tree(NE_CHILD(src), NE_CHILD(tgt), tgt);
354 copy_tree(SW_CHILD(src), SW_CHILD(tgt), tgt);
355 copy_tree(SE_CHILD(src), SE_CHILD(tgt), tgt);
356 }
357
358public:
359
367 {
368 // Empty
369 }
370
380 QuadTree(const Geom_Number & min_x, const Geom_Number & max_x,
381 const Geom_Number & min_y, const Geom_Number & max_y,
382 const size_t & _max_num_points_per_node = 1)
383 : root(make_root(min_x, max_x, min_y, max_y,
386 {
387 // Empty
388 }
389
394 QuadTree(const QuadTree & tree)
396 {
397 copy_tree(tree.root, root);
398 }
399
405 : root(tree.root), max_num_points_per_node(tree.max_num_points_per_node)
406 {
407 tree.root = nullptr;
408 }
409
416 {
417 if (this == &tree)
418 return *this;
419
420 empty(root);
422 copy_tree(tree.root, root);
423
424 return *this;
425 }
426
432 QuadTree & operator = (QuadTree && tree) noexcept
433 {
434 if (this != &tree)
435 {
436 empty(root);
437 root = tree.root;
438 max_num_points_per_node = tree.max_num_points_per_node;
439 tree.root = nullptr;
440 }
441 return *this;
442 }
443
446 {
447 empty(root);
448 }
449
452 {
453 return root;
454 }
455
458 {
459 return root;
460 }
461
470 {
472 << "QuadTree leaf capacity must be greater than zero";
474 }
475
481
487 [[nodiscard]] bool contains(const Point & p) const noexcept
488 {
489 return root != nullptr and root->contains(p);
490 }
491
500 Point * insert(const Point & p)
501 {
502 if (root == nullptr or not root->contains(p))
503 return nullptr;
504
505 return insert(root, p);
506 }
507
514 Point * insert(const Geom_Number & x, const Geom_Number & y)
515 {
516 return insert(Point(x, y));
517 }
518
524 [[nodiscard]] Point * search(const Point & p) noexcept
525 {
526 if (root == nullptr or not root->contains(p))
527 return nullptr;
528
529 Node * aux = root;
530
531 while (not aux->is_leaf())
532 aux = aux->get_child_to(p);
533
534 return aux->search_point(p);
535 }
536
542 [[nodiscard]] Node * search_container_node(const Point & p) noexcept
543 {
544 if (root == nullptr or not root->contains(p))
545 return nullptr;
546
547 Node * aux = root;
548
549 while (not aux->is_leaf())
550 aux = aux->get_child_to(p);
551
552 if (aux->search_point(p) == nullptr)
553 return nullptr;
554
555 return aux;
556 }
557
565 void remove(const Point & p)
566 {
567 if (root == nullptr or not root->contains(p))
568 return;
569
570 Node * aux = root;
571
572 while (not aux->is_leaf())
573 aux = aux->get_child_to(p);
574
575 if (not aux->remove_point(p))
576 return;
577
578 Node * parent = PARENT(aux);
579 while (parent != nullptr and has_four_leaf_children(parent) and
581 {
582 Node * grandparent = PARENT(parent);
583 join(parent);
584 parent = grandparent;
585 }
586 }
587
589 void empty()
590 {
591 if (root == nullptr)
592 return;
593
598 root->empty();
599 }
600
602 void clear() { empty(); }
603
611 template <class Op>
612 void for_each(Op & op)
613 {
615 }
616
618 template <class Op>
619 void for_each(Op && op = Op())
620 {
622 }
623};
624
625# endif // QUADTREE_H
#define PARENT(p)
Definition Dijkstra.H:125
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:527
#define LEVEL(p)
Definition btreepic.C:373
Doubly-linked list (defined in tpl_dynList.H).
Definition htlist.H:1155
T & append(const T &item)
Definition htlist.H:1271
constexpr bool is_empty() const noexcept
Definition htlist.H:419
Represents a point with rectangular coordinates in a 2D plane.
Definition point.H:221
Node for QuadTree spatial data structure.
Definition quadnode.H:94
bool contains(const Point &p) const noexcept
Check if a point is contained in this node's region.
Definition quadnode.H:423
const Geom_Number & get_min_y() const noexcept
Get minimum Y coordinate of this region.
Definition quadnode.H:490
const Geom_Number & get_max_y() const noexcept
Get maximum Y coordinate of this region.
Definition quadnode.H:493
void empty() noexcept
Remove all points from this node and mark it as White.
Definition quadnode.H:547
Geom_Number get_mid_x() const noexcept
Get midpoint X coordinate.
Definition quadnode.H:502
QuadNode * get_child_to(const Point &p) const
Find which child node should contain a given point.
Definition quadnode.H:438
DynList< Point > & get_points_set() noexcept
Get reference to the points list (for direct manipulation).
Definition quadnode.H:580
Geom_Number get_mid_y() const noexcept
Get midpoint Y coordinate.
Definition quadnode.H:505
const Geom_Number & get_min_x() const noexcept
Get minimum X coordinate of this region.
Definition quadnode.H:484
Point & add_point(const Point &p)
Add a point to this node.
Definition quadnode.H:471
Point * search_point(const Point &p) noexcept
Search for a point in this node.
Definition quadnode.H:514
bool is_leaf() const noexcept
Check if this node is a leaf (has no children).
Definition quadnode.H:381
bool remove_point(const Point &p)
Remove a point from this node.
Definition quadnode.H:529
const Geom_Number & get_max_x() const noexcept
Get maximum X coordinate of this region.
Definition quadnode.H:487
@ White
Empty leaf node.
@ Gray
Internal node with children.
@ Black
Leaf node with points.
QuadTree - Hierarchical spatial index for 2D points.
Definition quadtree.H:126
size_t max_num_points_per_node
Maximum points per leaf node before splitting.
Definition quadtree.H:134
static bool has_four_leaf_children(Node *node) noexcept
Return true when an internal node has four leaf children.
Definition quadtree.H:161
void empty(Node *&r) noexcept
Recursively delete all nodes.
Definition quadtree.H:300
void clear()
Alias for empty().
Definition quadtree.H:602
~QuadTree()
Destructor - frees all nodes.
Definition quadtree.H:445
void for_each(Op &op)
Apply an operation to each node in the tree.
Definition quadtree.H:612
QuadTree(const Geom_Number &min_x, const Geom_Number &max_x, const Geom_Number &min_y, const Geom_Number &max_y, const size_t &_max_num_points_per_node=1)
Construct a quadtree with specified region and capacity.
Definition quadtree.H:380
void for_each(Op &&op=Op())
Apply operation to each node (rvalue reference version).
Definition quadtree.H:619
void remove(const Point &p)
Remove a point from the tree.
Definition quadtree.H:565
QuadTree()
Default constructor - creates an uninitialized tree.
Definition quadtree.H:365
Point * search(const Point &p) noexcept
Search for a point in the tree.
Definition quadtree.H:524
Node * search_container_node(const Point &p) noexcept
Find the leaf node containing a point.
Definition quadtree.H:542
Point * insert(const Geom_Number &x, const Geom_Number &y)
Insert a point given by coordinates.
Definition quadtree.H:514
void copy_tree(QuadNode *src, QuadNode *&tgt, QuadNode *tgt_parent=nullptr)
Deep copy a tree structure.
Definition quadtree.H:330
const Node * get_root() const noexcept
Get the root node (const version).
Definition quadtree.H:457
void set_max_num_points_per_node(const size_t &_max_num_points_per_node)
Set the maximum points per leaf node.
Definition quadtree.H:469
static bool contains_only(Node *node, const Point &p)
Return true when every point stored in a leaf equals p.
Definition quadtree.H:151
static Node * make_root(const Geom_Number &min_x, const Geom_Number &max_x, const Geom_Number &min_y, const Geom_Number &max_y, const size_t capacity)
Validate constructor arguments and allocate the root node.
Definition quadtree.H:140
void split(Node *node)
Subdivide a leaf node into four children.
Definition quadtree.H:187
static size_t leaf_children_size(Node *node) noexcept
Return the number of points directly stored in four leaf children.
Definition quadtree.H:171
void operate_on_nodes(Node *r, Op &op)
Apply operation to all nodes in the tree.
Definition quadtree.H:316
QuadNode Node
Definition quadtree.H:128
QuadTree(const QuadTree &tree)
Copy constructor - creates a deep copy of the tree.
Definition quadtree.H:394
QuadTree(QuadTree &&tree) noexcept
Move constructor - transfers ownership.
Definition quadtree.H:404
bool contains(const Point &p) const noexcept
Check if a point is within the tree's region.
Definition quadtree.H:487
Point * insert(Node *&r, const Point &p)
Recursive insert helper.
Definition quadtree.H:281
size_t get_max_num_points_per_node() const noexcept
Get the maximum points per leaf node.
Definition quadtree.H:477
QuadTree & operator=(const QuadTree &tree)
Copy assignment operator - creates a deep copy.
Definition quadtree.H:415
void join(Node *node)
Merge four child nodes back into their parent.
Definition quadtree.H:234
Point * insert(const Point &p)
Insert a point into the tree.
Definition quadtree.H:500
Node * get_root() noexcept
Get the root node.
Definition quadtree.H:451
Node * root
Root node of the tree.
Definition quadtree.H:131
void empty()
Remove all points from the tree, keeping only the root.
Definition quadtree.H:589
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
static mpfr_t y
Definition mpfr_mul_d.c:3
and
Check uniqueness with explicit hash + equality functors.
static bool is_leaf(BinNode< std::string > *p) noexcept
Definition Huffman.H:104
QuadTree node implementation for spatial data structures.
#define COLOR(p)
Definition quadnode.H:58
#define SE_CHILD(p)
Definition quadnode.H:57
#define NE_CHILD(p)
Definition quadnode.H:55
#define NW_CHILD(p)
Definition quadnode.H:54
#define SW_CHILD(p)
Definition quadnode.H:56
gsl_rng * r