core/vgl/algo/vgl_rtree.txx
Go to the documentation of this file.
00001 #ifndef vgl_rtree_txx_
00002 #define vgl_rtree_txx_
00003 /*
00004   fsm
00005 */
00006 #include "vgl_rtree.h"
00007 #include <vcl_cassert.h>
00008 #include <vcl_iostream.h>
00009 
00010 #ifdef DEBUG
00011 #define trace(str) { vcl_cerr << str << vcl_endl; }
00012 #else
00013 #define trace(str)
00014 #endif
00015 
00016 //--------------------------------------------------------------------------------
00017 
00018 template <class V, class B, class C>
00019 vgl_rtree_node<V, B, C>::vgl_rtree_node(node *parent_node, V const &v)
00020   : parent(parent_node)
00021   //
00022   , total_vts(1)
00023   , local_vts(1)
00024   //
00025   , total_chs(1)
00026   , local_chs(0)
00027 {
00028   C::init(bounds, v);
00029   vts[0] = v;
00030 }
00031 
00032 template <class V, class B, class C>
00033 vgl_rtree_node<V, B, C>::~vgl_rtree_node()
00034 {
00035   parent = 0;
00036   for (unsigned int i=0; i<local_chs; ++i)
00037     delete chs[i];
00038 }
00039 
00040 template <class V, class B, class C>
00041 void vgl_rtree_node<V, B, C>::update_total_vts(int diff)
00042 {
00043   for (node *p=this; p; p=p->parent)
00044     p->total_vts += diff;
00045 }
00046 
00047 template <class V, class B, class C>
00048 void vgl_rtree_node<V, B, C>::update_total_chs(int diff)
00049 {
00050   for (node *p=this; p; p=p->parent)
00051     p->total_chs += diff;
00052 }
00053 
00054 template <class V, class B, class C>
00055 void vgl_rtree_node<V, B, C>::update_vertex_count(int diff)
00056 {
00057   local_vts += diff;
00058   update_total_vts(diff);
00059 }
00060 
00061 template <class V, class B, class C>
00062 void vgl_rtree_node<V, B, C>::update_child_count(int diff)
00063 {
00064   local_chs += diff;
00065   update_total_chs(diff);
00066 }
00067 
00068 //--------------------------------------------------------------------------------
00069 
00070 // look for a vertex which compares equal to the given one.
00071 // if found, return true and place the node and index in
00072 // the given locations. else return false.
00073 template <class V, class B, class C>
00074 bool vgl_rtree_node<V, B, C>::find(V const &v, node **n, int *i) const
00075 {
00076   B tmp;
00077   C::init(tmp, v);
00078   return find(tmp, v, n, i);
00079 }
00080 
00081 template <class V, class B, class C>
00082 bool vgl_rtree_node<V, B, C>::find(B const &b, V const &v, node **n_out, int *i_out) const
00083 {
00084   if (C::meet(b, bounds)) {
00085     // check if it is one of the vertices in this node.
00086     for (unsigned int i=0; i<local_vts; ++i) {
00087       if (vts[i] == v) {
00088         *n_out = const_cast<node*>(this);
00089         *i_out = i;
00090         return true;
00091       }
00092     }
00093     // if not, try the child nodes.
00094     for (unsigned int i=0; i<local_chs; ++i)
00095       if (chs[i]->find(b, v, n_out, i_out))
00096         return true;
00097     return false;
00098   }
00099   //
00100   else
00101     return false;
00102 }
00103 
00104 template <class V, class B, class C>
00105 void vgl_rtree_node<V, B, C>::print() const
00106 {
00107   vcl_cout << "node bounds: ";
00108   bounds.print(vcl_cout);
00109   vcl_cout << "\n--------";
00110   for (unsigned int i=0; i<local_chs; ++i) {
00111     vcl_cout << "\n\t";
00112     chs[i]->print();
00113   }
00114   vcl_cout << "------------" << vcl_endl;
00115 }
00116 
00117 //--------------------------------------------------------------------------------
00118 
00119 // add a vertex to the tree, returning the node into
00120 // which it was placed.
00121 template <class V, class B, class C>
00122 vgl_rtree_node<V, B, C> *vgl_rtree_node<V, B, C>::add(V const &v)
00123 {
00124   // if there is room on this node for another vertex, do that :
00125   if (local_vts < vgl_rtree_MAX_VERTICES) {
00126     vts[local_vts++] = v;
00127     update_total_vts(1);
00128 
00129     C::update(bounds, v);
00130     for (node *p=parent; p; p=p->parent)
00131       p->compute_bounds();
00132 
00133     return this;
00134   }
00135 
00136   // if there is room on this node for add another child, do that :
00137   if (local_chs < vgl_rtree_MAX_CHILDREN) {
00138     node *nn = new node(this, v);
00139 
00140     chs[local_chs++] = nn;
00141     update_total_chs(1);
00142     update_total_vts(1);
00143 
00144     C::update(bounds, v);
00145     for (node *p=parent; p; p=p->parent)
00146       p->compute_bounds();
00147 
00148     return nn;
00149   }
00150 
00151   // all full up, so add the vertex to a suitable child.
00152   node *child = 0;
00153 #if 0
00154   // get the smallest subtree :
00155   child = chs[0];
00156   for (unsigned int i=0; i<local_chs; ++i)
00157     if (chs[i]->total_vts < child->total_vts)
00158       child = chs[i];
00159 #else
00160   { // get the subtree which needs the least enlargement :
00161     float cost = 0;
00162     int best = -1;
00163     for (unsigned int i=0; i<local_chs; ++i) {
00164       B tmp(chs[i]->bounds);
00165       C::update(tmp, v);
00166       float dd = C::volume(tmp) - C::volume(chs[i]->bounds);
00167       if (best==-1 || dd<cost) {
00168         cost = dd;
00169         best = i;
00170       }
00171     }
00172     child = chs[best];
00173   }
00174 #endif
00175   assert(child);
00176   return child->add(v);
00177 }
00178 
00179 // remove the ith element from the node.
00180 template <class V, class B, class C>
00181 void vgl_rtree_node<V, B, C>::erase(unsigned int i)
00182 {
00183   assert(i<local_vts);
00184 
00185   if (total_vts > 1) { // there are other vertices.
00186 
00187     // decrease vertex counts.
00188     --local_vts;
00189     update_total_vts(-1);
00190 
00191     // move top element down to position i.
00192     if (i != local_vts)
00193       vts[i] = vts[local_vts];
00194 
00195     for (node *p = this; p; p=p->parent)
00196       p->compute_bounds();
00197   }
00198 
00199   else { // it's the only vertex in this node and below.
00200 
00201     // decrease vertex counts.
00202     --local_vts;
00203     update_total_vts(-1);
00204 
00205     // this node is now empty, so attempt some pruning.
00206     if (parent) {
00207       trace("prune");
00208 
00209       // move upwards as far as we need to prune. we can only prune
00210       // a node if it has total_vts equal to zero and has a parent.
00211       node *n = this;
00212       while (n->parent && (n->parent->parent && n->parent->total_vts==0))
00213         n = n->parent;
00214 
00215       // get pointer to parent.
00216       node *p = n->parent;
00217 
00218       // find out what index n has in p :
00219       unsigned int j = n->find_index_in_parent();
00220       assert(n == p->chs[j]);
00221 
00222       // update the node counts in p :
00223       p->update_total_chs(- (int)n->total_chs);
00224 
00225       -- p->local_chs;
00226 
00227       // move top child down to position j.
00228       if (p->local_chs != j)
00229         p->chs[j] = p->chs[p->local_chs];
00230 
00231       // delete the node.
00232       delete n; n=0;
00233 
00234       // recompute the bounding boxes all the way up to the root.
00235       for (node *t = p; t; t=t->parent)
00236         t->compute_bounds();
00237     }
00238   }
00239 }
00240 
00241 //--------------------------------------------------------------------------------
00242 
00243 template <class V, class B, class C>
00244 unsigned int vgl_rtree_node<V, B, C>::find_index_in_parent() const
00245 {
00246   assert(parent);
00247   for (unsigned int i=0; i<parent->local_chs; ++i)
00248     if (parent->chs[i] == this)
00249       return i;
00250   assert(!"this not found in parent");
00251   return (unsigned int)(-1);
00252 }
00253 
00254 // recompute the bounds of this node, using the vertices on
00255 // the node and the bounds of the children. non-recursive.
00256 template <class V, class B, class C>
00257 void vgl_rtree_node<V, B, C>::compute_bounds()
00258 {
00259   if (local_vts>0) {
00260     C::init(bounds, vts[0]);
00261     for (unsigned int i=1; i<local_vts; ++i)
00262       C::update(bounds, vts[i]);
00263     for (unsigned i=0; i<local_chs; ++i)
00264       C::update(bounds, chs[i]->bounds );
00265   }
00266   else if (local_chs>0) {
00267     bounds = chs[0]->bounds;
00268     for (unsigned int i=1; i<local_chs; ++i)
00269       C::update(bounds, chs[i]->bounds );
00270   }
00271   else {
00272     assert(!"This cannot happen. this node should be pruned.");
00273   }
00274 }
00275 
00276 //--------------------------------------------------------------------------------
00277 
00278 // this is a special case of the probe version.
00279 // calls only itself.
00280 template <class V, class B, class C>
00281 void vgl_rtree_node<V, B, C>::get(B const &region, vcl_vector<V> &vs) const
00282 {
00283 #ifdef DEBUG
00284   vcl_cout << " In get: " << region << vcl_endl;
00285 #endif // DEBUG
00286   // get vertices from this node :
00287   for (unsigned int i=0; i<local_vts; ++i)
00288     if (C::meet(region, vts[i] )) {
00289 #ifdef DEBUG
00290       vcl_cout << " pushed " << vts[i] << vcl_endl;
00291 #endif // DEBUG
00292       vs.push_back(vts[i]);
00293     }
00294 
00295   // get vertices from children :
00296   for (unsigned int i=0; i<local_chs; ++i)
00297     if (C::meet(region, chs[i]->bounds )) {
00298 #ifdef DEBUG
00299       vcl_cout << "--- region of child: " << i << " :" << chs[i]->bounds << " met search region----\n";
00300 #endif // DEBUG
00301       chs[i]->get(region, vs);
00302     }
00303 }
00304 
00305 // calls only itself.
00306 template <class V, class B, class C>
00307 void vgl_rtree_node<V, B, C>::get(vgl_rtree_probe<V, B, C> const &region, vcl_vector<V> &vs) const
00308 {
00309   // get vertices from this node :
00310   for (unsigned int i=0; i<local_vts; ++i)
00311     if (region.meets( vts[i] ))
00312       vs.push_back(vts[i]);
00313 
00314   // get vertices from children :
00315   for (unsigned int i=0; i<local_chs; ++i)
00316     if (region.meets( chs[i]->bounds ))
00317       chs[i]->get(region, vs);
00318 }
00319 
00320 template <class V, class B, class C>
00321 void vgl_rtree_node<V, B, C>::get_all(vcl_vector<V> &vs) const
00322 {
00323   vs.reserve(vs.size() + total_vts);
00324 
00325   for (unsigned int i=0; i<local_vts; ++i)
00326     vs.push_back(vts[i]);
00327 
00328   for (unsigned int i=0; i<local_chs; ++i)
00329     chs[i]->get_all(vs);
00330 }
00331 
00332 //--------------------------------------------------------------------------------
00333 // ITERATORS
00334 
00335 template <class V, class B, class C>
00336 void vgl_rtree_iterator_base<V, B, C>::operator_pp()
00337 {
00338   if (!current)
00339     return;
00340 
00341   ++i; // class member!
00342   if (i < current->local_vts)
00343     return;
00344 
00345   if (current->local_chs > 0) {
00346     // descend to first child.
00347     current = current->chs[0];
00348     i = 0;
00349     return;
00350   }
00351 
00352   // backtrack :
00353   unsigned int j;
00354   node *n;
00355   node *p;
00356  again:
00357   n = current;
00358   p = current->parent;
00359 
00360   if (!p) { // reached the end
00361     current = 0;
00362     return;
00363   }
00364 
00365   // find index j of n in p :
00366   j = n->find_index_in_parent();
00367 
00368   ++j;
00369   if (j<p->local_chs) {
00370     // go to next child of p
00371     current = p->chs[j];
00372     i = 0;
00373     return;
00374   }
00375 
00376   // no more children in p.
00377   current = p;
00378   goto again;
00379 }
00380 
00381 template <class V, class B, class C>
00382 void vgl_rtree_iterator_base<V, B, C>::operator_mm()
00383 {
00384   assert(!"not implemented");
00385 }
00386 
00387 template <class V, class B, class C>
00388 bool operator==(vgl_rtree_iterator_base<V, B, C> const &a,
00389                 vgl_rtree_iterator_base<V, B, C> const &b)
00390 {
00391   if (a.current || b.current)
00392     return (a.current==b.current) && (a.i == b.i);
00393   else
00394     return true; // both "at end"
00395 }
00396 
00397 //--------------------------------------------------------------------------------
00398 
00399 #define VGL_RTREE_INSTANTIATE_tagged(tag, V, B, C) \
00400 template class vgl_rtree_probe<V, B, C >; \
00401 template class vgl_rtree_node<V, B, C >; \
00402 template class vgl_rtree_iterator_base<V, B, C >; \
00403 typedef vgl_rtree_iterator_base<V, B, C > itVBC##tag; \
00404 template bool operator==(itVBC##tag const &, itVBC##tag const &); \
00405 VCL_INSTANTIATE_INLINE(bool operator!=(itVBC##tag const &, itVBC##tag const &)); \
00406 template class vgl_rtree_iterator<V, B, C >; \
00407 template class vgl_rtree_const_iterator<V, B, C >; \
00408 template class vgl_rtree<V, B, C >
00409 
00410 // the __LINE__ tag gets expanded here
00411 #define VGL_RTREE_INSTANTIATE_expand(tag, V, B, C) \
00412 VGL_RTREE_INSTANTIATE_tagged(tag, V, B, C)
00413 
00414 #undef VGL_RTREE_INSTANTIATE
00415 #define VGL_RTREE_INSTANTIATE(V, B, C) \
00416 VGL_RTREE_INSTANTIATE_expand(__LINE__, V, B, C)
00417 
00418 #endif