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