mdds
point_quad_tree.hpp
1 /*************************************************************************
2  *
3  * Copyright (c) 2010-2015 Kohei Yoshida
4  *
5  * Permission is hereby granted, free of charge, to any person
6  * obtaining a copy of this software and associated documentation
7  * files (the "Software"), to deal in the Software without
8  * restriction, including without limitation the rights to use,
9  * copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following
12  * conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24  * OTHER DEALINGS IN THE SOFTWARE.
25  *
26  ************************************************************************/
27 
28 #ifndef INCLUDED_MDDS_POINT_QUAD_TREE_HPP
29 #define INCLUDED_MDDS_POINT_QUAD_TREE_HPP
30 
31 #include "mdds/quad_node.hpp"
32 
33 #include <cstdlib>
34 #include <cassert>
35 #include <iostream>
36 #include <fstream>
37 #include <string>
38 #include <vector>
39 #include <memory>
40 
41 #define DEBUG_POINT_QUAD_TREE 0
42 
43 namespace mdds {
44 
45 template<typename _PairType>
46 void ensure_order(_PairType& v)
47 {
48  if (v.first > v.second)
49  ::std::swap(v.first, v.second);
50 }
51 
52 template<typename _Key, typename _NodeType, typename _Inserter>
53 void search_region_node(
54  const _NodeType* p, _Key x1, _Key y1, _Key x2, _Key y2, _Inserter& result)
55 {
56  using namespace std;
57 
58  if (!p)
59  return;
60 
61  search_region_space_t region = ::mdds::get_search_region_space(p, x1, y1, x2, y2);
62 
63  switch (region)
64  {
65  case region_center:
66  result(p);
67  search_region_node(p->northeast.get(), x1, y1, x2, y2, result);
68  search_region_node(p->northwest.get(), x1, y1, x2, y2, result);
69  search_region_node(p->southeast.get(), x1, y1, x2, y2, result);
70  search_region_node(p->southwest.get(), x1, y1, x2, y2, result);
71  break;
72  case region_east:
73  search_region_node(p->northwest.get(), x1, y1, x2, y2, result);
74  search_region_node(p->southwest.get(), x1, y1, x2, y2, result);
75  break;
76  case region_north:
77  search_region_node(p->southeast.get(), x1, y1, x2, y2, result);
78  search_region_node(p->southwest.get(), x1, y1, x2, y2, result);
79  break;
80  case region_northeast:
81  search_region_node(p->southwest.get(), x1, y1, x2, y2, result);
82  break;
83  case region_northwest:
84  search_region_node(p->southeast.get(), x1, y1, x2, y2, result);
85  break;
86  case region_south:
87  search_region_node(p->northeast.get(), x1, y1, x2, y2, result);
88  search_region_node(p->northwest.get(), x1, y1, x2, y2, result);
89  break;
90  case region_southeast:
91  search_region_node(p->northwest.get(), x1, y1, x2, y2, result);
92  break;
93  case region_southwest:
94  search_region_node(p->northeast.get(), x1, y1, x2, y2, result);
95  break;
96  case region_west:
97  search_region_node(p->northeast.get(), x1, y1, x2, y2, result);
98  search_region_node(p->southeast.get(), x1, y1, x2, y2, result);
99  break;
100  default:
101  throw general_error("unknown search region");
102  }
103 }
104 
105 
106 template<typename _Key, typename _Value>
108 {
109 private:
110  class search_result_inserter;
111 
112 public:
113  typedef _Key key_type;
114  typedef _Value value_type;
115  typedef size_t size_type;
116  typedef ::std::vector<value_type> data_array_type;
117 
118  class data_not_found : public ::std::exception {};
119 
120 private:
121  struct node;
122  typedef ::boost::intrusive_ptr<node> node_ptr;
123 
124  struct node : quad_node_base<node_ptr, node, key_type>
125  {
126  value_type data;
127  node(key_type _x, key_type _y, value_type _data) :
129  data(_data) {}
130 
131  node(const node& r) :
133  data(r.data) {}
134 
135  void dispose() {}
136 
137  bool operator== (const node& r) const
138  {
139  return quad_node_base<node_ptr, node, key_type>::operator ==(r) && data == r.data;
140  }
141 
142  node& operator= (const node& r)
143  {
145  data = r.data;
146  return *this;
147  }
148  };
149 
150  typedef ::std::vector<node_ptr> reinsert_tree_array_type;
151  typedef ::std::pair<key_type, key_type> key_range_type;
152 
153 public:
154 
160  {
161  friend class point_quad_tree<_Key,_Value>;
162  public:
163  node_access northeast() const { return node_access(mp->northeast.get()); }
164  node_access northwest() const { return node_access(mp->northwest.get()); }
165  node_access southeast() const { return node_access(mp->southeast.get()); }
166  node_access southwest() const { return node_access(mp->southwest.get()); }
167 
168  value_type data() const { return mp->data; }
169  key_type x() const { return mp->x; }
170  key_type y() const { return mp->y; }
171 
172  operator bool() const { return mp != nullptr; }
173  bool operator== (const node_access& r) const { return mp == r.mp; }
174 
175  node_access& operator= (const node_access& r)
176  {
177  mp = r.mp;
178  return *this;
179  }
180 
181  node_access() : mp(nullptr) {}
182  node_access(const node_access& r) : mp(r.mp) {}
183  ~node_access() {}
184 
185  private:
186  node_access(const node* p) : mp(p) {}
187 
188  private:
189  const node* mp;
190  };
191 
192  struct point
193  {
194  key_type x;
195  key_type y;
196  point(key_type _x, key_type _y) : x(_x), y(_y) {}
197  point() : x(0), y(0) {}
198  };
199 
201  {
202  friend class search_result_inserter;
203 
204  typedef std::vector<const node*> res_nodes_type;
205  typedef std::shared_ptr<res_nodes_type> res_nodes_ptr;
206  public:
207 
209  {
210  friend class point_quad_tree<_Key,_Value>::search_results;
211  typedef typename point_quad_tree<_Key,_Value>::point point;
212  typedef typename point_quad_tree<_Key,_Value>::value_type parent_value_type;
213 
214  public:
215  // Iterator traits
216  typedef std::pair<point, parent_value_type> value_type;
217  typedef value_type* pointer;
218  typedef value_type& reference;
219  typedef ptrdiff_t difference_type;
220  typedef ::std::bidirectional_iterator_tag iterator_category;
221 
222  const_iterator(res_nodes_ptr& ptr) : mp_res_nodes(ptr), m_end_pos(false) {}
223 
224  const_iterator(const const_iterator& r) :
225  mp_res_nodes(r.mp_res_nodes),
226  m_cur_pos(r.m_cur_pos),
227  m_cur_value(r.m_cur_value),
228  m_end_pos(r.m_end_pos) {}
229 
230  const_iterator& operator= (const const_iterator& r)
231  {
232  mp_res_nodes = r.mp_res_nodes;
233  m_cur_pos = r.m_cur_pos;
234  m_cur_value = r.m_cur_value;
235  m_end_pos = r.m_end_pos;
236  return *this;
237  }
238 
239  bool operator== (const const_iterator& r) const
240  {
241  if (mp_res_nodes)
242  {
243  // Non-empty result set.
244  return mp_res_nodes.get() == r.mp_res_nodes.get() &&
245  m_cur_pos == r.m_cur_pos && m_end_pos == r.m_end_pos;
246  }
247 
248  // Empty result set.
249  if (r.mp_res_nodes)
250  return false;
251 
252  return m_end_pos == r.m_end_pos;
253  }
254 
255  bool operator!= (const const_iterator& r) const
256  {
257  return !operator==(r);
258  }
259 
260  const value_type& operator*() const
261  {
262  return m_cur_value;
263  }
264 
265  const value_type* operator->() const
266  {
267  return get_current_value();
268  }
269 
270  const value_type* operator++()
271  {
272  // The only difference between the last data position and the
273  // end iterator position must be the value of m_end_pos;
274  // m_cur_pos needs to point to the last data position even
275  // when the iterator is at the end-of-iterator position.
276 
277  typename res_nodes_type::const_iterator cur_pos = m_cur_pos;
278  if (++cur_pos == mp_res_nodes->end())
279  {
280  m_end_pos = true;
281  return nullptr;
282  }
283  m_cur_pos = cur_pos;
284  update_current_value();
285  return operator->();
286  }
287 
288  const value_type* operator--()
289  {
290  if (m_end_pos)
291  {
292  m_end_pos = false;
293  return get_current_value();
294  }
295  --m_cur_pos;
296  update_current_value();
297  return get_current_value();
298  }
299 
300  private:
301  void move_to_front()
302  {
303  if (!mp_res_nodes)
304  {
305  // Empty data set.
306  m_end_pos = true;
307  return;
308  }
309 
310  m_cur_pos = mp_res_nodes->begin();
311  m_end_pos = false;
312  update_current_value();
313  }
314 
315  void move_to_end()
316  {
317  m_end_pos = true;
318  if (!mp_res_nodes)
319  // Empty data set.
320  return;
321 
322  m_cur_pos = mp_res_nodes->end();
323  --m_cur_pos; // Keep the position at the last data position.
324  }
325 
326  void update_current_value()
327  {
328  const node* p = *m_cur_pos;
329  m_cur_value.first = point(p->x, p->y);
330  m_cur_value.second = p->data;
331  }
332 
333  const value_type* get_current_value() const
334  {
335  return &m_cur_value;
336  }
337 
338  private:
339  res_nodes_ptr mp_res_nodes;
340  typename res_nodes_type::const_iterator m_cur_pos;
341  value_type m_cur_value;
342  bool m_end_pos:1;
343  };
344 
345  search_results() : mp_res_nodes(static_cast<res_nodes_type*>(nullptr)) {}
346  search_results(const search_results& r) : mp_res_nodes(r.mp_res_nodes) {}
347 
348  typename search_results::const_iterator begin()
349  {
350  typename search_results::const_iterator itr(mp_res_nodes);
351  itr.move_to_front();
352  return itr;
353  }
354 
355  typename search_results::const_iterator end()
356  {
357  typename search_results::const_iterator itr(mp_res_nodes);
358  itr.move_to_end();
359  return itr;
360  }
361 
362  private:
363  void push_back(const node* p)
364  {
365  if (!mp_res_nodes)
366  mp_res_nodes.reset(new res_nodes_type);
367  mp_res_nodes->push_back(p);
368  }
369 
370  private:
371  res_nodes_ptr mp_res_nodes;
372  };
373 
374  point_quad_tree();
376  ~point_quad_tree();
377 
386  void insert(key_type x, key_type y, value_type data);
387 
400  void search_region(key_type x1, key_type y1, key_type x2, key_type y2, data_array_type& result) const;
401 
415  search_results search_region(key_type x1, key_type y1, key_type x2, key_type y2) const;
416 
427  value_type find(key_type x, key_type y) const;
428 
436  void remove(key_type x, key_type y);
437 
443  void swap(point_quad_tree& r);
444 
448  void clear();
449 
455  bool empty() const;
456 
462  size_t size() const;
463 
469  node_access get_node_access() const;
470 
471  point_quad_tree& operator= (const point_quad_tree& r);
472 
473  bool operator== (const point_quad_tree& r) const;
474 
475  bool operator!= (const point_quad_tree& r) const { return !operator== (r); }
476 
477 #ifdef MDDS_UNIT_TEST
478 public:
479 #else
480 private:
481 #endif
482 
486  struct node_data
487  {
488  key_type x;
489  key_type y;
490  value_type data;
491  node_data(key_type _x, key_type _y, value_type _data) :
492  x(_x), y(_y), data(_data) {}
493  node_data(const node_data& r) :
494  x(r.x), y(r.y), data(r.data) {}
495 
496  bool operator== (const node_data& r) const
497  {
498  return (x == r.x) && (y == r.y) && (data == r.data);
499  }
500 
501  bool operator!= (const node_data& r) const
502  {
503  return !operator==(r);
504  }
505 
506  struct sorter : public ::std::binary_function<node_data, node_data, bool>
507  {
508  bool operator() (const node_data& left, const node_data& right) const
509  {
510  if (left.x != right.x)
511  return left.x < right.x;
512  if (left.y != right.y)
513  return left.y < right.y;
514  return left.data < right.data;
515  }
516  };
517  };
518 
519  static bool equals(::std::vector<node_data>& v1, ::std::vector<node_data>& v2);
520 
521  bool verify_data(::std::vector<node_data>& expected) const;
522 
523  bool verify_node_iterator(const node_access& nac) const;
524  static bool verify_node_iterator(const node_access& nac, const node* p);
525 
526  void get_all_stored_data(::std::vector<node_data>& stored_data) const;
527 
528  void dump_tree_svg(const ::std::string& fpath) const;
529 
530 private:
531  class array_inserter : public ::std::unary_function<const node*, void>
532  {
533  public:
534  array_inserter(data_array_type& result) : m_result(result) {}
535 
536  void operator() (const node* p)
537  {
538  m_result.push_back(p->data);
539  }
540  private:
541  data_array_type& m_result;
542  };
543 
544  class search_result_inserter : public ::std::unary_function<const node*, void>
545  {
546  public:
547  search_result_inserter(search_results& result) : m_result(result) {}
548 
549  void operator() (const node* p)
550  {
551  m_result.push_back(p);
552  }
553  private:
554  search_results& m_result;
555  };
556 
557  class data_inserter : public ::std::unary_function<node_data, void>
558  {
559  public:
560  data_inserter(point_quad_tree& db) : m_db(db) {}
561 
562  void operator() (const node_data& v)
563  {
564  m_db.insert(v.x, v.y, v.data);
565  }
566  private:
567  point_quad_tree& m_db;
568  };
569 
570  struct node_distance
571  {
572  node_quadrant_t quad;
573  key_type dist;
574  node_ptr node;
575 
576  node_distance() : quad(quad_unspecified), dist(0), node(nullptr) {}
577  node_distance(node_quadrant_t _quad, key_type _dist, const node_ptr& _node) :
578  quad(_quad), dist(_dist), node(_node) {}
579  };
580 
581  node_ptr find_node(key_type x, key_type y) const;
582  const node* find_node_ptr(key_type x, key_type y) const;
583  node_ptr find_replacement_node(key_type x, key_type y, const node_ptr& delete_node) const;
584 
585  void find_candidate_in_quad(key_type x, key_type y,
586  node_distance& dx_node, node_distance& dy_node, node_distance& min_city_block_node,
587  const node_ptr& delete_node, node_quadrant_t quad) const;
588 
589  void adjust_quad(const key_range_type& hatched_xrange, const key_range_type& hatched_yrange,
590  node_ptr quad_root, direction_t dir, reinsert_tree_array_type& insert_list);
591 
592  void set_new_root(const key_range_type& hatched_xrange, const key_range_type& hatched_yrange,
593  node_ptr& quad_root, node_quadrant_t dir, reinsert_tree_array_type& insert_list);
594 
595  void insert_node(node_ptr& dest, node_ptr& node);
596  void reinsert_tree(node_ptr& dest, node_ptr& root);
597  void reinsert_tree(node_ptr& dest, node_quadrant_t quad, node_ptr& root);
598  void clear_all_nodes();
599  void dump_node_svg(const node* p, ::std::ofstream& file) const;
600  void count_all_nodes(const node* p, size_t& node_count) const;
601  void insert_data_from(const point_quad_tree& r);
602  void get_all_stored_data(const node* p, ::std::vector<node_data>& stored_data) const;
603 
604 private:
605  node_ptr m_root;
606 
607  key_range_type m_xrange;
608  key_range_type m_yrange;
609 };
610 
611 template<typename _Key, typename _Value>
613  m_root(nullptr),
614  m_xrange(0,0),
615  m_yrange(0,0)
616 {
617 }
618 
619 template<typename _Key, typename _Value>
621  m_root(nullptr),
622  m_xrange(0,0),
623  m_yrange(0,0)
624 {
625  insert_data_from(r);
626 }
627 
628 template<typename _Key, typename _Value>
630 {
631  clear_all_nodes();
632 }
633 
634 template<typename _Key, typename _Value>
635 void point_quad_tree<_Key,_Value>::insert(key_type x, key_type y, value_type data)
636 {
637  m_xrange.first = ::std::min(m_xrange.first, x);
638  m_xrange.second = ::std::max(m_xrange.second, x);
639  m_yrange.first = ::std::min(m_yrange.first, y);
640  m_yrange.second = ::std::max(m_yrange.second, y);
641 
642  if (!m_root)
643  {
644  // The very first node.
645  m_root.reset(new node(x, y, data));
646  return;
647  }
648 
649  node_ptr cur_node = m_root;
650  while (true)
651  {
652  if (cur_node->x == x && cur_node->y == y)
653  {
654  // Replace the current data with this, and we are done!
655  cur_node->data = data;
656  return;
657  }
658 
659  node_quadrant_t quad = cur_node->get_quadrant(x, y);
660  switch (quad)
661  {
662  case quad_northeast:
663  if (cur_node->northeast)
664  cur_node = cur_node->northeast;
665  else
666  {
667  cur_node->northeast.reset(new node(x, y, data));
668  cur_node->northeast->parent = cur_node;
669  return;
670  }
671  break;
672  case quad_northwest:
673  if (cur_node->northwest)
674  cur_node = cur_node->northwest;
675  else
676  {
677  cur_node->northwest.reset(new node(x, y, data));
678  cur_node->northwest->parent = cur_node;
679  return;
680  }
681  break;
682  case quad_southeast:
683  if (cur_node->southeast)
684  cur_node = cur_node->southeast;
685  else
686  {
687  cur_node->southeast.reset(new node(x, y, data));
688  cur_node->southeast->parent = cur_node;
689  return;
690  }
691  break;
692  case quad_southwest:
693  if (cur_node->southwest)
694  cur_node = cur_node->southwest;
695  else
696  {
697  cur_node->southwest.reset(new node(x, y, data));
698  cur_node->southwest->parent = cur_node;
699  return;
700  }
701  break;
702  default:
703  throw general_error("unknown quadrant");
704  }
705  }
706  assert(!"This should never be reached.");
707 }
708 
709 template<typename _Key, typename _Value>
710 void point_quad_tree<_Key,_Value>::search_region(key_type x1, key_type y1, key_type x2, key_type y2, data_array_type& result) const
711 {
712  using namespace std;
713  const node* p = m_root.get();
714  array_inserter _inserter(result);
715  ::mdds::search_region_node(p, x1, y1, x2, y2, _inserter);
716 }
717 
718 template<typename _Key, typename _Value>
720 point_quad_tree<_Key,_Value>::search_region(key_type x1, key_type y1, key_type x2, key_type y2) const
721 {
722  using namespace std;
723  search_results result;
724  const node* p = m_root.get();
725  search_result_inserter _inserter(result);
726  ::mdds::search_region_node(p, x1, y1, x2, y2, _inserter);
727  return result;
728 }
729 
730 template<typename _Key, typename _Value>
731 typename point_quad_tree<_Key,_Value>::value_type
732 point_quad_tree<_Key,_Value>::find(key_type x, key_type y) const
733 {
734  const node* p = find_node_ptr(x, y);
735  if (!p)
736  throw data_not_found();
737  return p->data;
738 }
739 
740 template<typename _Key, typename _Value>
741 void point_quad_tree<_Key,_Value>::remove(key_type x, key_type y)
742 {
743  using namespace std;
744  node_ptr delete_node = find_node(x, y);
745  if (!delete_node)
746  // No node exists at this coordinate.
747  return;
748 
749 #if DEBUG_POINT_QUAD_TREE
750  cout << "found the node to be removed at " << delete_node->x << "," << delete_node->y << " (" << *delete_node->data << ")" << endl;
751 #endif
752 
753  // Check if this is a leaf node, in which case we can just delete it
754  // without further processing.
755  if (delete_node->leaf())
756  {
757 #if DEBUG_POINT_QUAD_TREE
758  cout << "deleting a leaf node." << endl;
759 #endif
760  if (delete_node.get() == m_root.get())
761  m_root.reset();
762  else
763  disconnect_node_from_parent(delete_node);
764  delete_node.reset();
765  return;
766  }
767 
768  node_ptr repl_node = find_replacement_node(x, y, delete_node);
769  if (!repl_node)
770  // Non-leaf node should have at least one replacement candidate.
771  throw general_error("failed to find a replacement candidate node.");
772 
773  node_quadrant_t repl_quad = delete_node->get_quadrant(repl_node->x, repl_node->y);
774 
775  key_range_type xrange(delete_node->x, repl_node->x);
776  key_range_type yrange(delete_node->y, repl_node->y);
777  ensure_order(xrange);
778  ensure_order(yrange);
779  reinsert_tree_array_type insert_list;
780 
781  // Call the quadrant where the replacement node is quadrant I. Adjust the
782  // quadrants adjacent to quadrant I first, then adjust quadrant I
783  // afterwards.
784  switch (repl_quad)
785  {
786  case quad_northeast:
787  adjust_quad(xrange, yrange, delete_node->northwest, dir_south, insert_list);
788  adjust_quad(xrange, yrange, delete_node->southeast, dir_west, insert_list);
789  set_new_root(xrange, yrange, delete_node->northeast, quad_southwest, insert_list);
790  break;
791  case quad_northwest:
792  adjust_quad(xrange, yrange, delete_node->northeast, dir_south, insert_list);
793  adjust_quad(xrange, yrange, delete_node->southwest, dir_east, insert_list);
794  set_new_root(xrange, yrange, delete_node->northwest, quad_southeast, insert_list);
795  break;
796  case quad_southeast:
797  adjust_quad(xrange, yrange, delete_node->northeast, dir_west, insert_list);
798  adjust_quad(xrange, yrange, delete_node->southwest, dir_north, insert_list);
799  set_new_root(xrange, yrange, delete_node->southeast, quad_northwest, insert_list);
800  break;
801  case quad_southwest:
802  adjust_quad(xrange, yrange, delete_node->northwest, dir_east, insert_list);
803  adjust_quad(xrange, yrange, delete_node->southeast, dir_north, insert_list);
804  set_new_root(xrange, yrange, delete_node->southwest, quad_northeast, insert_list);
805  break;
806  default:
807  throw general_error("quadrant for the replacement node is unspecified.");
808  }
809 
810  // Reinsert all child nodes from the replacement node into the node to be
811  // "deleted".
812  switch (repl_quad)
813  {
814  case quad_northeast:
815  case quad_southwest:
816  {
817  node_ptr root = repl_node->northwest;
818  repl_node->northwest.reset();
819  reinsert_tree(delete_node, quad_northwest, root);
820 
821  root = repl_node->southeast;
822  repl_node->southeast.reset();
823  reinsert_tree(delete_node, quad_southeast, root);
824  }
825  break;
826  case quad_northwest:
827  case quad_southeast:
828  {
829  node_ptr root = repl_node->northeast;
830  repl_node->northeast.reset();
831  reinsert_tree(delete_node, quad_northeast, root);
832 
833  root = repl_node->southwest;
834  repl_node->southwest.reset();
835  reinsert_tree(delete_node, quad_southwest, root);
836  }
837  break;
838  default:
839  throw general_error("quadrant for the replacement node is unspecified.");
840  }
841 
842  // Finally, replace the node to be removed with the replacement node.
843  delete_node->x = repl_node->x;
844  delete_node->y = repl_node->y;
845  delete_node->data = repl_node->data;
846 
847  // Reset the parent node.
848  delete_node->parent = repl_node->parent;
849  repl_node->parent.reset();
850 
851  switch (repl_quad)
852  {
853  case quad_northeast:
854  delete_node->northeast = repl_node->northeast;
855  repl_node->northeast.reset();
856  break;
857  case quad_northwest:
858  delete_node->northwest = repl_node->northwest;
859  repl_node->northwest.reset();
860  break;
861  case quad_southeast:
862  delete_node->southeast = repl_node->southeast;
863  repl_node->southeast.reset();
864  break;
865  case quad_southwest:
866  delete_node->southwest = repl_node->southwest;
867  repl_node->southwest.reset();
868  break;
869  default:
870  throw general_error("quadrant for the replacement node is unspecified.");
871  }
872 
873  // Lastly, re-insert all those trees that have been cut during the quad
874  // adjustment into the new root.
875  typename reinsert_tree_array_type::iterator
876  itr = insert_list.begin(), itr_end = insert_list.end();
877  for (; itr != itr_end; ++itr)
878  reinsert_tree(delete_node, *itr);
879 }
880 
881 template<typename _Key, typename _Value>
883 {
884  m_root.swap(r.m_root);
885  ::std::swap(m_xrange, r.m_xrange);
886  ::std::swap(m_yrange, r.m_yrange);
887 }
888 
889 template<typename _Key, typename _Value>
891 {
892  clear_all_nodes();
893 }
894 
895 template<typename _Key, typename _Value>
897 {
898  return (m_root.get() == nullptr);
899 }
900 
901 template<typename _Key, typename _Value>
903 {
904  size_t node_count = 0;
905  count_all_nodes(m_root.get(), node_count);
906  return node_count;
907 }
908 
909 template<typename _Key, typename _Value>
912 {
913  return node_access(m_root.get());
914 }
915 
916 template<typename _Key, typename _Value>
918 {
919  m_xrange = key_range_type(0, 0);
920  m_yrange = key_range_type(0, 0);
921  clear_all_nodes();
922  insert_data_from(r);
923  return *this;
924 }
925 
926 template<typename _Key, typename _Value>
928 {
929  ::std::vector<node_data> v1, v2;
930  get_all_stored_data(v1);
931  r.get_all_stored_data(v2);
932  return equals(v1, v2);
933 }
934 
935 template<typename _Key, typename _Value>
936 void point_quad_tree<_Key,_Value>::dump_tree_svg(const ::std::string& fpath) const
937 {
938  using namespace std;
939  ofstream file(fpath.c_str());
940  file << "<svg width=\"60cm\" height=\"60cm\" viewBox=\"-2 -2 202 202\" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">" << endl;
941  file << "<defs>"
942  << " <marker id=\"Triangle\""
943  << " viewBox=\"0 0 10 10\" refX=\"10\" refY=\"5\" "
944  << " markerUnits=\"strokeWidth\""
945  << " markerWidth=\"9\" markerHeight=\"6\""
946  << " orient=\"auto\">"
947  << " <path d=\"M 0 0 L 10 5 L 0 10 z\" />"
948  << " </marker>"
949  << "</defs>" << endl;
950 
951  file << "<path d=\"M 0 0 L 0 " << m_yrange.second + 1 << "\" stroke=\"blue\" stroke-width=\"0.2\" marker-end=\"url(#Triangle)\"/>" << endl;
952  file << "<path d=\"M 0 0 L " << m_xrange.second + 1 << " 0\" stroke=\"blue\" stroke-width=\"0.2\" marker-end=\"url(#Triangle)\"/>" << endl;
953  dump_node_svg(m_root.get(), file);
954  file << "</svg>" << endl;
955 }
956 
957 template<typename _NodePtr>
958 void draw_svg_arrow(::std::ofstream& file, const _NodePtr start, const _NodePtr end)
959 {
960  using namespace std;
961  file << "<g stroke=\"red\" marker-end=\"url(#Triangle)\">" << endl;
962  file << "<line x1=\"" << start->x << "\" y1=\"" << start->y << "\" x2=\""
963  << end->x << "\" y2=\"" << end->y << "\" stroke-width=\"0.2\"/>" << endl;
964  file << "</g>" << endl;
965 }
966 
967 template<typename _Key, typename _Value>
968 void point_quad_tree<_Key,_Value>::dump_node_svg(const node* p, ::std::ofstream& file) const
969 {
970  using namespace std;
971 
972  if (!p)
973  return;
974 
975  file << "<circle cx=\"" << p->x << "\" cy=\"" << p->y << "\" r=\"0.1\""
976  << " fill=\"black\" stroke=\"black\"/>" << endl;
977  file << "<text x=\"" << p->x + 1 << "\" y=\"" << p->y + 2 << "\" font-size=\"1.2\" fill=\"black\">"
978  << *p->data << " (" << p->x << "," << p->y << ")</text>" << endl;
979 
980  if (p->northwest)
981  draw_svg_arrow<const node*>(file, p, p->northwest.get());
982 
983  if (p->northeast)
984  draw_svg_arrow<const node*>(file, p, p->northeast.get());
985 
986  if (p->southwest)
987  draw_svg_arrow<const node*>(file, p, p->southwest.get());
988 
989  if (p->southeast)
990  draw_svg_arrow<const node*>(file, p, p->southeast.get());
991 
992  dump_node_svg(p->northeast.get(), file);
993  dump_node_svg(p->northwest.get(), file);
994  dump_node_svg(p->southeast.get(), file);
995  dump_node_svg(p->southwest.get(), file);
996 }
997 
998 template<typename _Key, typename _Value>
999 bool point_quad_tree<_Key,_Value>::equals(::std::vector<node_data>& v1, ::std::vector<node_data>& v2)
1000 {
1001  using namespace std;
1002 
1003  if (v1.size() != v2.size())
1004  return false;
1005 
1006  sort(v1.begin(), v1.end(), typename node_data::sorter());
1007  sort(v2.begin(), v2.end(), typename node_data::sorter());
1008 
1009  typename vector<node_data>::const_iterator
1010  itr1 = v1.begin(), itr1_end = v1.end(), itr2 = v2.begin(), itr2_end = v2.end();
1011 
1012  for (; itr1 != itr1_end; ++itr1, ++itr2)
1013  {
1014  if (itr2 == itr2_end)
1015  return false;
1016 
1017  if (*itr1 != *itr2)
1018  return false;
1019  }
1020  if (itr2 != itr2_end)
1021  return false;
1022 
1023  return true;
1024 }
1025 
1026 template<typename _Key, typename _Value>
1027 void point_quad_tree<_Key,_Value>::get_all_stored_data(::std::vector<node_data>& stored_data) const
1028 {
1029  stored_data.clear();
1030  if (!m_root)
1031  return;
1032 
1033  get_all_stored_data(m_root.get(), stored_data);
1034 }
1035 
1036 template<typename _Key, typename _Value>
1037 void point_quad_tree<_Key,_Value>::count_all_nodes(const node* p, size_t& node_count) const
1038 {
1039  if (!p)
1040  return;
1041 
1042  ++node_count;
1043 
1044  count_all_nodes(p->northeast.get(), node_count);
1045  count_all_nodes(p->northwest.get(), node_count);
1046  count_all_nodes(p->southeast.get(), node_count);
1047  count_all_nodes(p->southwest.get(), node_count);
1048 }
1049 
1050 template<typename _Key, typename _Value>
1052 {
1053  using namespace std;
1054  vector<node_data> all_data;
1055  r.get_all_stored_data(all_data);
1056  for_each(all_data.begin(), all_data.end(), data_inserter(*this));
1057 }
1058 
1059 template<typename _Key, typename _Value>
1060 bool point_quad_tree<_Key,_Value>::verify_data(::std::vector<node_data>& expected) const
1061 {
1062  ::std::vector<node_data> stored;
1063  get_all_stored_data(stored);
1064  return equals(stored, expected);
1065 }
1066 
1067 template<typename _Key, typename _Value>
1069 {
1070  return verify_node_iterator(nac, m_root.get());
1071 }
1072 
1073 template<typename _Key, typename _Value>
1075 {
1076  if (!nac)
1077  return (p == nullptr);
1078 
1079  if (!p)
1080  return false;
1081 
1082  if (!verify_node_iterator(nac.northeast(), p->northeast.get()))
1083  return false;
1084  if (!verify_node_iterator(nac.northwest(), p->northwest.get()))
1085  return false;
1086  if (!verify_node_iterator(nac.southeast(), p->southeast.get()))
1087  return false;
1088  if (!verify_node_iterator(nac.southwest(), p->southwest.get()))
1089  return false;
1090 
1091  return true;
1092 }
1093 
1094 template<typename _Key, typename _Value>
1095 void point_quad_tree<_Key,_Value>::get_all_stored_data(const node* p, ::std::vector<node_data>& stored_data) const
1096 {
1097  if (!p)
1098  return;
1099 
1100  stored_data.push_back(node_data(p->x, p->y, p->data));
1101 
1102  get_all_stored_data(p->northeast.get(), stored_data);
1103  get_all_stored_data(p->northwest.get(), stored_data);
1104  get_all_stored_data(p->southeast.get(), stored_data);
1105  get_all_stored_data(p->southwest.get(), stored_data);
1106 }
1107 
1108 template<typename _Key, typename _Value>
1109 typename point_quad_tree<_Key,_Value>::node_ptr
1110 point_quad_tree<_Key,_Value>::find_node(key_type x, key_type y) const
1111 {
1112  node_ptr cur_node = m_root;
1113  while (cur_node)
1114  {
1115  if (cur_node->x == x && cur_node->y == y)
1116  {
1117  // Found the node.
1118  return cur_node;
1119  }
1120 
1121  node_quadrant_t quad = cur_node->get_quadrant(x, y);
1122  switch (quad)
1123  {
1124  case quad_northeast:
1125  if (!cur_node->northeast)
1126  return node_ptr();
1127  cur_node = cur_node->northeast;
1128  break;
1129  case quad_northwest:
1130  if (!cur_node->northwest)
1131  return node_ptr();
1132  cur_node = cur_node->northwest;
1133  break;
1134  case quad_southeast:
1135  if (!cur_node->southeast)
1136  return node_ptr();
1137  cur_node = cur_node->southeast;
1138  break;
1139  case quad_southwest:
1140  if (!cur_node->southwest)
1141  return node_ptr();
1142  cur_node = cur_node->southwest;
1143  break;
1144  default:
1145  throw general_error("unknown quadrant");
1146  }
1147  }
1148  return node_ptr();
1149 }
1150 
1151 template<typename _Key, typename _Value>
1152 const typename point_quad_tree<_Key,_Value>::node*
1153 point_quad_tree<_Key,_Value>::find_node_ptr(key_type x, key_type y) const
1154 {
1155  const node* cur_node = m_root.get();
1156  while (cur_node)
1157  {
1158  if (cur_node->x == x && cur_node->y == y)
1159  {
1160  // Found the node.
1161  return cur_node;
1162  }
1163 
1164  node_quadrant_t quad = cur_node->get_quadrant(x, y);
1165  switch (quad)
1166  {
1167  case quad_northeast:
1168  if (!cur_node->northeast)
1169  return nullptr;
1170  cur_node = cur_node->northeast.get();
1171  break;
1172  case quad_northwest:
1173  if (!cur_node->northwest)
1174  return nullptr;
1175  cur_node = cur_node->northwest.get();
1176  break;
1177  case quad_southeast:
1178  if (!cur_node->southeast)
1179  return nullptr;
1180  cur_node = cur_node->southeast.get();
1181  break;
1182  case quad_southwest:
1183  if (!cur_node->southwest)
1184  return nullptr;
1185  cur_node = cur_node->southwest.get();
1186  break;
1187  default:
1188  throw general_error("unknown quadrant");
1189  }
1190  }
1191  return nullptr;
1192 }
1193 
1194 template<typename _Key, typename _Value>
1195 typename point_quad_tree<_Key,_Value>::node_ptr
1196 point_quad_tree<_Key,_Value>::find_replacement_node(key_type x, key_type y, const node_ptr& delete_node) const
1197 {
1198  using namespace std;
1199 
1200  // Try to get a replacement candidate in each quadrant.
1201  node_distance dx_node, dy_node, min_city_block_node;
1202 
1203 #if DEBUG_POINT_QUAD_TREE
1204  cout << "northeast" << endl;
1205 #endif
1206  find_candidate_in_quad(
1207  x, y, dx_node, dy_node, min_city_block_node, delete_node, quad_northeast);
1208 
1209 #if DEBUG_POINT_QUAD_TREE
1210  cout << "northwest" << endl;
1211 #endif
1212  find_candidate_in_quad(
1213  x, y, dx_node, dy_node, min_city_block_node, delete_node, quad_northwest);
1214 
1215 #if DEBUG_POINT_QUAD_TREE
1216  cout << "southwest" << endl;
1217 #endif
1218  find_candidate_in_quad(
1219  x, y, dx_node, dy_node, min_city_block_node, delete_node, quad_southwest);
1220 
1221 #if DEBUG_POINT_QUAD_TREE
1222  cout << "southeast" << endl;
1223 #endif
1224  find_candidate_in_quad(
1225  x, y, dx_node, dy_node, min_city_block_node, delete_node, quad_southeast);
1226 
1227  // Check Criterion 1.
1228 
1229 #if DEBUG_POINT_QUAD_TREE
1230  if (dx_node.node)
1231  cout << "node closest to x axis: " << *dx_node.node->data << " (dx=" << dx_node.dist << ")" << endl;
1232 
1233  if (dy_node.node)
1234  cout << "node closest to y axis: " << *dy_node.node->data << " (dy=" << dy_node.dist << ")" << endl;
1235 #endif
1236 
1237  if (dx_node.node == dy_node.node && ((dx_node.quad == quad_northwest) || (dx_node.quad == quad_southeast)))
1238  {
1239 #if DEBUG_POINT_QUAD_TREE
1240  cout << "node that satisfies Criterion 1: " << *dx_node.node->data << endl;
1241 #endif
1242  return dx_node.node;
1243  }
1244  else
1245  {
1246 #if DEBUG_POINT_QUAD_TREE
1247  cout << "unable to find node that satisfies Criterion 1." << endl;
1248 #endif
1249  }
1250 
1251  // Move on to Criterion 2.
1252 
1253  if (min_city_block_node.node)
1254  {
1255 #if DEBUG_POINT_QUAD_TREE
1256  cout << "node that satisfies Criterion 2: " << *min_city_block_node.node->data << " (dist=" << min_city_block_node.dist << ")" << endl;
1257 #endif
1258  return min_city_block_node.node;
1259  }
1260 
1261  return node_ptr();
1262 }
1263 
1264 template<typename _Key, typename _Value>
1266  key_type x, key_type y,
1267  node_distance& dx_node, node_distance& dy_node, node_distance& min_city_block_node,
1268  const node_ptr& delete_node, node_quadrant_t quad) const
1269 {
1270  using namespace std;
1271 
1272  node_ptr repl_node = delete_node->get_quadrant_node(quad);
1273  if (!repl_node)
1274  {
1275  // No candidate in this quadrant.
1276 #if DEBUG_POINT_QUAD_TREE
1277  cout << " no candidate in this quadrant" << endl;
1278 #endif
1279  return;
1280  }
1281 
1282  node_quadrant_t oppo_quad = opposite(quad);
1283  while (repl_node->has_quadrant_node(oppo_quad))
1284  repl_node = repl_node->get_quadrant_node(oppo_quad);
1285 
1286 #if DEBUG_POINT_QUAD_TREE
1287  cout << " candidate: " << repl_node->x << "," << repl_node->y << " (" << *repl_node->data << ")" << endl;
1288 #endif
1289 
1290  // Calculate its distance to each of the borders.
1291  key_type dx = repl_node->x > x ? repl_node->x - x : x - repl_node->x;
1292  key_type dy = repl_node->y > y ? repl_node->y - y : y - repl_node->y;
1293 #if DEBUG_POINT_QUAD_TREE
1294  cout << " dx = " << dx << ", dy = " << dy << endl;
1295 #endif
1296 
1297  if (!dx_node.node || dx_node.dist > dx)
1298  dx_node = node_distance(quad, dx, repl_node);
1299  if (!dy_node.node || dy_node.dist > dy)
1300  dy_node = node_distance(quad, dy, repl_node);
1301 
1302  if (!min_city_block_node.node || min_city_block_node.dist > (dx + dy))
1303  min_city_block_node = node_distance(quad_unspecified, dx+dy, repl_node);
1304 }
1305 
1306 template<typename _Key, typename _Value>
1308  const key_range_type& hatched_xrange, const key_range_type& hatched_yrange,
1309  node_ptr quad_root, direction_t dir, reinsert_tree_array_type& insert_list)
1310 {
1311  using namespace std;
1312 
1313  if (!quad_root)
1314  return;
1315 
1316 #if DEBUG_POINT_QUAD_TREE
1317  cout << "adjust_quad: checking " << *quad_root->data << " (" << quad_root->x << "," << quad_root->y << ")" << endl;
1318 #endif
1319 
1320  if ((hatched_xrange.first <= quad_root->x && quad_root->x <= hatched_xrange.second) ||
1321  (hatched_yrange.first <= quad_root->y && quad_root->y <= hatched_yrange.second))
1322  {
1323 #if DEBUG_POINT_QUAD_TREE
1324  cout << " " << *quad_root->data << " is in the hatched region" << endl;
1325 #endif
1326  // Insert the whole tree, including the root, into the insert list.
1327  disconnect_node_from_parent(quad_root);
1328  quad_root->parent.reset();
1329  insert_list.push_back(quad_root);
1330  return;
1331  }
1332 
1333  switch (dir)
1334  {
1335  case dir_east:
1336  adjust_quad(hatched_xrange, hatched_yrange, quad_root->northeast, dir_east, insert_list);
1337  adjust_quad(hatched_xrange, hatched_yrange, quad_root->southeast, dir_east, insert_list);
1338  break;
1339  case dir_north:
1340  adjust_quad(hatched_xrange, hatched_yrange, quad_root->northeast, dir_north, insert_list);
1341  adjust_quad(hatched_xrange, hatched_yrange, quad_root->northwest, dir_north, insert_list);
1342  break;
1343  case dir_south:
1344  adjust_quad(hatched_xrange, hatched_yrange, quad_root->southeast, dir_south, insert_list);
1345  adjust_quad(hatched_xrange, hatched_yrange, quad_root->southwest, dir_south, insert_list);
1346  break;
1347  case dir_west:
1348  adjust_quad(hatched_xrange, hatched_yrange, quad_root->northwest, dir_west, insert_list);
1349  adjust_quad(hatched_xrange, hatched_yrange, quad_root->southwest, dir_west, insert_list);
1350  break;
1351  default:
1352  ;
1353  }
1354 }
1355 
1356 template<typename _Key, typename _Value>
1358  const key_range_type& hatched_xrange, const key_range_type& hatched_yrange,
1359  node_ptr& quad_root, node_quadrant_t dir, reinsert_tree_array_type& insert_list)
1360 {
1361  node_ptr cur_node = quad_root;
1362  while (cur_node)
1363  {
1364  switch (dir)
1365  {
1366  case quad_northeast:
1367  adjust_quad(hatched_xrange, hatched_yrange, cur_node->southeast, dir_east, insert_list);
1368  adjust_quad(hatched_xrange, hatched_yrange, cur_node->northwest, dir_north, insert_list);
1369  break;
1370  case quad_northwest:
1371  adjust_quad(hatched_xrange, hatched_yrange, cur_node->northeast, dir_north, insert_list);
1372  adjust_quad(hatched_xrange, hatched_yrange, cur_node->southwest, dir_west, insert_list);
1373  break;
1374  case quad_southeast:
1375  adjust_quad(hatched_xrange, hatched_yrange, cur_node->northeast, dir_east, insert_list);
1376  adjust_quad(hatched_xrange, hatched_yrange, cur_node->southwest, dir_south, insert_list);
1377  break;
1378  case quad_southwest:
1379  adjust_quad(hatched_xrange, hatched_yrange, cur_node->northwest, dir_west, insert_list);
1380  adjust_quad(hatched_xrange, hatched_yrange, cur_node->southeast, dir_south, insert_list);
1381  break;
1382  default:
1383  throw general_error("unspecified quadrant");
1384  }
1385  cur_node = cur_node->get_quadrant_node(dir);
1386  }
1387 }
1388 
1389 template<typename _Key, typename _Value>
1390 void point_quad_tree<_Key,_Value>::insert_node(node_ptr& dest, node_ptr& this_node)
1391 {
1392  node_ptr cur_node = dest;
1393  while (true)
1394  {
1395  if (cur_node->x == this_node->x && cur_node->y == this_node->y)
1396  {
1397  // When inserting a node instance directly (likely as part of tree
1398  // re-insertion), we are not supposed to have another node at
1399  // identical position.
1400  throw general_error("node with identical position encountered.");
1401  }
1402 
1403  node_quadrant_t quad = cur_node->get_quadrant(this_node->x, this_node->y);
1404  switch (quad)
1405  {
1406  case quad_northeast:
1407  if (cur_node->northeast)
1408  cur_node = cur_node->northeast;
1409  else
1410  {
1411  cur_node->northeast = this_node;
1412  this_node->parent = cur_node;
1413  return;
1414  }
1415  break;
1416  case quad_northwest:
1417  if (cur_node->northwest)
1418  cur_node = cur_node->northwest;
1419  else
1420  {
1421  cur_node->northwest = this_node;
1422  this_node->parent = cur_node;
1423  return;
1424  }
1425  break;
1426  case quad_southeast:
1427  if (cur_node->southeast)
1428  cur_node = cur_node->southeast;
1429  else
1430  {
1431  cur_node->southeast = this_node;
1432  this_node->parent = cur_node;
1433  return;
1434  }
1435  break;
1436  case quad_southwest:
1437  if (cur_node->southwest)
1438  cur_node = cur_node->southwest;
1439  else
1440  {
1441  cur_node->southwest = this_node;
1442  this_node->parent = cur_node;
1443  return;
1444  }
1445  break;
1446  default:
1447  throw general_error("unknown quadrant");
1448  }
1449  }
1450  assert(!"This should never be reached.");
1451 }
1452 
1453 template<typename _Key, typename _Value>
1454 void point_quad_tree<_Key,_Value>::reinsert_tree(node_ptr& dest, node_ptr& root)
1455 {
1456  assert(dest); // Destination node should not be null.
1457 
1458  if (!root)
1459  // Nothing to re-insert. Bail out.
1460  return;
1461 
1462  if (root->northeast)
1463  {
1464  reinsert_tree(dest, root->northeast);
1465  root->northeast.reset();
1466  }
1467  if (root->northwest)
1468  {
1469  reinsert_tree(dest, root->northwest);
1470  root->northwest.reset();
1471  }
1472  if (root->southeast)
1473  {
1474  reinsert_tree(dest, root->southeast);
1475  root->southeast.reset();
1476  }
1477  if (root->southwest)
1478  {
1479  reinsert_tree(dest, root->southwest);
1480  root->southwest.reset();
1481  }
1482 
1483  root->parent.reset();
1484  insert_node(dest, root);
1485 }
1486 
1487 template<typename _Key, typename _Value>
1488 void point_quad_tree<_Key,_Value>::reinsert_tree(node_ptr& dest, node_quadrant_t quad, node_ptr& root)
1489 {
1490  if (!root)
1491  // Nothing to re-insert. Bail out.
1492  return;
1493 
1494  switch (quad)
1495  {
1496  case quad_northeast:
1497  if (dest->northeast)
1498  reinsert_tree(dest->northeast, root);
1499  else
1500  {
1501  dest->northeast = root;
1502  root->parent = dest;
1503  }
1504  break;
1505  case quad_northwest:
1506  if (dest->northwest)
1507  reinsert_tree(dest->northwest, root);
1508  else
1509  {
1510  dest->northwest = root;
1511  root->parent = dest;
1512  }
1513  break;
1514  case quad_southeast:
1515  if (dest->southeast)
1516  reinsert_tree(dest->southeast, root);
1517  else
1518  {
1519  dest->southeast = root;
1520  root->parent = dest;
1521  }
1522  break;
1523  case quad_southwest:
1524  if (dest->southwest)
1525  reinsert_tree(dest->southwest, root);
1526  else
1527  {
1528  dest->southwest = root;
1529  root->parent = dest;
1530  }
1531  break;
1532  default:
1533  throw general_error("reinsert_tree: quadrant unspecified");
1534  }
1535 }
1536 
1537 template<typename _Key, typename _Value>
1539 {
1540  ::mdds::disconnect_all_nodes(m_root);
1541  m_root.reset();
1542 }
1543 
1544 }
1545 
1546 #endif
value_type find(key_type x, key_type y) const
Definition: point_quad_tree.hpp:732
void remove(key_type x, key_type y)
Definition: point_quad_tree.hpp:741
Definition: point_quad_tree.hpp:159
void search_region(key_type x1, key_type y1, key_type x2, key_type y2, data_array_type &result) const
Definition: point_quad_tree.hpp:710
void swap(point_quad_tree &r)
Definition: point_quad_tree.hpp:882
Definition: point_quad_tree.hpp:192
Definition: point_quad_tree.hpp:200
Definition: point_quad_tree.hpp:107
void insert(key_type x, key_type y, value_type data)
Definition: point_quad_tree.hpp:635
void clear()
Definition: point_quad_tree.hpp:890
node_access get_node_access() const
Definition: point_quad_tree.hpp:911
Definition: global.hpp:58
Definition: point_quad_tree.hpp:118
size_t size() const
Definition: point_quad_tree.hpp:902
Definition: flat_segment_tree.hpp:46
quad_node_base & operator=(const quad_node_base &r)
Definition: quad_node.hpp:182
Definition: point_quad_tree.hpp:506
bool empty() const
Definition: point_quad_tree.hpp:896
Definition: quad_node.hpp:118