RStarTree.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008 Dustin Spicuzza <dustin@virtualroadside.com>
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of version 2 of the GNU General Public License
6  * as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16  */
17 
18 /*
19  * This is intended to be a templated implementation of an R* Tree, designed
20  * to create an efficient and (relatively) small indexing container in N
21  * dimensions. At the moment, it is a memory-based container instead of disk
22  * based.
23  *
24  * Based on "The R*-Tree: An Efficient and Robust Access Method for Points
25  * and Rectangles" by N. Beckmann, H.P. Kriegel, R. Schneider, and B. Seeger
26  */
27 
28 
29 #ifndef RSTARTREE_H
30 #define RSTARTREE_H
31 
32 #include <list>
33 #include <vector>
34 #include <limits>
35 #include <algorithm>
36 #include <cassert>
37 #include <functional>
38 
39 #include <iostream>
40 #include <sstream>
41 #include <fstream>
42 
43 //#include "RStarBoundingBox.h"
45 
46 // R* tree parameters
47 #define RTREE_REINSERT_P 0.30
48 #define RTREE_CHOOSE_SUBTREE_P 32
49 
50 // template definition:
51 #define RSTAR_TEMPLATE
52 
53 
54 // definition of an leaf
55 template <typename BoundedItem, typename LeafType>
56 struct RStarLeaf : BoundedItem {
57 
58  typedef LeafType leaf_type;
59  LeafType leaf;
60 };
61 
62 // definition of a node
63 template <typename BoundedItem>
64 struct RStarNode : BoundedItem {
65  std::vector< BoundedItem* > items;
66  bool hasLeaves;
67 };
68 
69 //#include "RStarVisitor.h"
71 
72 
73 /**
74  \class RStarTree
75  \brief Implementation of an RTree with an R* index
76 
77  @tparam LeafType type of leaves stored in the tree
78  @tparam dimensions number of dimensions the bounding boxes are described in
79  @tparam min_child_items m, in the range 2 <= m < M
80  @tparam max_child_items M, in the range 2 <= m < M
81  @tparam RemoveLeaf A functor used to remove leaves from the tree
82 */
83 template <
84  typename LeafType,
85  std::size_t dimensions, std::size_t min_child_items, std::size_t max_child_items
86 >
87 class RStarTree {
88 public:
89 
90  // shortcuts
93 
96 
97  // acceptors
101 
102  // predefined visitors
105 
106  static_assert(1 <= min_child_items && min_child_items <= max_child_items/2,
107  "Wrong parameters in RStarTree template.");
108 
109  // default constructor
110  RStarTree() : m_root(NULL), m_size(0)
111  {
112  }
113 
114  // destructor
116  Remove(
117  AcceptAny(),
118  RemoveLeaf()
119  );
120  }
121 
122  // Single insert function, adds a new item to the tree
123  void Insert(LeafType leaf, const BoundingBox &bound)
124  {
125  // ID1: Invoke Insert starting with the leaf level as a
126  // parameter, to Insert a new data rectangle
127  Leaf * newLeaf = new Leaf();
128  newLeaf->bound = bound;
129  newLeaf->leaf = leaf;
130 
131  // create a new root node if necessary
132  if (!m_root)
133  {
134  m_root = new Node();
135  m_root->hasLeaves = true;
136 
137  // reserve memory
138  m_root->items.reserve(min_child_items);
139  m_root->items.push_back(newLeaf);
140  m_root->bound = bound;
141  }
142  else
143  // start the insertion process
144  InsertInternal(newLeaf, m_root);
145 
146  m_size += 1;
147  }
148 
149 
150  /*
151  This is an interpretation of the bulk insert algorithm described
152  in "Improving Performance with Bulk-Inserts in Oracle R-Trees"
153  by N. An, R. Kanth, V. Kothuri, and S. Ravada
154 
155  I think this is essentially right, since if you think about it for too
156  long then it makes sense ;) The idea is to work your way down to the
157  bottom of the tree, make some child nodes, perform a split, and work
158  your way back up continually. The bounding boxes have to be adjusted
159  on the way up the tree, and not on the way down.
160 
161  Entries * BulkInsert(Node * node, Node * buddy, vector<Leaf*> &entries)
162  {
163  if (entries.empty() && !buddy)
164  return node;
165 
166  if (node->hasLeaves)
167  child_entries = node.items + buddy.items + entries;
168  else
169  {
170  combine items in node and buddy;
171 
172  for each item in entries?
173  for each possible partition in entries
174  {
175  pick ci and bi using choose subtree, where
176  ci is not null, bi can be null
177 
178  each entry can only be in one partition
179 
180  child_entries += BulkInsert(ci, bi, entries);
181  }
182  }
183 
184  // this part builds up the tree from the ground up, and then
185  // passes it back to the parent to be split more until we reach
186  // the root node
187 
188  // create new nodes: the split algorithm generalized to N
189 
190  return rtreeCluster(child_entries);
191 
192  }
193  */
194 
195  /**
196  \brief Touches each node using the visitor pattern
197 
198  You must specify an acceptor functor that takes a BoundingBox and a
199  visitor that takes a BoundingBox and a const LeafType&.
200 
201  See RStarVisitor.h for more information about the various visitor
202  types available.
203 
204  @param acceptor An acceptor functor that returns true if this
205  branch or leaf of the tree should be considered for visitation.
206 
207  @param visitor A visitor functor that does the visiting
208 
209  @return This will return the Visitor object, so you can retrieve whatever
210  data it has in it if needed (for example, to get the count of items
211  visited). It returns by value, so ensure that the copy is cheap
212  for decent performance.
213  */
214  template <typename Acceptor, typename Visitor>
215  Visitor Query(const Acceptor &accept, Visitor visitor)
216  {
217  if (m_root)
218  {
219  QueryFunctor<Acceptor, Visitor> query(accept, visitor);
220  query(m_root);
221  }
222 
223  return visitor;
224  }
225 
226 
227  /**
228  \brief Removes item(s) from the tree.
229 
230  See RStarVisitor.h for more information about the various visitor
231  types available.
232 
233  @param acceptor A node acceptor functor that returns true if this
234  branch or leaf of the tree should be considered for deletion
235  (it does not delete it, however. That is what the LeafRemover does).
236 
237  @param leafRemover A visitor functor that decides whether that
238  individual item should be removed from the tree. If it returns true,
239  then the node holding that item will be deleted.
240 
241  See also RemoveBoundedArea, RemoveItem for examples of how this
242  function can be called.
243  */
244  template <typename Acceptor, typename LeafRemover>
245  void Remove( const Acceptor &accept, LeafRemover leafRemover)
246  {
247  std::list<Leaf*> itemsToReinsert;
248 
249  if (!m_root)
250  return;
251 
252  RemoveFunctor<Acceptor, LeafRemover> remove(accept, leafRemover, &itemsToReinsert, &m_size);
253  remove(m_root, true);
254 
255  if (!itemsToReinsert.empty())
256  {
257  // reinsert anything that needs to be reinserted
258  typename std::list< Leaf* >::iterator it = itemsToReinsert.begin();
259  typename std::list< Leaf* >::iterator end = itemsToReinsert.end();
260 
261  // TODO: do this whenever that actually works..
262  // BulkInsert(itemsToReinsert, m_root);
263 
264  for(;it != end; it++)
265  InsertInternal(*it, m_root);
266  }
267  }
268 
269  // stub that removes any items contained in an specified area
270  void RemoveBoundedArea( const BoundingBox &bound )
271  {
272  Remove(AcceptEnclosing(bound), RemoveLeaf());
273  }
274 
275  // removes a specific item. If removeDuplicates is true, only the first
276  // item found will be removed
277  void RemoveItem( const LeafType &item, bool removeDuplicates = true )
278  {
279  Remove( AcceptAny(), RemoveSpecificLeaf(item, removeDuplicates));
280  }
281 
282 
283  std::size_t GetSize() const { return m_size; }
284  std::size_t GetDimensions() const { return dimensions; }
285 
286 
287 protected:
288 
289  // choose subtree: only pass this items that do not have leaves
290  // I took out the loop portion of this algorithm, so it only
291  // picks a subtree at that particular level
292  Node * ChooseSubtree(Node * node, const BoundingBox * bound)
293  {
294  // If the child pointers in N point to leaves
295  if (static_cast<Node*>(node->items[0])->hasLeaves)
296  {
297  // determine the minimum overlap cost
298  if (max_child_items > (RTREE_CHOOSE_SUBTREE_P*2)/3 && node->items.size() > RTREE_CHOOSE_SUBTREE_P)
299  {
300  // ** alternative algorithm:
301  // Sort the rectangles in N in increasing order of
302  // then area enlargement needed to include the new
303  // data rectangle
304 
305  // Let A be the group of the first p entrles
306  std::partial_sort( node->items.begin(), node->items.begin() + RTREE_CHOOSE_SUBTREE_P, node->items.end(),
308 
309  // From the items in A, considering all items in
310  // N, choose the leaf whose rectangle needs least
311  // overlap enlargement
312 
313  return static_cast<Node*>(* std::min_element(node->items.begin(), node->items.begin() + RTREE_CHOOSE_SUBTREE_P,
315  }
316 
317  // choose the leaf in N whose rectangle needs least
318  // overlap enlargement to include the new data
319  // rectangle Resolve ties by choosmg the leaf
320  // whose rectangle needs least area enlargement, then
321  // the leaf with the rectangle of smallest area
322 
323  return static_cast<Node*>(* std::min_element(node->items.begin(), node->items.end(),
325  }
326 
327  // if the chlld pointers in N do not point to leaves
328 
329  // [determine the minimum area cost],
330  // choose the leaf in N whose rectangle needs least
331  // area enlargement to include the new data
332  // rectangle. Resolve ties by choosing the leaf
333  // with the rectangle of smallest area
334 
335  return static_cast<Node*>(* std::min_element( node->items.begin(), node->items.end(),
337  }
338 
339 
340  // inserts nodes recursively. As an optimization, the algorithm steps are
341  // way out of order. :) If this returns something, then that item should
342  // be added to the caller's level of the tree
343  Node * InsertInternal(Leaf * leaf, Node * node, bool firstInsert = true)
344  {
345  // I4: Adjust all covering rectangles in the insertion path
346  // such that they are minimum bounding boxes
347  // enclosing the children rectangles
348  node->bound.stretch(leaf->bound);
349 
350 
351  // CS2: If we're at a leaf, then use that level
352  if (node->hasLeaves)
353  {
354  // I2: If N has less than M items, accommodate E in N
355  node->items.push_back(leaf);
356  }
357  else
358  {
359  // I1: Invoke ChooseSubtree. with the level as a parameter,
360  // to find an appropriate node N, m which to place the
361  // new leaf E
362 
363  // of course, this already does all of that recursively. we just need to
364  // determine whether we need to split the overflow or not
365  Node * tmp_node = InsertInternal( leaf, ChooseSubtree(node, &leaf->bound), firstInsert );
366 
367  if (!tmp_node)
368  return NULL;
369 
370  // this gets joined to the list of items at this level
371  node->items.push_back(tmp_node);
372  }
373 
374 
375  // If N has M+1 items. invoke OverflowTreatment with the
376  // level of N as a parameter [for reinsertion or split]
377  if (node->items.size() > max_child_items )
378  {
379 
380  // I3: If OverflowTreatment was called and a split was
381  // performed, propagate OverflowTreatment upwards
382  // if necessary
383 
384  // This is implicit, the rest of the algorithm takes place in there
385  return OverflowTreatment(node, firstInsert);
386  }
387 
388  return NULL;
389  }
390 
391 
392  // TODO: probably could just merge this in with InsertInternal()
393  Node * OverflowTreatment(Node * level, bool firstInsert)
394  {
395  // OT1: If the level is not the root level AND this is the first
396  // call of OverflowTreatment in the given level during the
397  // insertion of one data rectangle, then invoke Reinsert
398  if (level != m_root && firstInsert)
399  {
400  Reinsert(level);
401  return NULL;
402  }
403 
404  Node * splitItem = Split(level);
405 
406  // If OverflowTreatment caused a split of the root, create a new root
407  if (level == m_root)
408  {
409  Node * newRoot = new Node();
410  newRoot->hasLeaves = false;
411 
412  // reserve memory
413  newRoot->items.reserve(min_child_items);
414  newRoot->items.push_back(m_root);
415  newRoot->items.push_back(splitItem);
416 
417  // Do I4 here for the new root item
418  newRoot->bound.reset();
419  for_each(newRoot->items.begin(), newRoot->items.end(), StretchBoundingBox<BoundedItem>(&newRoot->bound));
420 
421  // and we're done
422  m_root = newRoot;
423  return NULL;
424  }
425 
426  // propagate it upwards
427  return splitItem;
428  }
429 
430  // this combines Split, ChooseSplitAxis, and ChooseSplitIndex into
431  // one function as an optimization (they all share data structures,
432  // so it would be pointless to do all of that copying)
433  //
434  // This returns a node, which should be added to the items of the
435  // passed node's parent
436  Node * Split(Node * node)
437  {
438  Node * newNode = new Node();
439  newNode->hasLeaves = node->hasLeaves;
440 
441  const std::size_t n_items = node->items.size();
442  const std::size_t distribution_count = n_items - 2*min_child_items + 1;
443 
444  std::size_t split_axis = dimensions+1, split_edge = 0, split_index = 0;
445  int split_margin = 0;
446 
447  BoundingBox R1, R2;
448 
449  // these should always hold true
450  assert(n_items == max_child_items + 1);
451  assert(distribution_count > 0);
452  assert(min_child_items + distribution_count-1 <= n_items);
453 
454  // S1: Invoke ChooseSplitAxis to determine the axis,
455  // perpendicular to which the split 1s performed
456  // S2: Invoke ChooseSplitIndex to determine the best
457  // distribution into two groups along that axis
458 
459  // NOTE: We don't compare against node->bound, so it gets overwritten
460  // at the end of the loop
461 
462  // CSA1: For each axis
463  for (std::size_t axis = 0; axis < dimensions; axis++)
464  {
465  // initialize per-loop items
466  int margin = 0;
467  double overlap = 0, dist_area, dist_overlap;
468  std::size_t dist_edge = 0, dist_index = 0;
469 
470  dist_area = dist_overlap = std::numeric_limits<double>::max();
471 
472 
473  // Sort the items by the lower then by the upper
474  // edge of their bounding box on this particular axis and
475  // determine all distributions as described . Compute S. the
476  // sum of all margin-values of the different
477  // distributions
478 
479  // lower edge == 0, upper edge = 1
480  for (std::size_t edge = 0; edge < 2; edge++)
481  {
482  // sort the items by the correct key (upper edge, lower edge)
483  if (edge == 0)
484  std::sort(node->items.begin(), node->items.end(), SortBoundedItemsByFirstEdge<BoundedItem>(axis));
485  else
486  std::sort(node->items.begin(), node->items.end(), SortBoundedItemsBySecondEdge<BoundedItem>(axis));
487 
488  // Distributions: pick a point m in the middle of the thing, call the left
489  // R1 and the right R2. Calculate the bounding box of R1 and R2, then
490  // calculate the margins. Then do it again for some more points
491  for (std::size_t k = 0; k < distribution_count; k++)
492  {
493  double area = 0;
494 
495  // calculate bounding box of R1
496  R1.reset();
497  for_each(node->items.begin(), node->items.begin()+(min_child_items+k), StretchBoundingBox<BoundedItem>(&R1));
498 
499  // then do the same for R2
500  R2.reset();
501  for_each(node->items.begin()+(min_child_items+k+1), node->items.end(), StretchBoundingBox<BoundedItem>(&R2));
502 
503 
504  // calculate the three values
505  margin += R1.edgeDeltas() + R2.edgeDeltas();
506  area += R1.area() + R2.area(); // TODO: need to subtract.. overlap?
507  overlap = R1.overlap(R2);
508 
509 
510  // CSI1: Along the split axis, choose the distribution with the
511  // minimum overlap-value. Resolve ties by choosing the distribution
512  // with minimum area-value.
513  if (overlap < dist_overlap || (overlap == dist_overlap && area < dist_area))
514  {
515  // if so, store the parameters that allow us to recreate it at the end
516  dist_edge = edge;
517  dist_index = min_child_items+k;
518  dist_overlap = overlap;
519  dist_area = area;
520  }
521  }
522  }
523 
524  // CSA2: Choose the axis with the minimum S as split axis
525  if (split_axis == dimensions+1 || split_margin > margin )
526  {
527  split_axis = axis;
528  split_margin = margin;
529  split_edge = dist_edge;
530  split_index = dist_index;
531  }
532  }
533 
534  // S3: Distribute the items into two groups
535 
536  // ok, we're done, and the best distribution on the selected split
537  // axis has been recorded, so we just have to recreate it and
538  // return the correct index
539 
540  if (split_edge == 0)
541  std::sort(node->items.begin(), node->items.end(), SortBoundedItemsByFirstEdge<BoundedItem>(split_axis));
542 
543  // only reinsert the sort key if we have to
544  else if (split_axis != dimensions-1)
545  std::sort(node->items.begin(), node->items.end(), SortBoundedItemsBySecondEdge<BoundedItem>(split_axis));
546 
547  // distribute the end of the array to the new node, then erase them from the original node
548  newNode->items.assign(node->items.begin() + split_index, node->items.end());
549  node->items.erase(node->items.begin() + split_index, node->items.end());
550 
551  // adjust the bounding box for each 'new' node
552  node->bound.reset();
553  std::for_each(node->items.begin(), node->items.end(), StretchBoundingBox<BoundedItem>(&node->bound));
554 
555  newNode->bound.reset();
556  std::for_each(newNode->items.begin(), newNode->items.end(), StretchBoundingBox<BoundedItem>(&newNode->bound));
557 
558  return newNode;
559  }
560 
561  // This routine is used to do the opportunistic reinsertion that the
562  // R* algorithm calls for
563  void Reinsert(Node * node)
564  {
565  std::vector< BoundedItem* > removed_items;
566 
567  const std::size_t n_items = node->items.size();
568  const std::size_t p = (std::size_t)((double)n_items * RTREE_REINSERT_P) > 0 ? (std::size_t)((double)n_items * RTREE_REINSERT_P) : 1;
569 
570  // RI1 For all M+l items of a node N, compute the distance
571  // between the centers of their rectangles and the center
572  // of the bounding rectangle of N
573  assert(n_items == max_child_items + 1);
574 
575  // RI2: Sort the items in increasing order of their distances
576  // computed in RI1
577  std::partial_sort(node->items.begin(), node->items.end() - p, node->items.end(),
579 
580  // RI3.A: Remove the last p items from N
581  removed_items.assign(node->items.end() - p, node->items.end());
582  node->items.erase(node->items.end() - p, node->items.end());
583 
584  // RI3.B: adjust the bounding rectangle of N
585  node->bound.reset();
586  for_each(node->items.begin(), node->items.end(), StretchBoundingBox<BoundedItem>(&node->bound));
587 
588  // RI4: In the sort, defined in RI2, starting with the
589  // minimum distance (= close reinsert), invoke Insert
590  // to reinsert the items
591  for (typename std::vector< BoundedItem* >::iterator it = removed_items.begin(); it != removed_items.end(); it++)
592  InsertInternal( static_cast<Leaf*>(*it), m_root, false);
593  }
594 
595  /****************************************************************
596  * These are used to implement walking the entire R* tree in a
597  * conditional way
598  ****************************************************************/
599 
600  // visits a node if necessary
601  template <typename Acceptor, typename Visitor>
602  struct VisitFunctor : std::unary_function< const BoundingBox *, void > {
603 
604  const Acceptor &accept;
606 
607  explicit VisitFunctor(const Acceptor &a, Visitor &v) : accept(a), visit(v) {}
608 
609  void operator()( BoundedItem * item )
610  {
611  Leaf * leaf = static_cast<Leaf*>(item);
612 
613  if (accept(leaf))
614  visit(leaf);
615  }
616  };
617 
618 
619  // this functor recursively walks the tree
620  template <typename Acceptor, typename Visitor>
621  struct QueryFunctor : std::unary_function< const BoundedItem, void > {
622  const Acceptor &accept;
624 
625  explicit QueryFunctor(const Acceptor &a, Visitor &v) : accept(a), visitor(v) {}
626 
627  void operator()(BoundedItem * item)
628  {
629  Node * node = static_cast<Node*>(item);
630 
631  if (visitor.ContinueVisiting && accept(node))
632  {
633  if (node->hasLeaves)
634  for_each(node->items.begin(), node->items.end(), VisitFunctor<Acceptor, Visitor>(accept, visitor));
635  else
636  for_each(node->items.begin(), node->items.end(), *this);
637  }
638  }
639  };
640 
641 
642  /****************************************************************
643  * Used to remove items from the tree
644  *
645  * At some point, the complexity just gets ridiculous. I'm pretty
646  * sure that the remove functions are close to that by now...
647  ****************************************************************/
648 
649 
650 
651  // determines whether a leaf should be deleted or not
652  template <typename Acceptor, typename LeafRemover>
654  std::unary_function< const BoundingBox *, bool >
655  {
656  const Acceptor &accept;
657  LeafRemover &remove;
658  std::size_t * size;
659 
660  explicit RemoveLeafFunctor(const Acceptor &a, LeafRemover &r, std::size_t * s) :
661  accept(a), remove(r), size(s) {}
662 
663  bool operator()(BoundedItem * item ) const {
664  Leaf * leaf = static_cast<Leaf *>(item);
665 
666  if (accept(leaf) && remove(leaf))
667  {
668  --(*size);
669  delete leaf;
670  return true;
671  }
672 
673  return false;
674  }
675  };
676 
677 
678  template <typename Acceptor, typename LeafRemover>
679  struct RemoveFunctor :
680  std::unary_function< const BoundedItem *, bool >
681  {
682  const Acceptor &accept;
683  LeafRemover &remove;
684 
685  // parameters that are passed in
686  std::list<Leaf*> * itemsToReinsert;
687  std::size_t * m_size;
688 
689  // the third parameter is a list that the items that need to be reinserted
690  // are put into
691  explicit RemoveFunctor(const Acceptor &na, LeafRemover &lr, std::list<Leaf*>* ir, std::size_t * size)
692  : accept(na), remove(lr), itemsToReinsert(ir), m_size(size) {}
693 
694  bool operator()(BoundedItem * item, bool isRoot = false)
695  {
696  Node * node = static_cast<Node*>(item);
697 
698  if (accept(node))
699  {
700  // this is the easy part: remove nodes if they need to be removed
701  if (node->hasLeaves)
702  node->items.erase(std::remove_if(node->items.begin(), node->items.end(), RemoveLeafFunctor<Acceptor, LeafRemover>(accept, remove, m_size)), node->items.end());
703  else
704  node->items.erase(std::remove_if(node->items.begin(), node->items.end(), *this), node->items.end() );
705 
706  if (!isRoot)
707  {
708  if (node->items.empty())
709  {
710  // tell parent to remove us if theres nothing left
711  delete node;
712  return true;
713  }
714  else if (node->items.size() < min_child_items)
715  {
716  // queue up the items that need to be reinserted
717  QueueItemsToReinsert(node);
718  return true;
719  }
720  }
721  else if (node->items.empty())
722  {
723  // if the root node is empty, setting these won't hurt
724  // anything, since the algorithms don't actually require
725  // the nodes to have anything in them.
726  node->hasLeaves = true;
727  node->bound.reset();
728  }
729  }
730 
731  // anything else, don't remove it
732  return false;
733 
734  }
735 
736  // theres probably a better way to do this, but this
737  // traverses and finds any leaves, and adds them to a
738  // list of items that will later be reinserted
739  void QueueItemsToReinsert(Node * node)
740  {
741  typename std::vector< BoundedItem* >::iterator it = node->items.begin();
742  typename std::vector< BoundedItem* >::iterator end = node->items.end();
743 
744  if (node->hasLeaves)
745  {
746  for(; it != end; it++)
747  itemsToReinsert->push_back(static_cast<Leaf*>(*it));
748  }
749  else
750  for (; it != end; it++)
751  QueueItemsToReinsert(static_cast<Node*>(*it));
752 
753  delete node;
754  }
755  };
756 
757 
758 private:
759  Node * m_root;
760 
761  std::size_t m_size;
762 };
763 
764 #undef RSTAR_TEMPLATE
765 
766 #undef RTREE_SPLIT_M
767 #undef RTREE_REINSERT_P
768 #undef RTREE_CHOOSE_SUBTREE_P
769 
770 
771 
772 
773 #endif
774 
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
~RStarTree()
Definition: RStarTree.h:115
intermediate_table::iterator iterator
Node * ChooseSubtree(Node *node, const BoundingBox *bound)
Definition: RStarTree.h:292
void operator()(BoundedItem *item)
Definition: RStarTree.h:609
void Remove(const Acceptor &accept, LeafRemover leafRemover)
Removes item(s) from the tree.
Definition: RStarTree.h:245
std::size_t GetDimensions() const
Definition: RStarTree.h:284
QMapNodeBase Node
Definition: qmap.cpp:41
#define RTREE_CHOOSE_SUBTREE_P
Definition: RStarTree.h:48
double overlap(const RStarBoundingBox< dimensions > &bb) const
const Acceptor & accept
Definition: RStarTree.h:682
const Acceptor & accept
Definition: RStarTree.h:656
bool ContinueVisiting
Definition: main.cpp:53
Implementation of an RTree with an R* index.
Definition: RStarTree.h:87
void Insert(LeafType leaf, const BoundingBox &bound)
Definition: RStarTree.h:123
std::list< Leaf * > * itemsToReinsert
Definition: RStarTree.h:686
RStarAcceptOverlapping< Node, Leaf > AcceptOverlapping
Definition: RStarTree.h:98
LeafType leaf_type
Definition: RStarTree.h:58
std::vector< BoundedItem * > items
Definition: RStarTree.h:65
double area() const
void Reinsert(Node *node)
Definition: RStarTree.h:563
LeafType leaf
Definition: RStarTree.h:59
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
Node * m_root
Definition: RStarTree.h:759
RStarLeaf< BoundedItem, LeafType > Leaf
Definition: RStarTree.h:95
const Acceptor & accept
Definition: RStarTree.h:604
const double a
std::size_t * m_size
Definition: RStarTree.h:687
p
Definition: test.py:223
int edgeDeltas() const
RemoveFunctor(const Acceptor &na, LeafRemover &lr, std::list< Leaf * > *ir, std::size_t *size)
Definition: RStarTree.h:691
bool hasLeaves
Definition: RStarTree.h:66
BoundedItem::BoundingBox BoundingBox
Definition: RStarTree.h:92
std::size_t GetSize() const
Definition: RStarTree.h:283
bool operator()(BoundedItem *item, bool isRoot=false)
Definition: RStarTree.h:694
RStarRemoveLeaf< Leaf > RemoveLeaf
Definition: RStarTree.h:103
static int max(int a, int b)
void QueueItemsToReinsert(Node *node)
Definition: RStarTree.h:739
const Acceptor & accept
Definition: RStarTree.h:622
Definition: main.cpp:51
RStarAcceptAny< Node, Leaf > AcceptAny
Definition: RStarTree.h:100
VisitFunctor(const Acceptor &a, Visitor &v)
Definition: RStarTree.h:607
RStarBoundedItem< dimensions > BoundedItem
Definition: RStarTree.h:91
vector< string > Split(string input, string delim)
Definition: StringUtils.cxx:36
RStarAcceptEnclosing< Node, Leaf > AcceptEnclosing
Definition: RStarTree.h:99
RStarRemoveSpecificLeaf< Leaf > RemoveSpecificLeaf
Definition: RStarTree.h:104
bool operator()(BoundedItem *item) const
Definition: RStarTree.h:663
void operator()(BoundedItem *item)
Definition: RStarTree.h:627
std::size_t m_size
Definition: RStarTree.h:761
RemoveLeafFunctor(const Acceptor &a, LeafRemover &r, std::size_t *s)
Definition: RStarTree.h:660
Visitor Query(const Acceptor &accept, Visitor visitor)
Touches each node using the visitor pattern.
Definition: RStarTree.h:215
query_result< Args... > query(sqlite3 *db, std::string const &ddl)
Definition: select.h:75
QueryFunctor(const Acceptor &a, Visitor &v)
Definition: RStarTree.h:625
Node * Split(Node *node)
Definition: RStarTree.h:436
Node * OverflowTreatment(Node *level, bool firstInsert)
Definition: RStarTree.h:393
static QCString * s
Definition: config.cpp:1042
void RemoveItem(const LeafType &item, bool removeDuplicates=true)
Definition: RStarTree.h:277
void RemoveBoundedArea(const BoundingBox &bound)
Definition: RStarTree.h:270
RStarNode< BoundedItem > Node
Definition: RStarTree.h:94
#define RTREE_REINSERT_P
Definition: RStarTree.h:47
Node * InsertInternal(Leaf *leaf, Node *node, bool firstInsert=true)
Definition: RStarTree.h:343