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