Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
quadnode.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
44# ifndef QUADNODE_H
45# define QUADNODE_H
46
47# include <htlist.H>
48# include <point.H>
49# include <ah-errors.H>
50
51using namespace Aleph;
52
53# define PARENT(p) ((p)->get_parent())
54# define NW_CHILD(p) ((p)->get_nw_child())
55# define NE_CHILD(p) ((p)->get_ne_child())
56# define SW_CHILD(p) ((p)->get_sw_child())
57# define SE_CHILD(p) ((p)->get_se_child())
58# define COLOR(p) ((p)->get_color())
59# define LEVEL(p) ((p)->get_level())
60
94{
95public:
96
104 enum class Color
105 {
106 White,
107 Gray,
108 Black,
110 };
111
120 enum class Quad
121 {
122 NW,
123 NE,
124 SW,
125 SE,
127 };
128
133 enum class Side
134 {
135 North,
136 South,
137 East,
138 West,
140 };
141
142private:
144
150
152 unsigned long level;
153
154 // Region boundaries
159
161 static QuadNode * get_north_neighbor(QuadNode * v) noexcept
162 {
163 if (PARENT(v) == nullptr)
164 return nullptr;
165
166 if (v->is_sw_child())
167 return NW_CHILD(PARENT(v));
168
169 if (v->is_se_child())
170 return NE_CHILD(PARENT(v));
171
173
174 if (u == nullptr or u->is_leaf())
175 return u;
176 else if (v->is_nw_child())
177 return SW_CHILD(u);
178 else
179 return SE_CHILD(u);
180 }
181
183 static QuadNode * get_south_neighbor(QuadNode * v) noexcept
184 {
185 if (PARENT(v) == nullptr)
186 return nullptr;
187
188 if (v->is_nw_child())
189 return SW_CHILD(PARENT(v));
190
191 if (v->is_ne_child())
192 return SE_CHILD(PARENT(v));
193
195
196 if (u == nullptr or u->is_leaf())
197 return u;
198 else if (v->is_sw_child())
199 return NW_CHILD(u);
200 else
201 return NE_CHILD(u);
202 }
203
205 static QuadNode * get_east_neighbor(QuadNode * v) noexcept
206 {
207 if (PARENT(v) == nullptr)
208 return nullptr;
209
210 if (v->is_nw_child())
211 return NE_CHILD(PARENT(v));
212
213 if (v->is_sw_child())
214 return SE_CHILD(PARENT(v));
215
217
218 if (u == nullptr or u->is_leaf())
219 return u;
220 else if (v->is_ne_child())
221 return NW_CHILD(u);
222 else
223 return SW_CHILD(u);
224 }
225
227 static QuadNode * get_west_neighbor(QuadNode * v) noexcept
228 {
229 if (PARENT(v) == nullptr)
230 return nullptr;
231
232 if (v->is_ne_child())
233 return NW_CHILD(PARENT(v));
234
235 if (v->is_se_child())
236 return SW_CHILD(PARENT(v));
237
239
240 if (u == nullptr or u->is_leaf())
241 return u;
242 else if (v->is_nw_child())
243 return NE_CHILD(u);
244 else
245 return SE_CHILD(u);
246 }
247
249 static void get_neighbors_by_side(QuadNode * node,
250 const Side & side,
252 {
253 if (node == nullptr)
254 return;
255
256 if (node->is_leaf())
257 {
258 neighbors.append(node);
259 return;
260 }
261
262 switch(side)
263 {
264 case Side::West:
267 break;
268 case Side::East:
271 break;
272 case Side::North:
275 break;
276 case Side::South:
279 break;
280 default:
281 ah_domain_error_if(true) << "Invalid side value";
282 }
283}
284
286static size_t count_points(QuadNode * node) noexcept
287{
288 if (node == nullptr)
289 return 0;
290
291 if (node->is_leaf())
292 return node->points.size();
293
294 size_t num_points = 0;
295
300
301 return num_points;
302}
303
304public:
305
308 : points(), parent(nullptr), nw_child(nullptr), ne_child(nullptr),
309 sw_child(nullptr), se_child(nullptr), color(Color::White), level(0),
310 min_x(0), max_x(0), min_y(0), max_y(0)
311 {
312 // Empty
313 }
314
324 const Geom_Number & _min_y, const Geom_Number & _max_y,
325 QuadNode * _parent = nullptr) noexcept
326 : points(), parent(_parent), nw_child(nullptr), ne_child(nullptr),
327 sw_child(nullptr), se_child(nullptr), color(Color::White), level(0),
329 {
330 // Empty
331 }
332
333 QuadNode(const QuadNode &) = delete;
334
343 const Geom_Number & _max_x,
344 const Geom_Number & _min_y,
345 const Geom_Number & _max_y) noexcept
346 {
347 min_x = _min_x;
348 max_x = _max_x;
349 min_y = _min_y;
350 max_y = _max_y;
351 }
352
355
358
361
364
367
370
372 [[nodiscard]] unsigned long & get_level() noexcept { return level; }
373
375 [[nodiscard]] bool is_leaf() const noexcept { return color != Color::Gray; }
376
379 {
380 if (parent == nullptr)
381 return false;
382 return NW_CHILD(parent) == this;
383 }
384
387 {
388 if (parent == nullptr)
389 return false;
390 return NE_CHILD(parent) == this;
391 }
392
395 {
396 if (parent == nullptr)
397 return false;
398 return SW_CHILD(parent) == this;
399 }
400
403 {
404 if (parent == nullptr)
405 return false;
406 return SE_CHILD(parent) == this;
407 }
408
417 [[nodiscard]] bool contains(const Point & p) const noexcept
418 {
419 return p.get_x() >= min_x and p.get_x() < max_x and
420 p.get_y() >= min_y and p.get_y() < max_y;
421 }
422
432 [[nodiscard]] QuadNode * get_child_to(const Point & p) const
433 {
434 assert(nw_child != nullptr);
435 assert(ne_child != nullptr);
436 assert(sw_child != nullptr);
437 assert(se_child != nullptr);
438
440 << "This node does not contain that point";
441
442 if (nw_child->contains(p))
443 return nw_child;
444
445 if (ne_child->contains(p))
446 return ne_child;
447
448 if (sw_child->contains(p))
449 return sw_child;
450
451 if (se_child->contains(p))
452 return se_child;
453
454 return nullptr; // To avoid compiler warnings
455 }
456
465 Point & add_point(const Point & p)
466 {
467 color = Color::Black;
468 return points.append(p);
469 }
470
473 {
474 return count_points(this);
475 }
476
479
482
485
488
491
494
497
500
508 [[nodiscard]] Point * search_point(const Point & p) noexcept
509 {
510 for (Point & point : points)
511 {
512 if (point == p)
513 return &point;
514 }
515 return nullptr;
516 }
517
523 bool remove_point(const Point & p)
524 {
525 for (DynList<Point>::iterator it(points); it.has_curr(); it.next_ne())
526 {
527 const Point & curr = it.get_curr_ne();
528
529 if (curr == p)
530 {
531 it.del();
532 return true;
533 }
534 }
535 return false;
536 }
537
540 {
541 points.empty();
542 color = Color::White;
543 }
544
570
573
579 template <class Op>
581 {
582 for (Point & point : points)
583 op(point);
584 };
585
587 template <class Op>
588 void for_each_point(Op && op = Op())
589 {
591 }
592
593 QuadNode & operator = (const QuadNode &) = delete;
594};
595
596# endif // QUADNODE_H
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
void empty() noexcept
empty the list
Definition htlist.H:1689
Node for QuadTree spatial data structure.
Definition quadnode.H:94
DynList< QuadNode * > get_neighbors()
Find all adjacent leaf nodes.
Definition quadnode.H:552
Color & get_color() noexcept
Get reference to color (for reading/writing via COLOR macro).
Definition quadnode.H:369
Side
Cardinal directions for neighbor navigation.
Definition quadnode.H:134
@ South
Southern neighbor.
@ North
Northern neighbor.
@ East
Eastern neighbor.
@ West
Western neighbor.
bool is_sw_child() const noexcept
Check if this node is the SW child of its parent.
Definition quadnode.H:394
static QuadNode * get_east_neighbor(QuadNode *v) noexcept
Find the eastern neighbor of a node.
Definition quadnode.H:205
static size_t count_points(QuadNode *node) noexcept
Recursively count all points in a subtree.
Definition quadnode.H:286
QuadNode *& get_sw_child() noexcept
Get reference to SW child (for reading/writing via SW_CHILD macro).
Definition quadnode.H:363
Geom_Number min_y
Minimum Y coordinate.
Definition quadnode.H:157
QuadNode *& get_se_child() noexcept
Get reference to SE child (for reading/writing via SE_CHILD macro).
Definition quadnode.H:366
void set_region(const Geom_Number &_min_x, const Geom_Number &_max_x, const Geom_Number &_min_y, const Geom_Number &_max_y) noexcept
Set the region boundaries for this node.
Definition quadnode.H:342
static QuadNode * get_west_neighbor(QuadNode *v) noexcept
Find the western neighbor of a node.
Definition quadnode.H:227
static void get_neighbors_by_side(QuadNode *node, const Side &side, DynList< QuadNode * > &neighbors)
Recursively collect leaf neighbors on a given side.
Definition quadnode.H:249
bool contains(const Point &p) const noexcept
Check if a point is contained in this node's region.
Definition quadnode.H:417
unsigned long & get_level() noexcept
Get reference to level (for reading/writing via LEVEL macro).
Definition quadnode.H:372
Geom_Number get_height() const noexcept
Get height of this region.
Definition quadnode.H:493
Geom_Number max_x
Maximum X coordinate.
Definition quadnode.H:156
static QuadNode * get_south_neighbor(QuadNode *v) noexcept
Find the southern neighbor of a node.
Definition quadnode.H:183
bool is_ne_child() const noexcept
Check if this node is the NE child of its parent.
Definition quadnode.H:386
Geom_Number max_y
Maximum Y coordinate.
Definition quadnode.H:158
QuadNode *& get_ne_child() noexcept
Get reference to NE child (for reading/writing via NE_CHILD macro).
Definition quadnode.H:360
QuadNode() noexcept
Default constructor - creates a white (empty) node.
Definition quadnode.H:307
const Geom_Number & get_min_y() const noexcept
Get minimum Y coordinate of this region.
Definition quadnode.H:484
bool is_se_child() const noexcept
Check if this node is the SE child of its parent.
Definition quadnode.H:402
const Geom_Number & get_max_y() const noexcept
Get maximum Y coordinate of this region.
Definition quadnode.H:487
void for_each_point(Op &&op=Op())
Apply operation to each point (rvalue reference version).
Definition quadnode.H:588
QuadNode * ne_child
Northeast child.
Definition quadnode.H:147
Geom_Number min_x
Minimum X coordinate.
Definition quadnode.H:155
void empty() noexcept
Remove all points from this node and mark it as White.
Definition quadnode.H:539
Geom_Number get_mid_x() const noexcept
Get midpoint X coordinate.
Definition quadnode.H:496
QuadNode * parent
Parent node (nullptr for root)
Definition quadnode.H:145
QuadNode * get_child_to(const Point &p) const
Find which child node should contain a given point.
Definition quadnode.H:432
DynList< Point > & get_points_set() noexcept
Get reference to the points list (for direct manipulation).
Definition quadnode.H:572
Geom_Number get_mid_y() const noexcept
Get midpoint Y coordinate.
Definition quadnode.H:499
Quad
Quadrant directions for child nodes.
Definition quadnode.H:121
@ SW
Southwest quadrant.
@ NW
Northwest quadrant.
@ NE
Northeast quadrant.
@ SE
Southeast quadrant.
QuadNode(const Geom_Number &_min_x, const Geom_Number &_max_x, const Geom_Number &_min_y, const Geom_Number &_max_y, QuadNode *_parent=nullptr) noexcept
Construct a node with specified region bounds.
Definition quadnode.H:323
const Geom_Number & get_min_x() const noexcept
Get minimum X coordinate of this region.
Definition quadnode.H:478
QuadNode * sw_child
Southwest child.
Definition quadnode.H:148
Geom_Number get_width() const noexcept
Get width of this region.
Definition quadnode.H:490
bool is_nw_child() const noexcept
Check if this node is the NW child of its parent.
Definition quadnode.H:378
static QuadNode * get_north_neighbor(QuadNode *v) noexcept
Find the northern neighbor of a node.
Definition quadnode.H:161
QuadNode *& get_nw_child() noexcept
Get reference to NW child (for reading/writing via NW_CHILD macro).
Definition quadnode.H:357
QuadNode & operator=(const QuadNode &)=delete
Point & add_point(const Point &p)
Add a point to this node.
Definition quadnode.H:465
unsigned long level
Depth in the tree (0 for root)
Definition quadnode.H:152
Point * search_point(const Point &p) noexcept
Search for a point in this node.
Definition quadnode.H:508
void for_each_point(Op &op)
Apply operation to each point in this node.
Definition quadnode.H:580
QuadNode(const QuadNode &)=delete
QuadNode * se_child
Southeast child.
Definition quadnode.H:149
bool is_leaf() const noexcept
Check if this node is a leaf (has no children).
Definition quadnode.H:375
DynList< Point > points
Points stored in this node (only for leaves)
Definition quadnode.H:143
bool remove_point(const Point &p)
Remove a point from this node.
Definition quadnode.H:523
Color color
Node state (White/Gray/Black)
Definition quadnode.H:151
size_t get_num_points() noexcept
Get total number of points in this subtree.
Definition quadnode.H:472
const Geom_Number & get_max_x() const noexcept
Get maximum X coordinate of this region.
Definition quadnode.H:481
Color
Node color states for quadtree nodes.
Definition quadnode.H:105
@ White
Empty leaf node.
@ Gray
Internal node with children.
@ Black
Leaf node with points.
QuadNode *& get_parent() noexcept
Get reference to parent node (for reading/writing via PARENT macro).
Definition quadnode.H:354
QuadNode * nw_child
Northwest child.
Definition quadnode.H:146
Singly linked list implementations with head-tail access.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynList< T > maps(const C &c, Op op)
Classic map operation.
2D point and geometric utilities.
#define PARENT(p)
Definition quadnode.H:53
#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