vgl_rtree.hxx
Go to the documentation of this file.
1 #ifndef vgl_rtree_hxx_
2 #define vgl_rtree_hxx_
3 /*
4  fsm
5 */
6 #include <iostream>
7 #include "vgl_rtree.h"
8 #include <cassert>
9 #ifdef _MSC_VER
10 # include <vcl_msvc_warnings.h>
11 #endif
12 
13 #ifdef DEBUG
14 #define trace(str) { std::cerr << str << std::endl; }
15 #else
16 #define trace(str)
17 #endif
18 
19 //--------------------------------------------------------------------------------
20 
21 template <class V, class B, class C>
23  : parent(parent_node)
24  //
25  , total_vts(1)
26  , local_vts(1)
27  //
28  , total_chs(1)
29  , local_chs(0)
30 {
31  C::init(bounds, v);
32  vts[0] = v;
33 }
34 
35 template <class V, class B, class C>
37 {
38  parent = nullptr;
39  for (unsigned int i=0; i<local_chs; ++i)
40  delete chs[i];
41 }
42 
43 template <class V, class B, class C>
45 {
46  for (node *p=this; p; p=p->parent)
47  p->total_vts += diff;
48 }
49 
50 template <class V, class B, class C>
52 {
53  for (node *p=this; p; p=p->parent)
54  p->total_chs += diff;
55 }
56 
57 template <class V, class B, class C>
59 {
60  local_vts += diff;
61  update_total_vts(diff);
62 }
63 
64 template <class V, class B, class C>
66 {
67  local_chs += diff;
68  update_total_chs(diff);
69 }
70 
71 //--------------------------------------------------------------------------------
72 
73 // look for a vertex which compares equal to the given one.
74 // if found, return true and place the node and index in
75 // the given locations. else return false.
76 template <class V, class B, class C>
77 bool vgl_rtree_node<V, B, C>::find(V const &v, node **n, int *i) const
78 {
79  B tmp;
80  C::init(tmp, v);
81  return find(tmp, v, n, i);
82 }
83 
84 template <class V, class B, class C>
85 bool vgl_rtree_node<V, B, C>::find(B const &b, V const &v, node **n_out, int *i_out) const
86 {
87  if (C::meet(b, bounds)) {
88  // check if it is one of the vertices in this node.
89  for (unsigned int i=0; i<local_vts; ++i) {
90  if (vts[i] == v) {
91  *n_out = const_cast<node*>(this);
92  *i_out = i;
93  return true;
94  }
95  }
96  // if not, try the child nodes.
97  for (unsigned int i=0; i<local_chs; ++i)
98  if (chs[i]->find(b, v, n_out, i_out))
99  return true;
100  return false;
101  }
102  //
103  else
104  return false;
105 }
106 
107 template <class V, class B, class C>
109 {
110  std::cout << "node bounds: ";
111  bounds.print(std::cout);
112  std::cout << "\n--------";
113  for (unsigned int i=0; i<local_chs; ++i) {
114  std::cout << "\n\t";
115  chs[i]->print();
116  }
117  std::cout << "------------" << std::endl;
118 }
119 
120 //--------------------------------------------------------------------------------
121 
122 // add a vertex to the tree, returning the node into
123 // which it was placed.
124 template <class V, class B, class C>
126 {
127  // if there is room on this node for another vertex, do that :
128  if (local_vts < vgl_rtree_MAX_VERTICES) {
129  vts[local_vts++] = v;
130  update_total_vts(1);
131 
132  C::update(bounds, v);
133  for (node *p=parent; p; p=p->parent)
134  p->compute_bounds();
135 
136  return this;
137  }
138 
139  // if there is room on this node for add another child, do that :
140  if (local_chs < vgl_rtree_MAX_CHILDREN) {
141  node *nn = new node(this, v);
142 
143  chs[local_chs++] = nn;
144  update_total_chs(1);
145  update_total_vts(1);
146 
147  C::update(bounds, v);
148  for (node *p=parent; p; p=p->parent)
149  p->compute_bounds();
150 
151  return nn;
152  }
153 
154  // all full up, so add the vertex to a suitable child.
155  node *child = nullptr;
156 #if 0
157  // get the smallest subtree :
158  child = chs[0];
159  for (unsigned int i=0; i<local_chs; ++i)
160  if (chs[i]->total_vts < child->total_vts)
161  child = chs[i];
162 #else
163  { // get the subtree which needs the least enlargement :
164  float cost = 0;
165  int best = -1;
166  for (unsigned int i=0; i<local_chs; ++i) {
167  B tmp(chs[i]->bounds);
168  C::update(tmp, v);
169  float dd = C::volume(tmp) - C::volume(chs[i]->bounds);
170  if (best==-1 || dd<cost) {
171  cost = dd;
172  best = i;
173  }
174  }
175  child = chs[best];
176  }
177 #endif
178  assert(child);
179  return child->add(v);
180 }
181 
182 // remove the ith element from the node.
183 template <class V, class B, class C>
184 void vgl_rtree_node<V, B, C>::erase(unsigned int i)
185 {
186  assert(i<local_vts);
187 
188  if (total_vts > 1) { // there are other vertices.
189 
190  // decrease vertex counts.
191  --local_vts;
192  update_total_vts(-1);
193 
194  // move top element down to position i.
195  if (i != local_vts)
196  vts[i] = vts[local_vts];
197 
198  for (node *p = this; p; p=p->parent)
199  p->compute_bounds();
200  }
201 
202  else { // it's the only vertex in this node and below.
203 
204  // decrease vertex counts.
205  --local_vts;
206  update_total_vts(-1);
207 
208  // this node is now empty, so attempt some pruning.
209  if (parent) {
210  trace("prune");
211 
212  // move upwards as far as we need to prune. we can only prune
213  // a node if it has total_vts equal to zero and has a parent.
214  node *n = this;
215  while (n->parent && (n->parent->parent && n->parent->total_vts==0))
216  n = n->parent;
217 
218  // get pointer to parent.
219  node *p = n->parent;
220 
221  // find out what index n has in p :
222  unsigned int j = n->find_index_in_parent();
223  assert(n == p->chs[j]);
224 
225  // update the node counts in p :
226  p->update_total_chs(- (int)n->total_chs);
227 
228  -- p->local_chs;
229 
230  // move top child down to position j.
231  if (p->local_chs != j)
232  p->chs[j] = p->chs[p->local_chs];
233 
234  // delete the node.
235  delete n; n=nullptr;
236 
237  // recompute the bounding boxes all the way up to the root.
238  for (node *t = p; t; t=t->parent)
239  t->compute_bounds();
240  }
241  }
242 }
243 
244 //--------------------------------------------------------------------------------
245 
246 template <class V, class B, class C>
248 {
249  assert(parent);
250  for (unsigned int i=0; i<parent->local_chs; ++i)
251  if (parent->chs[i] == this)
252  return i;
253  assert(!"this not found in parent");
254  return (unsigned int)(-1);
255 }
256 
257 // recompute the bounds of this node, using the vertices on
258 // the node and the bounds of the children. non-recursive.
259 template <class V, class B, class C>
261 {
262  if (local_vts>0) {
263  C::init(bounds, vts[0]);
264  for (unsigned int i=1; i<local_vts; ++i)
265  C::update(bounds, vts[i]);
266  for (unsigned i=0; i<local_chs; ++i)
267  C::update(bounds, chs[i]->bounds );
268  }
269  else if (local_chs>0) {
270  bounds = chs[0]->bounds;
271  for (unsigned int i=1; i<local_chs; ++i)
272  C::update(bounds, chs[i]->bounds );
273  }
274  else {
275  assert(!"This cannot happen. this node should be pruned.");
276  }
277 }
278 
279 //--------------------------------------------------------------------------------
280 
281 // this is a special case of the probe version.
282 // calls only itself.
283 template <class V, class B, class C>
284 void vgl_rtree_node<V, B, C>::get(B const &region, std::vector<V> &vs) const
285 {
286 #ifdef DEBUG
287  std::cout << " In get: " << region << std::endl;
288 #endif // DEBUG
289  // get vertices from this node :
290  for (unsigned int i=0; i<local_vts; ++i)
291  if (C::meet(region, vts[i] )) {
292 #ifdef DEBUG
293  std::cout << " pushed " << vts[i] << std::endl;
294 #endif // DEBUG
295  vs.push_back(vts[i]);
296  }
297 
298  // get vertices from children :
299  for (unsigned int i=0; i<local_chs; ++i)
300  if (C::meet(region, chs[i]->bounds )) {
301 #ifdef DEBUG
302  std::cout << "--- region of child: " << i << " :" << chs[i]->bounds << " met search region----\n";
303 #endif // DEBUG
304  chs[i]->get(region, vs);
305  }
306 }
307 
308 // calls only itself.
309 template <class V, class B, class C>
310 void vgl_rtree_node<V, B, C>::get(vgl_rtree_probe<V, B, C> const &region, std::vector<V> &vs) const
311 {
312  // get vertices from this node :
313  for (unsigned int i=0; i<local_vts; ++i)
314  if (region.meets( vts[i] ))
315  vs.push_back(vts[i]);
316 
317  // get vertices from children :
318  for (unsigned int i=0; i<local_chs; ++i)
319  if (region.meets( chs[i]->bounds ))
320  chs[i]->get(region, vs);
321 }
322 
323 template <class V, class B, class C>
324 void vgl_rtree_node<V, B, C>::get_all(std::vector<V> &vs) const
325 {
326  vs.reserve(vs.size() + total_vts);
327 
328  for (unsigned int i=0; i<local_vts; ++i)
329  vs.push_back(vts[i]);
330 
331  for (unsigned int i=0; i<local_chs; ++i)
332  chs[i]->get_all(vs);
333 }
334 
335 //--------------------------------------------------------------------------------
336 // ITERATORS
337 
338 template <class V, class B, class C>
340 {
341  if (!current)
342  return;
343 
344  ++i; // class member!
345  if (i < current->local_vts)
346  return;
347 
348  if (current->local_chs > 0) {
349  // descend to first child.
350  current = current->chs[0];
351  i = 0;
352  return;
353  }
354 
355  // backtrack :
356  unsigned int j;
357  node *n;
358  node *p;
359  again:
360  n = current;
361  p = current->parent;
362 
363  if (!p) { // reached the end
364  current = nullptr;
365  return;
366  }
367 
368  // find index j of n in p :
369  j = n->find_index_in_parent();
370 
371  ++j;
372  if (j<p->local_chs) {
373  // go to next child of p
374  current = p->chs[j];
375  i = 0;
376  return;
377  }
378 
379  // no more children in p.
380  current = p;
381  goto again;
382 }
383 
384 template <class V, class B, class C>
386 {
387  assert(!"not implemented");
388 }
389 
390 template <class V, class B, class C>
393 {
394  if (a.current || b.current)
395  return (a.current==b.current) && (a.i == b.i);
396  else
397  return true; // both "at end"
398 }
399 
400 //--------------------------------------------------------------------------------
401 
402 #define VGL_RTREE_INSTANTIATE_tagged(tag, V, B, C) \
403 template class vgl_rtree_probe<V, B, C >; \
404 template class vgl_rtree_node<V, B, C >; \
405 template class vgl_rtree_iterator_base<V, B, C >; \
406 typedef vgl_rtree_iterator_base<V, B, C > itVBC##tag; \
407 template bool operator==(itVBC##tag const &, itVBC##tag const &); \
408 /*template bool operator!=(itVBC##tag const &, itVBC##tag const &) ; */ \
409 template class vgl_rtree_iterator<V, B, C >; \
410 template class vgl_rtree_const_iterator<V, B, C >; \
411 template class vgl_rtree<V, B, C >
412 
413 // the __LINE__ tag gets expanded here
414 #define VGL_RTREE_INSTANTIATE_expand(tag, V, B, C) \
415 VGL_RTREE_INSTANTIATE_tagged(tag, V, B, C)
416 
417 #undef VGL_RTREE_INSTANTIATE
418 #define VGL_RTREE_INSTANTIATE(V, B, C) \
419 VGL_RTREE_INSTANTIATE_expand(__LINE__, V, B, C)
420 
421 #endif
void get_all(std::vector< V > &vs) const
Definition: vgl_rtree.hxx:324
node * add(V const &v)
Definition: vgl_rtree.hxx:125
void update_total_vts(int diff)
Definition: vgl_rtree.hxx:44
unsigned int find_index_in_parent() const
Definition: vgl_rtree.hxx:247
#define vgl_rtree_MAX_VERTICES
max. number of Vs stored in a node.
Definition: vgl_rtree.h:34
void print() const
Definition: vgl_rtree.hxx:108
bool operator==(vgl_rtree_iterator_base< V, B, C > const &a, vgl_rtree_iterator_base< V, B, C > const &b)
Definition: vgl_rtree.hxx:391
unsigned total_vts
Definition: vgl_rtree.h:55
node * chs[vgl_rtree_MAX_CHILDREN]
Definition: vgl_rtree.h:71
Represent a node in the rtree.
Definition: vgl_algo_fwd.h:31
void update_vertex_count(int diff)
Definition: vgl_rtree.hxx:58
void update_child_count(int diff)
Definition: vgl_rtree.hxx:65
virtual bool meets(V const &v) const
return true if the probe "meets" the given object.
Definition: vgl_rtree.h:28
unsigned local_chs
Definition: vgl_rtree.h:68
#define v
Definition: vgl_vector_2d.h:74
#define trace(str)
Definition: vgl_rtree.hxx:16
unsigned total_chs
Definition: vgl_rtree.h:65
Templated rtree class and associated classes and functions.
node * parent
Definition: vgl_rtree.h:51
vgl_rtree_node(node *parent, V const &v)
Definition: vgl_rtree.hxx:22
bool find(V const &v, node **n, int *i) const
Definition: vgl_rtree.hxx:77
void erase(unsigned int i)
Definition: vgl_rtree.hxx:184
void get(B const &region, std::vector< V > &) const
Definition: vgl_rtree.hxx:284
void update_total_chs(int diff)
Definition: vgl_rtree.hxx:51
#define vgl_rtree_MAX_CHILDREN
max. number of children of a given node.
Definition: vgl_rtree.h:38
void compute_bounds()
Definition: vgl_rtree.hxx:260
V vts[vgl_rtree_MAX_VERTICES]
Definition: vgl_rtree.h:61
Base class for both rtree iterators.
Definition: vgl_algo_fwd.h:32
Function predicate object for querying the tree.
Definition: vgl_algo_fwd.h:30