OGS
QuadTree.h
Go to the documentation of this file.
1
15#pragma once
16
17#include <cassert>
18#include <limits>
19#include <list>
20#include <utility>
21
22#include "BaseLib/Logging.h"
23
24namespace GeoLib
25{
37template <typename POINT>
39{
40public:
41 enum class Quadrant
42 {
43 NE = 0,
44 NW,
45 SW,
46 SE
47 };
55 QuadTree(POINT ll, POINT ur, std::size_t max_points_per_leaf)
56 : _father(nullptr),
57 _ll(std::move(ll)),
58 _ur(std::move(ur)),
59 _max_points_per_leaf(max_points_per_leaf)
60 {
61 assert(_max_points_per_leaf > 0);
62
63 if ((_ur[0] - _ll[0]) > (_ur[1] - _ll[1]))
64 {
65 _ur[1] = _ll[1] + _ur[0] - _ll[0];
66 }
67 else
68 {
69 _ur[0] = _ll[0] + _ur[1] - _ll[1];
70 }
71
72 DBUG(
73 "QuadTree(): lower left: ({:f},{:f},{:f}), upper right: "
74 "({:f},{:f},{:f}), depth: {:d}",
75 _ll[0],
76 _ll[1],
77 _ll[2],
78 _ur[0],
79 _ur[1],
80 _ur[2],
81 _depth);
82 }
83
88 {
89 for (auto const& child : _children)
90 {
91 delete child;
92 }
93 }
94
101 bool addPoint(POINT const* pnt)
102 {
103 if ((*pnt)[0] < _ll[0])
104 {
105 return false;
106 }
107 if ((*pnt)[0] >= _ur[0])
108 {
109 return false;
110 }
111 if ((*pnt)[1] < _ll[1])
112 {
113 return false;
114 }
115 if ((*pnt)[1] >= _ur[1])
116 {
117 return false;
118 }
119
120 if (!_is_leaf)
121 {
122 return std::any_of(begin(_children), end(_children),
123 [&pnt](auto* child)
124 { return child->addPoint(pnt); });
125 }
126
127 // check if point is already in quadtree
128 bool pnt_in_quadtree(false);
129 for (std::size_t k(0); k < _pnts.size() && !pnt_in_quadtree; k++)
130 {
131 const double v0((*(_pnts[k]))[0] - (*pnt)[0]);
132 const double v1((*(_pnts[k]))[1] - (*pnt)[1]);
133 const double sqr_dist(v0 * v0 + v1 * v1);
134 if (sqr_dist < std::numeric_limits<double>::epsilon())
135 {
136 pnt_in_quadtree = true;
137 }
138 }
139 if (!pnt_in_quadtree)
140 {
141 _pnts.push_back(pnt);
142 }
143 else
144 {
145 return false;
146 }
147
148 if (_pnts.size() > _max_points_per_leaf)
149 {
150 splitNode();
151 }
152 return true;
153 }
154
162 void balance()
163 {
164 std::list<QuadTree<POINT>*> leaf_list;
165 getLeafs(leaf_list);
166
167 while (!leaf_list.empty())
168 {
169 QuadTree<POINT>* node(leaf_list.front());
170 leaf_list.pop_front();
171
172 if (node->isLeaf())
173 {
174 if (needToRefine(node))
175 {
176 node->splitNode();
177 leaf_list.push_back(node->getChild(Quadrant::NE));
178 leaf_list.push_back(node->getChild(Quadrant::NW));
179 leaf_list.push_back(node->getChild(Quadrant::SW));
180 leaf_list.push_back(node->getChild(Quadrant::SE));
181
182 // check if north neighbor has to be refined
183 QuadTree<POINT>* north_neighbor(node->getNorthNeighbor());
184 if (north_neighbor != nullptr)
185 {
186 if (north_neighbor->getDepth() < node->getDepth())
187 {
188 if (north_neighbor->isLeaf())
189 {
190 leaf_list.push_back(north_neighbor);
191 }
192 }
193 }
194
195 // check if west neighbor has to be refined
196 QuadTree<POINT>* west_neighbor(node->getWestNeighbor());
197 if (west_neighbor != nullptr)
198 {
199 if (west_neighbor->getDepth() < node->getDepth())
200 {
201 if (west_neighbor->isLeaf())
202 {
203 leaf_list.push_back(west_neighbor);
204 }
205 }
206 }
207
208 // check if south neighbor has to be refined
209 QuadTree<POINT>* south_neighbor(node->getSouthNeighbor());
210 if (south_neighbor != nullptr)
211 {
212 if (south_neighbor->getDepth() < node->getDepth())
213 {
214 if (south_neighbor->isLeaf())
215 {
216 leaf_list.push_back(south_neighbor);
217 }
218 }
219 }
220
221 // check if east neighbor has to be refined
222 QuadTree<POINT>* east_neighbor(node->getEastNeighbor());
223 if (east_neighbor != nullptr)
224 {
225 if (east_neighbor->getDepth() < node->getDepth())
226 {
227 if (east_neighbor->isLeaf())
228 {
229 leaf_list.push_back(east_neighbor);
230 }
231 }
232 }
233 }
234 }
235 }
236 }
237
242 void getLeafs(std::list<QuadTree<POINT>*>& leaf_list)
243 {
244 if (_is_leaf)
245 {
246 leaf_list.push_back(this);
247 }
248 else
249 {
250 for (auto& child : _children)
251 {
252 child->getLeafs(leaf_list);
253 }
254 }
255 }
256
257 const std::vector<POINT const*>& getPoints() const { return _pnts; }
258
259 void getSquarePoints(POINT& ll, POINT& ur) const
260 {
261 ll = _ll;
262 ur = _ur;
263 }
264
265 void getLeaf(const POINT& pnt, POINT& ll, POINT& ur)
266 {
267 if (this->isLeaf())
268 {
269 ll = _ll;
270 ur = _ur;
271 }
272 else
273 {
274 if (pnt[0] <= 0.5 * (_ur[0] + _ll[0])) // WEST
275 {
276 if (pnt[1] <= 0.5 * (_ur[1] + _ll[1]))
277 { // SOUTH
278 _children[static_cast<int>(Quadrant::SW)]->getLeaf(pnt, ll,
279 ur);
280 }
281 else
282 { // NORTH
283 _children[static_cast<int>(Quadrant::NW)]->getLeaf(pnt, ll,
284 ur);
285 }
286 }
287 else // EAST
288 {
289 if (pnt[1] <= 0.5 * (_ur[1] + _ll[1]))
290 { // SOUTH
291 _children[static_cast<int>(Quadrant::SE)]->getLeaf(pnt, ll,
292 ur);
293 }
294 else
295 { // NORTH
296 _children[static_cast<int>(Quadrant::NE)]->getLeaf(pnt, ll,
297 ur);
298 }
299 }
300 }
301 }
302
303 QuadTree<POINT> const* getFather() const { return _father; }
304
305 QuadTree<POINT> const* getChild(Quadrant quadrant) const
306 {
307 return _children[quadrant];
308 }
309
316 void getMaxDepth(std::size_t& max_depth) const
317 {
318 if (max_depth < _depth)
319 {
320 max_depth = _depth;
321 }
322
323 for (auto& child : _children)
324 {
325 if (child)
326 {
327 child->getMaxDepth(max_depth);
328 }
329 }
330 }
331
336 std::size_t getDepth() const { return _depth; }
337
338private:
340 {
341 return _children[static_cast<int>(quadrant)];
342 }
343
344 bool isLeaf() const { return _is_leaf; }
345
346 bool isChild(QuadTree<POINT> const* const tree, Quadrant quadrant) const
347 {
348 return _children[static_cast<int>(quadrant)] == tree;
349 }
350
352 {
353 if (this->_father == nullptr)
354 { // root of QuadTree
355 return nullptr;
356 }
357
358 if (this->_father->isChild(this, Quadrant::SW))
359 {
360 return this->_father->getChild(Quadrant::NW);
361 }
362 if (this->_father->isChild(this, Quadrant::SE))
363 {
364 return this->_father->getChild(Quadrant::NE);
365 }
366
367 QuadTree<POINT>* north_neighbor(this->_father->getNorthNeighbor());
368 if (north_neighbor == nullptr)
369 {
370 return nullptr;
371 }
372 if (north_neighbor->isLeaf())
373 {
374 return north_neighbor;
375 }
376
377 if (this->_father->isChild(this, Quadrant::NW))
378 {
379 return north_neighbor->getChild(Quadrant::SW);
380 }
381
382 return north_neighbor->getChild(Quadrant::SE);
383 }
384
386 {
387 if (this->_father == nullptr)
388 { // root of QuadTree
389 return nullptr;
390 }
391
392 if (this->_father->isChild(this, Quadrant::NW))
393 {
394 return this->_father->getChild(Quadrant::SW);
395 }
396 if (this->_father->isChild(this, Quadrant::NE))
397 {
398 return this->_father->getChild(Quadrant::SE);
399 }
400
401 QuadTree<POINT>* south_neighbor(this->_father->getSouthNeighbor());
402 if (south_neighbor == nullptr)
403 {
404 return nullptr;
405 }
406 if (south_neighbor->isLeaf())
407 {
408 return south_neighbor;
409 }
410
411 if (this->_father->isChild(this, Quadrant::SW))
412 {
413 return south_neighbor->getChild(Quadrant::NW);
414 }
415
416 return south_neighbor->getChild(Quadrant::NE);
417 }
418
420 {
421 if (this->_father == nullptr)
422 { // root of QuadTree
423 return nullptr;
424 }
425
426 if (this->_father->isChild(this, Quadrant::NW))
427 {
428 return this->_father->getChild(Quadrant::NE);
429 }
430 if (this->_father->isChild(this, Quadrant::SW))
431 {
432 return this->_father->getChild(Quadrant::SE);
433 }
434
435 QuadTree<POINT>* east_neighbor(this->_father->getEastNeighbor());
436 if (east_neighbor == nullptr)
437 {
438 return nullptr;
439 }
440 if (east_neighbor->isLeaf())
441 {
442 return east_neighbor;
443 }
444
445 if (this->_father->isChild(this, Quadrant::SE))
446 {
447 return east_neighbor->getChild(Quadrant::SW);
448 }
449
450 return east_neighbor->getChild(Quadrant::NW);
451 }
452
454 {
455 if (this->_father == nullptr)
456 { // root of QuadTree
457 return nullptr;
458 }
459
460 if (this->_father->isChild(this, Quadrant::NE))
461 {
462 return this->_father->getChild(Quadrant::NW);
463 }
464 if (this->_father->isChild(this, Quadrant::SE))
465 {
466 return this->_father->getChild(Quadrant::SW);
467 }
468
469 QuadTree<POINT>* west_neighbor(this->_father->getWestNeighbor());
470 if (west_neighbor == nullptr)
471 {
472 return nullptr;
473 }
474 if (west_neighbor->isLeaf())
475 {
476 return west_neighbor;
477 }
478
479 if (this->_father->isChild(this, Quadrant::SW))
480 {
481 return west_neighbor->getChild(Quadrant::SE);
482 }
483
484 return west_neighbor->getChild(Quadrant::NE);
485 }
486
496 POINT ur,
497 QuadTree* father,
498 std::size_t depth,
499 std::size_t max_points_per_leaf)
500 : _father(father),
501 _ll(std::move(ll)),
502 _ur(std::move(ur)),
503 _depth(depth),
504 _max_points_per_leaf(max_points_per_leaf)
505 {
506 }
507
509 {
510 // create children
511 POINT mid_point(_ll);
512 mid_point[0] += (_ur[0] - _ll[0]) / 2.0;
513 mid_point[1] += (_ur[1] - _ll[1]) / 2.0;
514 assert(_children[0] == nullptr);
515 _children[0] = new QuadTree<POINT>(mid_point, _ur, this, _depth + 1,
516 _max_points_per_leaf); // north east
517 POINT h_ll(mid_point), h_ur(mid_point);
518 h_ll[0] = _ll[0];
519 h_ur[1] = _ur[1];
520 assert(_children[1] == nullptr);
521 _children[1] = new QuadTree<POINT>(h_ll, h_ur, this, _depth + 1,
522 _max_points_per_leaf); // north west
523 assert(_children[2] == nullptr);
524 _children[2] = new QuadTree<POINT>(_ll, mid_point, this, _depth + 1,
525 _max_points_per_leaf); // south west
526 h_ll = _ll;
527 h_ll[0] = mid_point[0];
528 h_ur = _ur;
529 h_ur[1] = mid_point[1];
530 assert(_children[3] == nullptr);
531 _children[3] = new QuadTree<POINT>(h_ll, h_ur, this, _depth + 1,
532 _max_points_per_leaf); // south east
533
534 // distribute points to sub quadtrees
535 for (std::size_t j(0); j < _pnts.size(); j++)
536 {
537 bool nfound(true);
538 for (std::size_t k(0); k < 4 && nfound; k++)
539 {
540 if (_children[k]->addPoint(_pnts[j]))
541 {
542 nfound = false;
543 }
544 }
545 }
546 _pnts.clear();
547 _is_leaf = false;
548 }
549
550 static bool needToRefine(QuadTree<POINT> const* const node)
551 {
552 QuadTree<POINT>* north_neighbor(node->getNorthNeighbor());
553 if (north_neighbor != nullptr)
554 {
555 if (north_neighbor->getDepth() == node->getDepth())
556 {
557 if (!north_neighbor->isLeaf())
558 {
559 if (!(north_neighbor->getChild(Quadrant::SW))->isLeaf())
560 {
561 return true;
562 }
563 if (!(north_neighbor->getChild(Quadrant::SE))->isLeaf())
564 {
565 return true;
566 }
567 }
568 }
569 }
570
571 QuadTree<POINT>* west_neighbor(node->getWestNeighbor());
572 if (west_neighbor != nullptr)
573 {
574 if (west_neighbor->getDepth() == node->getDepth())
575 {
576 if (!west_neighbor->isLeaf())
577 {
578 if (!(west_neighbor->getChild(Quadrant::SE))->isLeaf())
579 {
580 return true;
581 }
582 if (!(west_neighbor->getChild(Quadrant::NE))->isLeaf())
583 {
584 return true;
585 }
586 }
587 }
588 }
589
590 QuadTree<POINT>* south_neighbor(node->getSouthNeighbor());
591 if (south_neighbor != nullptr)
592 {
593 if (south_neighbor->getDepth() == node->getDepth())
594 {
595 if (!south_neighbor->isLeaf())
596 {
597 if (!(south_neighbor->getChild(Quadrant::NE))->isLeaf())
598 {
599 return true;
600 }
601 if (!(south_neighbor->getChild(Quadrant::NW))->isLeaf())
602 {
603 return true;
604 }
605 }
606 }
607 }
608
609 QuadTree<POINT>* east_neighbor(node->getEastNeighbor());
610 if (east_neighbor != nullptr)
611 {
612 if (east_neighbor->getDepth() == node->getDepth())
613 {
614 if (!east_neighbor->isLeaf())
615 {
616 if (!(east_neighbor->getChild(Quadrant::NW))->isLeaf())
617 {
618 return true;
619 }
620 if (!(east_neighbor->getChild(Quadrant::SW))->isLeaf())
621 {
622 return true;
623 }
624 }
625 }
626 }
627 return false;
628 }
629
638 std::array<QuadTree<POINT>*, 4> _children = {nullptr, nullptr, nullptr,
639 nullptr};
648 std::size_t _depth = 0;
649 std::vector<POINT const*> _pnts;
650 bool _is_leaf = true;
654 const std::size_t _max_points_per_leaf;
655};
656} // namespace GeoLib
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:30
QuadTree< POINT > * _father
Definition QuadTree.h:630
QuadTree< POINT > * getNorthNeighbor() const
Definition QuadTree.h:351
bool isChild(QuadTree< POINT > const *const tree, Quadrant quadrant) const
Definition QuadTree.h:346
static bool needToRefine(QuadTree< POINT > const *const node)
Definition QuadTree.h:550
QuadTree< POINT > const * getChild(Quadrant quadrant) const
Definition QuadTree.h:305
std::array< QuadTree< POINT > *, 4 > _children
Definition QuadTree.h:638
bool isLeaf() const
Definition QuadTree.h:344
QuadTree< POINT > const * getFather() const
Definition QuadTree.h:303
std::size_t getDepth() const
Definition QuadTree.h:336
void getMaxDepth(std::size_t &max_depth) const
Definition QuadTree.h:316
void getLeafs(std::list< QuadTree< POINT > * > &leaf_list)
Definition QuadTree.h:242
const std::vector< POINT const * > & getPoints() const
Definition QuadTree.h:257
QuadTree< POINT > * getWestNeighbor() const
Definition QuadTree.h:453
const std::size_t _max_points_per_leaf
Definition QuadTree.h:654
std::vector< POINT const * > _pnts
Definition QuadTree.h:649
void getLeaf(const POINT &pnt, POINT &ll, POINT &ur)
Definition QuadTree.h:265
QuadTree< POINT > * getSouthNeighbor() const
Definition QuadTree.h:385
bool addPoint(POINT const *pnt)
Definition QuadTree.h:101
QuadTree< POINT > * getChild(Quadrant quadrant)
Definition QuadTree.h:339
QuadTree< POINT > * getEastNeighbor() const
Definition QuadTree.h:419
std::size_t _depth
Definition QuadTree.h:648
void getSquarePoints(POINT &ll, POINT &ur) const
Definition QuadTree.h:259
QuadTree(POINT ll, POINT ur, QuadTree *father, std::size_t depth, std::size_t max_points_per_leaf)
Definition QuadTree.h:495
QuadTree(POINT ll, POINT ur, std::size_t max_points_per_leaf)
Definition QuadTree.h:55