Aleph-w  1.5a.2
Biblioteca general de algoritmos y estructuras de datos
 Todo Clases Archivos Funciones Variables 'typedefs' Enumeraciones Amigas Grupos Páginas
tpl_2dtree.H
1 # ifndef TPL_2DTREE_H
2 # define TPL_2DTREE_H
3 
4 # include <point.H>
5 # include <htlist.H>
6 # include <tpl_nodePool.H>
7 
16  template <typename T = Empty_Class>
17 class K2Tree
18 {
19  struct Node
20  {
21  Point point; // the point
22  Rectangle rect; // the axis-aligned rectangle corresponding to this node
23  Node * lb; // the left/bottom subtree
24  Node * rt; // the right/top subtree
25 
26  Node(const Point & __point) : point(__point), lb(NULL), rt(NULL)
27  {
28  // empty
29  }
30 
31  void set_rect(const Geom_Number & xmin, const Geom_Number & ymin,
32  const Geom_Number & xmax, const Geom_Number & ymax)
33  {
34  rect.set_rect(xmin, ymin, xmax, ymax);
35  }
36 
37  void set_rect(const Point & pmin, const Point & pmax)
38  {
39  rect.set_rect(pmin.get_x(), pmin.get_y(), pmax.get_x(), pmax.get_y());
40  }
41 
42  const Geom_Number & xmin() const { return rect.get_xmin(); }
43  const Geom_Number & ymin() const { return rect.get_ymin(); }
44  const Geom_Number & xmax() const { return rect.get_xmax(); }
45  const Geom_Number & ymax() const { return rect.get_ymax(); }
46  const Geom_Number & x() const { return point.get_x(); }
47  const Geom_Number & y() const { return point.get_y(); }
48  };
49 
50  Point pmin; // esquina inferior izquierda del rectángulo de referencia
51  Point pmax; // esquina superior derecha del rectángulo de referencia
52  size_t N; // número de puntos que maneja el árbol
53  Node * root; // raíz del árbol
54 
55  static const size_t dim = 19;
56  Node_Pool<Node> node_pool;
57 
58 public:
59 
60  K2Tree() : pmin(0, 0), pmax(0, 0), node_pool(dim) { /* empty */ }
61 
62  K2Tree(const Point & __pmin, const Point & __pmax)
63  : pmin(__pmin), pmax(__pmax), node_pool(dim)
64  {
65  /* empty */
66  }
67 
68  K2Tree(const Geom_Number & xmin, const Geom_Number & ymin,
69  const Geom_Number & xmax, const Geom_Number & ymax)
70  : pmin(xmin, ymin), pmax(xmax, ymax), node_pool(dim)
71  {
72  /* empty */
73  }
74 
76  bool is_empty() const { return N == 0; }
77 
79  size_t size() const { return N; }
80 
81 private:
82 
83  static Node * lr_insert(Node * root, const Point & p)
84  {
85  if (root == NULL)
86  return new Point (p);
87 
88  Node * ret_val = NULL;
89  if (p.get_x() == root->x())
90  {
91  if (p.get_y() == root->y())
92  return NULL; // duplicated point
93 
94  ret_val = bu_insert(root->rt, p);
95  if (ret_val != NULL)
96  {
97  root->rt = ret_val; // node was inserted
98  root->rt->set_rect(root->x(), root->ymin(),
99  root->xmax(), root->ymax());
100 
101  return root;
102  }
103 
104  return NULL;
105  }
106 
107  if (p.get_x() < root->x())
108  {
109  ret_val = bu_insert(root->lb, p);
110  if (ret_val != NULL)
111  {
112  root->lb = ret_val;
113  root->lb->set_rect(root->xmin(), root->ymin(),
114  root->x(), root->ymax());
115 
116  return root;
117  }
118  else
119  return NULL;
120  }
121 
122  ret_val = bu_insert(root->rt, p);
123  if (ret_val != NULL)
124  {
125  root->rt = ret_val;
126  root->rt->set_rect(root->x(), root->ymin(),
127  root->xmax(), root->ymax());
128 
129  return root;
130  }
131 
132  return NULL;
133  }
134 
135  static Node * bu_insert(Node * root, const Point & p)
136  {
137  if (root == NULL)
138  return new Point(p);
139 
140  Node * ret_val = NULL;
141  if (p.get_y() == root->y())
142  {
143  if (p.get_x() == root->x())
144  return NULL; // duplicated point
145 
146  ret_val = lr_insert(root->rt, p);
147  if (ret_val != NULL)
148  {
149  root->rt = ret_val; // node was inserted
150  root->rt->set_rect(root->xmin(), root->y(),
151  root->xmax(), root->ymax());
152 
153  return root;
154  }
155 
156  return NULL;
157  }
158 
159  if (p.get_y() < root->y())
160  {
161  ret_val = lr_insert(root->lb, p);
162  if (ret_val != NULL)
163  {
164  root->lb = ret_val;
165  root->lb->set_rect(root->xmin(), root->ymin(),
166  root->xmax(), root->y());
167  return root;
168  }
169  else
170  return NULL;
171  }
172 
173  ret_val = lr_insert(root->rt, p);
174  if (ret_val != NULL)
175  {
176  root->rt = ret_val;
177  root->rt->set_rect(root->xmin(), root->y(),
178  root->xmax(), root->ymax());
179 
180  return root;
181  }
182 
183  return NULL;
184  }
185 
186 public:
187 
194  Point * insert(const Point & p)
195  {
196  if (root == NULL)
197  {
198  root = new Node (p);
199  root->set_rect(pmin, pmax);
200  N++;
201 
202  return &root->point;
203  }
204 
205  Node * ret = lr_insert(root, p);
206  if (ret == NULL)
207  return NULL;
208 
209  N++;
210 
211  return NULL;
212  }
213 
214 private:
215 
216  static Node * bu_search(Node * root, const Point & p)
217  {
218  if (root == NULL)
219  return NULL;
220 
221  if (root->y() == p.get_y())
222  {
223  if (root->x() == p.get_x())
224  return root;
225 
226  return lr_search(root->rt, p);
227  }
228 
229  if (p.get_y() < root->y())
230  return lr_search(root->lb, p);
231  else
232  return lr_search(root->rt, p);
233  }
234 
235  static Node * lr_search(Node * root, const Point & p)
236  {
237  if (root == NULL)
238  return NULL;
239 
240  if (root->x() == p.get_x())
241  {
242  if (root->y() == p.get_y())
243  return root;
244 
245  return bu_search(root->rt, p);
246  }
247 
248  if (p.get_x() < root->x())
249  return bu_search(root->lb, p);
250  else
251  return bu_search(root->rt, p);
252  }
253 
254 public:
255 
257  bool contains(const Point & p)
258  {
259  return lr_search(root, p) != NULL;
260  }
261 
262 private:
263 
264  static void range(Node * root, const Rectangle & rect, DynList<Point> * q)
265  {
266  if (root == NULL)
267  return;
268 
269  if (not root->rect.intersects(rect))
270  return;
271 
272  const Point & point = root->point;
273  if (rect.contains(point))
274  q->append(point);
275 
276  range(root->lb, rect, q);
277  range(root->rt, rect, q);
278  }
279 
280 public:
281 
288  void range(const Rectangle & rect, DynList<Point> * l)
289  {
290  if (N == 0)
291  return;
292 
293  range(root, rect, l);
294  }
295 
296 private:
297 
298  Node * min_node;
299  Geom_Number min_dist2;
300 
301  void lr_nearest(Node * root, const Point & p)
302  {
303  if (root == NULL)
304  return;
305 
306  if (root->rect.distance_squared_to(p) > min_dist2)
307  return;
308 
309  Geom_Number d2 = root->point.distance_squared_to(p); // es con el rectángulo
310  if (d2 < min_dist2)
311  {
312  min_dist2 = d2;
313  min_node = root;
314  }
315 
316  if (p.get_x() < root->x()) // is p to left of this
317  {
318  bu_nearest(root->lb, p);
319  bu_nearest(root->rt, p);
320  }
321  else
322  {
323  bu_nearest(root->rt, p);
324  bu_nearest(root->lb, p);
325  }
326  }
327 
328  void bu_nearest(Node * root, const Point & p)
329  {
330  if (root == NULL)
331  return;
332 
333  if (root->rect.distance_squared_to(p) > min_dist2)
334  return;
335 
336  Geom_Number d2 = root->point.distance_squared_to(p);
337  if (d2 < min_dist2)
338  {
339  min_dist2 = d2;
340  min_node = root;
341  }
342 
343  if (p.get_y() < root->y()) // is p to below this?
344  {
345  lr_nearest(root->lb, p);
346  lr_nearest(root->rt, p);
347  }
348  else
349  {
350  lr_nearest(root->rt, p);
351  lr_nearest(root->lb, p);
352  }
353  }
354 
355 public:
356 
358  Point nearest(const Point & p)
359  {
360  if (N == 0)
361  return NullPoint;
362 
363  min_dist2 = 1.0;
364  lr_nearest(root, p);
365 
366  return min_node->point;
367  }
368 };
369 
370 # endif // TPL_2DTREE_H
void range(const Rectangle &rect, DynList< Point > *l)
Definition: tpl_2dtree.H:288
Definition: tpl_nodePool.H:19
Point nearest(const Point &p)
Retorna el punto más cercano al punto p.
Definition: tpl_2dtree.H:358
bool contains(const Point &p)
Retorna true si el árbol contiene exactamente al punto p.
Definition: tpl_2dtree.H:257
Definition: point.H:87
const Geom_Number & get_y() const
retorna el valor de la coordenada y
Definition: point.H:166
const Geom_Number & get_x() const
retorna el valor de la coordenada x
Definition: point.H:161
Point * insert(const Point &p)
Definition: tpl_2dtree.H:194
Definition: point.H:972
Definition: tpl_2dtree.H:17
size_t size() const
retorna el número de puntos que contiene el árbol
Definition: tpl_2dtree.H:79
Definition: ahDry.H:13
bool is_empty() const
retorna true si el árbol no contiene ningún punto
Definition: tpl_2dtree.H:76
T & append(const T &item)
Inserta un item como último elemento.
Definition: htlist.H:685

Leandro Rabindranath León