Index.h
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file Index.h
22 
23  \brief An implementation of R-tree data structure for main memory.
24 */
25 
26 #ifndef __TERRALIB_SAM_RTREE_INTERNAL_INDEX_H
27 #define __TERRALIB_SAM_RTREE_INTERNAL_INDEX_H
28 
29 // TerraLib
30 #include "Node.h"
31 #include "PartitionVars.h"
32 
33 // STL
34 #include <cassert>
35 #include <vector>
36 
37 namespace te
38 {
39  namespace sam
40  {
41  namespace rtree
42  {
43  /*!
44  \class Index
45 
46  \brief A class that represents an R-tree.
47 
48  This implementation is based on:
49 
50  <i>Antonin Guttman. R-Trees: A Dynamic Index Structure for Spatial Searching. ACM SIGMOD: International Conference on Management of Data, 1984, pp. 47-57</i>.
51 
52  and in his original source code.
53 
54  \todo Implement nearest neighbour query.
55  */
56  template<class DATATYPE, int MAXNODES = 8, int MINNODES = MAXNODES / 2> class Index
57  {
58  public:
59 
61  typedef typename NodeType::BranchType BranchType;
63 
64  /*! \brief Constructor. */
65  Index();
66 
67  /*!
68  \brief Constructor.
69 
70  \param mbr The MBR of all elements in the R-tree.
71 
72  \pre The given MBR must be valid.
73  */
74  Index(const te::gm::Envelope& mbr);
75 
76  /*! \brief Destructor. */
77  ~Index();
78 
79  /*!
80  \brief It returns the number of elements in the tree.
81 
82  \return The number of indexed elements.
83  */
84  std::size_t size(void) const;
85 
86  /*!
87  \brief It returns true if the tree is empty.
88 
89  \return True if the tree is empty.
90  */
91  bool isEmpty(void) const;
92 
93  /*! It clears all tree nodes and make it ready for new insertions. */
94  void clear(void);
95 
96  /*!
97  \brief It inserts an item into the tree.
98 
99  \param mbr The object MBR.
100  \param data The object to be indexed.
101  */
102  void insert(const te::gm::Envelope& mbr, const DATATYPE& data);
103 
104  /*!
105  \brief It removes an item from the tree.
106 
107  \param mbr The object MBR.
108  \param data The object to be removed from the tree.
109 
110  \return True if the object is found and removed, false otherwise.
111  */
112  bool remove(const te::gm::Envelope& mbr, const DATATYPE& data);
113 
114  /*!
115  \brief Range search query.
116 
117  \param mbr The search rectangle.
118  \param report A vector to output the founded objects.
119 
120  \return the number of found objects.
121  */
122  int search(const te::gm::Envelope& mbr, std::vector<DATATYPE>& report) const;
123 
124  /*!
125  \brief It sets the bounding box of all elements in the tree.
126 
127  \param mbr The bounding box of all elements in the tree.
128  */
129  void setMBR(const te::gm::Envelope& mbr);
130 
131  /*!
132  \brief It returns the bounding box of all elements in the tree.
133 
134  \return The bounding box of all elements in the tree.
135  */
136  const te::gm::Envelope& getMBR(void) const;
137 
138  protected:
139 
140  /*!
141  \brief It inserts a data rectangle into an index structure.
142 
143  \return It returns true if root was split, false if it was not.
144  */
145  bool insert(const te::gm::Envelope& mbr, const DATATYPE& data, NodeType** root, int level);
146 
147  /*!
148  \brief It deletes a data rectangle from an index structure.
149 
150  \return It returns 1 if record not found, 0 if success.
151  */
152  bool remove(const te::gm::Envelope& mbr, const DATATYPE& data, NodeType** root);
153 
154  /*!
155  \brief It deletes a rectangle from non-root part of an index structure.
156 
157  \return
158  */
159  bool remove2(const te::gm::Envelope& mbr, const DATATYPE& data, NodeType* n, std::vector<NodeType*>& ee);
160 
161  /*!
162  \brief It disconnects a dependent node.
163  */
164  void disconBranch(NodeType* n, int i);
165 
166  /*!
167  \brief It inserts a new data rectangle into the index structure.
168  */
169  bool chooseLeaf(const te::gm::Envelope& mbr,
170  const DATATYPE& data,
171  NodeType* node,
172  NodeType** newNode,
173  int level);
174 
175  /*!
176  \brief Recursive range query.
177  */
178  void search(const te::gm::Envelope& mbr,
179  NodeType* node,
180  std::vector<DATATYPE>& report,
181  int& foundObjs) const;
182 
183  /*!
184  \brief Find the smallest rectangle that includes all rectangles in branches of a node.
185  */
187 
188  /*!
189  \brief Combine two rectangles into larger one containing both.
190  */
192  const te::gm::Envelope& mbrB) const;
193 
194  /*!
195  \brief Add a branch to a node.
196  */
197  bool addBranch(BranchType* branch,
198  NodeType* node,
199  NodeType** newNode) const;
200 
201  /*!
202  \brief Pick a branch.
203  */
204  int pickBranch(const te::gm::Envelope& mbr, NodeType* node) const;
205 
206  /*!
207  \brief Split a node.
208  */
209  void splitNode(NodeType* node, BranchType* branch, NodeType** newNode) const;
210 
212 
214 
215  void pickSeeds(PartitionVarsType& p) const;
216 
217  void classify(int i, int group, PartitionVarsType& p) const;
218 
220 
222 
223  /*!
224  \brief Erases a node from the tree and all nodes below it.
225 
226  \param node The node to be removed.
227 
228  \pos The node pointer will be invalidated.
229  */
230  void erase(NodeType* node);
231 
232 
233  private:
234 
235 
236  /*!
237  \brief No copy constructor allowed.
238 
239  \param rhs The other rtree.
240  */
241  Index(const Index& rhs);
242 
243  /*!
244  \brief No assignment operator allowed.
245 
246  \param rhs The other rtree.
247 
248  \return A reference for this instance.
249  */
250  Index& operator=(const Index& rhs);
251 
252 
253  private:
254 
255  NodeType* m_root; //!< Pointer to the root node.
256  te::gm::Envelope m_mbr; //!< Bounding box of the tree.
257  mutable std::size_t m_size; //!< The size of R-Tree (number of nodes).
258  };
259 
260  template<class DATATYPE, int MAXNODES, int MINNODES> inline
262  : m_root(0), m_size(0)
263  {
264  ++m_size;
265  m_root = new NodeType();
266  m_root->m_level = 0;
267  }
268 
269  template<class DATATYPE, int MAXNODES, int MINNODES> inline
271  : m_root(0), m_mbr(mbr), m_size(0)
272  {
273  assert(m_mbr.isValid());
274  ++m_size;
275  m_root = new NodeType();
276  m_root->m_level = 0;
277  }
278 
279  template<class DATATYPE, int MAXNODES, int MINNODES> inline
281  {
282  clear();
283  delete m_root;
284  }
285 
286  template<class DATATYPE, int MAXNODES, int MINNODES> inline
288  {
289  return m_size;
290  }
291 
292  template<class DATATYPE, int MAXNODES, int MINNODES> inline
294  {
295  return (m_root->m_count == 0);
296  }
297 
298  template<class DATATYPE, int MAXNODES, int MINNODES> inline
300  {
301  if(m_root)
302  {
303  erase(m_root);
304  m_root = 0;
305 
306  m_size = 1;
307  m_root = new NodeType();
308  m_root->m_level = 0;
309  }
310  }
311 
312  template<class DATATYPE, int MAXNODES, int MINNODES> inline
313  void Index<DATATYPE, MAXNODES, MINNODES>::insert(const te::gm::Envelope& mbr, const DATATYPE& data)
314  {
315  insert(mbr, data, &m_root, 0);
316  m_mbr.Union(mbr);
317  }
318 
319  template<class DATATYPE, int MAXNODES, int MINNODES> inline
320  bool Index<DATATYPE, MAXNODES, MINNODES>::remove(const te::gm::Envelope& mbr, const DATATYPE& data)
321  {
322  return remove(mbr, data, &m_root);
323  }
324 
325  template<class DATATYPE, int MAXNODES, int MINNODES> inline
326  int Index<DATATYPE, MAXNODES, MINNODES>::search(const te::gm::Envelope& mbr, std::vector<DATATYPE>& report) const
327  {
328  int foundObjs = 0;
329 
330  if(m_root)
331  search(mbr, m_root, report, foundObjs);
332 
333  return foundObjs;
334  }
335 
336  template<class DATATYPE, int MAXNODES, int MINNODES> inline
338  {
339  m_mbr = mbr;
340  }
341 
342  template<class DATATYPE, int MAXNODES, int MINNODES> inline
344  {
345  return m_mbr;
346  }
347 
348  template<class DATATYPE, int MAXNODES, int MINNODES> inline
349  bool Index<DATATYPE, MAXNODES, MINNODES>::insert(const te::gm::Envelope& mbr, const DATATYPE& data, NodeType** root, int level)
350  {
351 // this is the algorithm insert
352  NodeType* newNode;
353 
354  if(chooseLeaf(mbr, data, *root, &newNode, level)) // I1
355  {
356 // I4
357 // if root was split
358 // grow a new root, make tree taller
359  ++m_size;
360  NodeType* newRoot = new NodeType();
361 
362  newRoot->m_level = (*root)->m_level + 1;
363 
364 // first half node
365  BranchType branch;
366  branch.m_mbr = nodeCover(*root);
367  branch.m_child = *root;
368  addBranch(&branch, newRoot, 0);
369 
370 // second half node
371  branch.m_mbr = nodeCover(newNode);
372  branch.m_child = newNode;
373  addBranch(&branch, newRoot, 0);
374 
375  *root = newRoot;
376 
377  return true;
378  }
379 
380  return false;
381  }
382 
383  template<class DATATYPE, int MAXNODES, int MINNODES> inline
384  bool Index<DATATYPE, MAXNODES, MINNODES>::remove(const te::gm::Envelope& mbr, const DATATYPE& data, NodeType** root)
385  {
386  NodeType *t;
387  std::vector<NodeType*> reInsertList;
388 
389  if(remove2(mbr, data, *root, reInsertList))
390  {
391 // if we are here, so we have found and deleted a data item
392 
393 // reinsert any branches from eliminated nodes
394  while(!reInsertList.empty())
395  {
396  t = reInsertList[0];
397 
398  for(int i = 0; i < t->m_count; ++i)
399  insert(t->m_branch[i].m_mbr, t->m_branch[i].m_data, root, t->m_level);
400 
401 // erase node from list
402  reInsertList.erase(reInsertList.begin());
403 
404 // remove node card from memory
405  delete t;
406  --m_size;
407  }
408 
409 // check for redundant root (not leaf, 1 child) and eliminate
410  if(((*root)->m_count == 1) && ((*root)->isInternalNode()))
411  {
412  t = (*root)->m_branch[0].m_child;
413 
414  delete (*root);
415  --m_size;
416 
417  *root = t;
418  }
419 
420  return true;
421  }
422 
423  return false;
424  }
425 
426  template<class DATATYPE, int MAXNODES, int MINNODES> inline
427  bool Index<DATATYPE, MAXNODES, MINNODES>::remove2(const te::gm::Envelope& mbr, const DATATYPE& data, NodeType* n, std::vector<NodeType*>& ee)
428  {
429  int i;
430 
431  if(n->isInternalNode()) /* not a leaf node */
432  {
433  for(i = 0; i < n->m_count; ++i)
434  {
435  if(mbr.intersects(n->m_branch[i].m_mbr))
436  {
437  if(remove2(mbr, data, n->m_branch[i].m_child, ee))
438  {
439  if(n->m_branch[i].m_child->m_count >= MINNODES)
440  n->m_branch[i].m_mbr = nodeCover(n->m_branch[i].m_child);
441  else
442  {
443  /* not enough entries in child, eliminate child node */
444  ee.push_back(n->m_branch[i].m_child); //reInsert(n->m_branch[i].m_child, ee);
445  disconBranch(n, i);
446  }
447 
448  return true; // found item
449  }
450  }
451  }
452 
453  return false; // din't find item
454  }
455  else /* a leaf node */
456  {
457  for(i = 0; i < n->m_count; ++i)
458  {
459  if(n->m_branch[i].m_data == data)
460  {
461  disconBranch(n, i);
462  return true; // found item
463  }
464  }
465 
466  return false; // didn't find item
467  }
468  }
469 
470  template<class DATATYPE, int MAXNODES, int MINNODES>
472  {
473 // remove element copying the last element in array
474  n->m_branch[i] = n->m_branch[n->m_count - 1];
475 
476  --(n->m_count);
477  }
478 
479  template<class DATATYPE, int MAXNODES, int MINNODES>
480  bool Index<DATATYPE, MAXNODES, MINNODES>::chooseLeaf(const te::gm::Envelope& mbr, const DATATYPE& data, NodeType* node, NodeType** newNode, int level)
481  {
482  if(node->m_level > level)
483  {
484 // Still above level for insertion, go down tree recursively
485  int i = pickBranch(mbr, node); // CL3
486 
487  NodeType* n2;
488  if(!chooseLeaf(mbr, data, node->m_branch[i].m_child, &n2, level))
489  {
490 // child was not split
491  node->m_branch[i].m_mbr = combineRect(mbr, node->m_branch[i].m_mbr);
492 
493  return false;
494  }
495  else
496  {
497 // child was split
498  node->m_branch[i].m_mbr = nodeCover(node->m_branch[i].m_child);
499 
500  BranchType b;
501  b.m_child = n2;
502  b.m_mbr = nodeCover(n2);
503 
504  return addBranch(&b, node, newNode);
505  }
506  }
507  else if (node->m_level == level)
508  {
509 // have reached level for insertion. Add mbr, split if necessary
510  BranchType b;
511  b.m_mbr = mbr;
512  //b.m_child = (NodeType*) data;
513  b.m_data = data;
514 
515 // child field of leaves contains tid of data record
516  return addBranch(&b, node, newNode);
517  }
518  else
519  {
520 // Not supposed to happen
521  //throw;
522  return false;
523  }
524  }
525 
526  template<class DATATYPE, int MAXNODES, int MINNODES>
527  void Index<DATATYPE, MAXNODES, MINNODES>::search(const te::gm::Envelope& mbr, NodeType* node, std::vector<DATATYPE>& report, int& foundObjs) const
528  {
529  int i;
530 // S1
531  if(node->isInternalNode()) // This is an internal node in the tree
532  {
533  for(i = 0; i < node->m_count; ++i)
534  {
535  if(mbr.intersects(node->m_branch[i].m_mbr))
536  search(mbr, node->m_branch[i].m_child, report, foundObjs);
537  }
538  }
539 // S2
540  else // This is a leaf node
541  {
542  for(i = 0; i < node->m_count; ++i)
543  {
544  if(mbr.intersects(node->m_branch[i].m_mbr))
545  {
546  DATATYPE& id = node->m_branch[i].m_data;
547  report.push_back(id);
548 
549  ++foundObjs;
550  }
551  }
552  }
553 
554  return;
555  }
556 
557  template<class DATATYPE, int MAXNODES, int MINNODES>
559  {
560  bool flag = true;
561 
563 
564  for(int i = 0; i < n->m_count; ++i)
565  {
566  if(flag)
567  {
568  r = n->m_branch[i].m_mbr;
569  flag = false;
570  }
571  else
572  r = combineRect(r, n->m_branch[i].m_mbr);
573  }
574 
575  return r;
576  }
577 
578  template<class DATATYPE, int MAXNODES, int MINNODES> inline
580  {
581  te::gm::Envelope newRect(mbrA);
582  newRect.Union(mbrB);
583  return newRect;
584  }
585 
586  template<class DATATYPE, int MAXNODES, int MINNODES> inline
588  {
589  if(node->m_count < MAXNODES) /* split won't be necessary */
590  {
591  node->m_branch[node->m_count] = *branch;
592  ++(node->m_count);
593  return false;
594  }
595  else
596  {
597  splitNode(node, branch, newNode);
598  return true;
599  }
600  }
601 
602  template<class DATATYPE, int MAXNODES, int MINNODES> inline
604  {
605 // CL3
606  bool flag = true;
607  double bestIncr = -1.0;
608  double bestArea = 0.;
609  int best = 0;
610 
611  for(int i = 0; i < node->m_count; ++i)
612  {
613  te::gm::Envelope rr = node->m_branch[i].m_mbr;
614  double area = rr.getArea();
615 
616  rr = combineRect(mbr, rr);
617 
618  double increase = rr.getArea() - area;
619 
620  if((increase < bestIncr) || flag)
621  {
622  best = i;
623  bestArea = area;
624  bestIncr = increase;
625  flag = false;
626  }
627  else if((increase == bestIncr) && (area < bestArea))
628  {
629  best = i;
630  bestArea = area;
631  bestIncr = increase;
632  }
633  }
634 
635  return best;
636  }
637 
638  template<class DATATYPE, int MAXNODES, int MINNODES> inline
640  {
641  PartitionVarsType partitions;
642 
643 // load all the branches into a buffer, initialize old node
644  int level = node->m_level;
645 
646  getBranches(node, branch, partitions);
647 
648 // find partition
649  methodZero(partitions);
650 
651 // put branches from buffer into 2 nodes according to chosen partition
652  ++m_size;
653 
654  *newNode = new NodeType();
655  (*newNode)->m_level = node->m_level = level;
656 
657  loadNodes(node, *newNode, partitions);
658  }
659 
660  template<class DATATYPE, int MAXNODES, int MINNODES> inline
662  {
663 // load the branch buffer
664  for(int i = 0; i < MAXNODES; ++i)
665  {
666  p.m_branchBuf[i] = n->m_branch[i];
667  }
668 
669  p.m_branchBuf[MAXNODES] = *b;
670 
671 // calculate mbr containing all in the set
672  p.m_coverSplit = p.m_branchBuf[0].m_mbr;
673 
674  for(int i = 1; i <= MAXNODES; ++i)
675  p.m_coverSplit = combineRect(p.m_coverSplit, p.m_branchBuf[i].m_mbr);
676 
677  n->init();
678  }
679 
680  template<class DATATYPE, int MAXNODES, int MINNODES> inline
682  {
683  p.init();
684  pickSeeds(p);
685  pigeonhole(p);
686  }
687 
688  template<class DATATYPE, int MAXNODES, int MINNODES> inline
690  {
691  double w;
692  double separation;
693  double bestSep;
694  double width[2];
695  int leastUpper[2];
696  int greatestLower[2];
697  int seed0;
698  int seed1;
699  int i;
700 // LPS1
701 // find the rectangles farthest out in each dimbrion along dimens "x"
702  greatestLower[0] = leastUpper[0] = 0;
703 
704  for(i = 1; i <= MAXNODES; ++i)
705  {
706  te::gm::Envelope& r = p.m_branchBuf[i].m_mbr;
707 
708  if(r.m_llx > p.m_branchBuf[greatestLower[0]].m_mbr.m_llx)
709  greatestLower[0] = i;
710 
711  if(r.m_urx < p.m_branchBuf[leastUpper[0]].m_mbr.m_urx)
712  leastUpper[0] = i;
713  }
714 
715 // LPS2
716 // LPS3
717 // find the width of the whole collection along this dimension
718  width[0] = p.m_coverSplit.m_urx - p.m_coverSplit.m_llx;
719 
720 // find the rectangles farthest out in each dimbrion along dimens "y"
721  greatestLower[1] = leastUpper[1] = 0;
722 
723  for(i = 1; i <= MAXNODES; ++i)
724  {
725  te::gm::Envelope& r = p.m_branchBuf[i].m_mbr;
726 
727  if(r.m_lly > p.m_branchBuf[greatestLower[1]].m_mbr.m_lly)
728  greatestLower[1] = i;
729 
730  if(r.m_ury < p.m_branchBuf[leastUpper[1]].m_mbr.m_ury)
731  leastUpper[1] = i;
732  }
733 
734 // LPS2
735 // LPS3
736 // find the width of the whole collection along this dimension
737  width[1] = p.m_coverSplit.m_ury - p.m_coverSplit.m_lly;
738 
739 
740 // pick the best separation dimension and the two seed mbrs
741 
742 // divisor for normalizing by width
743 
744 // x
745  if(width[0] == 0.0)
746  w = 1.0;
747  else
748  w = width[0];
749 
750  te::gm::Envelope rlow = p.m_branchBuf[leastUpper[0]].m_mbr;
751  te::gm::Envelope rhigh = p.m_branchBuf[greatestLower[0]].m_mbr;
752 
753  seed0 = leastUpper[0];
754  seed1 = greatestLower[0];
755 
756  bestSep = (rhigh.m_llx - rlow.m_urx) / w;
757 
758 // y
759  if(width[1] == 0.0)
760  w = 1.0;
761  else
762  w = width[1];
763 
764  rlow = p.m_branchBuf[leastUpper[1]].m_mbr;
765  rhigh = p.m_branchBuf[greatestLower[1]].m_mbr;
766 
767  separation = (rhigh.m_lly - rlow.m_ury) / w;
768 
769 // LPS3
770  if(separation > bestSep)
771  {
772  seed0 = leastUpper[1];
773  seed1 = greatestLower[1];
774 
775  bestSep = separation;
776  }
777 
778  if(seed0 != seed1)
779  {
780  classify(seed0, 0, p);
781  classify(seed1, 1, p);
782  }
783  }
784 
785  template<class DATATYPE, int MAXNODES, int MINNODES> inline
787  {
788  p.m_partition[i] = group;
789  p.m_taken[i] = 1;
790 
791  if(p.m_count[group] == 0)
792  p.m_cover[group] = p.m_branchBuf[i].m_mbr;
793  else
794  p.m_cover[group] = combineRect(p.m_branchBuf[i].m_mbr, p.m_cover[group]);
795 
796  p.m_area[group] = p.m_cover[group].getArea();
797 
798  ++(p.m_count[group]);
799  }
800 
801  template<class DATATYPE, int MAXNODES, int MINNODES> inline
803  {
804  te::gm::Envelope newCover[2];
805 
806  double newArea[2];
807  double increase[2];
808 
809  for(int i = 0; i <= MAXNODES; ++i)
810  {
811  if(p.m_taken[i] == 0)
812  {
813 // if one group too full, put mbr in the other regardless
814  if(p.m_count[0] >= (MAXNODES + 1 - MINNODES))
815  {
816  classify(i, 1, p);
817  continue;
818  }
819  else if(p.m_count[1] >= (MAXNODES + 1 - MINNODES))
820  {
821  classify(i, 0, p);
822  continue;
823  }
824 
825 // find the areas of the two groups' old and new covers
826  for(int group = 0; group < 2; ++group)
827  {
828  if(p.m_count[group] > 0)
829  {
830  newCover[group] = combineRect(p.m_branchBuf[i].m_mbr, p.m_cover[group]);
831  }
832  else
833  {
834  newCover[group] = p.m_branchBuf[i].m_mbr;
835  }
836 
837  newArea[group] = newCover[group].getArea();
838  increase[group] = newArea[group] - p.m_area[group];
839  }
840 
841 // put mbr in group whose cover will need to expand less
842  if(increase[0] < increase[1])
843  classify(i, 0, p);
844  else if(increase[1] < increase[0])
845  classify(i, 1, p);
846 // put mbr in group that will have a smaller area cover
847  else if(p.m_area[0] < p.m_area[1])
848  classify(i, 0, p);
849  else if(p.m_area[1] < p.m_area[0])
850  classify(i, 1, p);
851 // put mbr in group with fewer elements
852  else if(p.m_count[0] < p.m_count[1])
853  classify(i, 0, p);
854  else
855  classify(i, 1, p);
856  }
857  }
858  }
859 
860  template<class DATATYPE, int MAXNODES, int MINNODES> inline
862  {
863  for(int i = 0; i <= MAXNODES; ++i)
864  {
865  if(p.m_partition[i] == 0)
866  addBranch(&(p.m_branchBuf[i]), n, 0);
867  else if(p.m_partition[i] == 1)
868  addBranch(&(p.m_branchBuf[i]), q, 0);
869  //else
870  // throw; // ERROR
871  }
872  }
873 
874  template<class DATATYPE, int MAXNODES, int MINNODES> inline
876  {
877  if(node->isLeaf())
878  {
879  delete node;
880  return;
881  }
882 
883  for(int i = 0u; i < node->m_count; ++i)
884  erase(node->m_branch[i].m_child);
885 
886  delete node;
887  return;
888  }
889 
890  } // end namespace rtree
891  } // end namespace sam
892 } // end namespace te
893 
894 
895 #endif // __TERRALIB_SAM_RTREE_INTERNAL_INDEX_H
896 
te::gm::Envelope
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:52
te::sam::rtree::Index::getMBR
const te::gm::Envelope & getMBR(void) const
It returns the bounding box of all elements in the tree.
Definition: Index.h:343
te::sam::rtree::Branch< Node, DATATYPE >
te
TerraLib.
Definition: AddressGeocodingOp.h:52
te::gm::Envelope::isValid
bool isValid() const
It tells if the rectangle is valid or not.
te::sam::rtree::Index::splitNode
void splitNode(NodeType *node, BranchType *branch, NodeType **newNode) const
Split a node.
Definition: Index.h:639
te::sam::rtree::Index::chooseLeaf
bool chooseLeaf(const te::gm::Envelope &mbr, const DATATYPE &data, NodeType *node, NodeType **newNode, int level)
It inserts a new data rectangle into the index structure.
Definition: Index.h:480
te::sam::rtree::Index::pigeonhole
void pigeonhole(PartitionVarsType &p) const
Definition: Index.h:802
te::sam::rtree::Index
A class that represents an R-tree.
Definition: Index.h:57
te::sam::rtree::Node::m_count
int m_count
The number of elements in the node (count).
Definition: Node.h:110
te::gm::Envelope::getArea
double getArea() const
It returns the area of this envelope as measured in the spatial reference system of it.
Definition: Envelope.h:452
te::sam::rtree::Node::isInternalNode
bool isInternalNode() const
It returns true if this is a internal node.
Definition: Node.h:62
te::sam::rtree::Index::disconBranch
void disconBranch(NodeType *n, int i)
It disconnects a dependent node.
Definition: Index.h:471
PartitionVars.h
te::sam::rtree::Node::m_level
int m_level
Leaf is zero, others positive.
Definition: Node.h:111
te::sam::rtree::Index::combineRect
te::gm::Envelope combineRect(const te::gm::Envelope &mbrA, const te::gm::Envelope &mbrB) const
Combine two rectangles into larger one containing both.
Definition: Index.h:579
te::sam::rtree::Index::NodeType
Node< DATATYPE, MAXNODES, MINNODES > NodeType
Definition: Index.h:60
te::sam::rtree::Index::methodZero
void methodZero(PartitionVarsType &p) const
Definition: Index.h:681
te::gm::Envelope::m_llx
double m_llx
Lower left corner x-coordinate.
Definition: Envelope.h:344
te::sam::rtree::Index::size
std::size_t size(void) const
It returns the number of elements in the tree.
Definition: Index.h:287
te::sam::rtree::Node::init
void init()
This method is used during split when a node retained and used again (beeing re-filled).
Definition: Node.h:78
te::sam::rtree::Index::operator=
Index & operator=(const Index &rhs)
No assignment operator allowed.
te::gm::Envelope::Union
void Union(const Envelope &rhs)
It updates the envelop with coordinates of another envelope.
Definition: Envelope.h:554
te::sam::rtree::Index::insert
bool insert(const te::gm::Envelope &mbr, const DATATYPE &data, NodeType **root, int level)
It inserts a data rectangle into an index structure.
Definition: Index.h:349
te::sam::rtree::PartitionVars
Auxiliary structure when searching for a split partition.
Definition: PartitionVars.h:44
te::sam::rtree::Branch::m_data
DATATYPE m_data
An object-identifier (oid).
Definition: Branch.h:52
te::sam::rtree::Index::PartitionVarsType
te::sam::rtree::PartitionVars< BranchType, MAXNODES > PartitionVarsType
Definition: Index.h:62
te::sam::rtree::Index::clear
void clear(void)
Definition: Index.h:299
te::sam::rtree::PartitionVars::m_area
double m_area[2]
Auxiliary area of each new page.
Definition: PartitionVars.h:49
te::sam::rtree::Index::pickSeeds
void pickSeeds(PartitionVarsType &p) const
Definition: Index.h:689
Node.h
A class that represents an R-tree node.
te::sam::rtree::Index::remove
bool remove(const te::gm::Envelope &mbr, const DATATYPE &data)
It removes an item from the tree.
Definition: Index.h:320
te::gm::Envelope::m_urx
double m_urx
Upper right corner x-coordinate.
Definition: Envelope.h:346
te::sam::rtree::Index::search
void search(const te::gm::Envelope &mbr, NodeType *node, std::vector< DATATYPE > &report, int &foundObjs) const
Recursive range query.
Definition: Index.h:527
te::sam::rtree::Index::m_root
NodeType * m_root
Pointer to the root node.
Definition: Index.h:255
te::sam::rtree::Index::remove2
bool remove2(const te::gm::Envelope &mbr, const DATATYPE &data, NodeType *n, std::vector< NodeType * > &ee)
It deletes a rectangle from non-root part of an index structure.
Definition: Index.h:427
te::sam::rtree::Index::remove
bool remove(const te::gm::Envelope &mbr, const DATATYPE &data, NodeType **root)
It deletes a data rectangle from an index structure.
Definition: Index.h:384
te::xml::NodeType
NodeType
The type of node read by XML reader.
Definition: Enums.h:41
insert
mydialect insert("+", new te::da::BinaryOpEncoder("+"))
te::sam::rtree::Index::erase
void erase(NodeType *node)
Erases a node from the tree and all nodes below it.
Definition: Index.h:875
te::sam::rtree::Index::Index
Index(const te::gm::Envelope &mbr)
Constructor.
Definition: Index.h:270
te::sam::rtree::Node
A class that represents an R-tree node.
Definition: Node.h:46
te::gm::Envelope::m_lly
double m_lly
Lower left corner y-coordinate.
Definition: Envelope.h:345
te::sam::rtree::Index::nodeCover
te::gm::Envelope nodeCover(NodeType *n) const
Find the smallest rectangle that includes all rectangles in branches of a node.
Definition: Index.h:558
te::sam::rtree::Index::addBranch
bool addBranch(BranchType *branch, NodeType *node, NodeType **newNode) const
Add a branch to a node.
Definition: Index.h:587
te::sam::rtree::Index::search
int search(const te::gm::Envelope &mbr, std::vector< DATATYPE > &report) const
Range search query.
Definition: Index.h:326
te::sam::rtree::Branch::m_mbr
te::gm::Envelope m_mbr
Bounding box containing all the objects under the branch or an object bounding box.
Definition: Branch.h:47
te::sam::rtree::Index::BranchType
NodeType::BranchType BranchType
Definition: Index.h:61
te::sam::rtree::Node::isLeaf
bool isLeaf() const
It returns true if this is a leaf node.
Definition: Node.h:72
te::sam::rtree::Index::getBranches
void getBranches(NodeType *n, BranchType *b, PartitionVarsType &p) const
Definition: Index.h:661
te::sam::rtree::Index::Index
Index()
Constructor.
Definition: Index.h:261
te::sam::rtree::PartitionVars::m_coverSplit
te::gm::Envelope m_coverSplit
Auxiliary box covering branchBuf.
Definition: PartitionVars.h:51
te::sam::rtree::Index::isEmpty
bool isEmpty(void) const
It returns true if the tree is empty.
Definition: Index.h:293
te::sam::rtree::Index::m_mbr
te::gm::Envelope m_mbr
Bounding box of the tree.
Definition: Index.h:256
te::sam::rtree::Index::classify
void classify(int i, int group, PartitionVarsType &p) const
Definition: Index.h:786
te::sam::rtree::PartitionVars::m_cover
te::gm::Envelope m_cover[2]
Auxiliary box of each new page.
Definition: PartitionVars.h:48
te::sam::rtree::Node::m_branch
BranchType m_branch[MAXNODES]
Branches.
Definition: Node.h:112
te::sam::rtree::PartitionVars::m_count
int m_count[2]
Number of entries in each new page.
Definition: PartitionVars.h:47
te::sam::rtree::PartitionVars::m_taken
int m_taken[MAXNODES+1]
Flag to indicate that entry is ok.
Definition: PartitionVars.h:46
te::sam::rtree::Index::~Index
~Index()
Destructor.
Definition: Index.h:280
te::sam::rtree::Index::insert
void insert(const te::gm::Envelope &mbr, const DATATYPE &data)
It inserts an item into the tree.
Definition: Index.h:313
te::gm::Envelope::m_ury
double m_ury
Upper right corner y-coordinate.
Definition: Envelope.h:347
te::gm::Envelope::intersects
bool intersects(const Envelope &rhs) const
It returns true if the envelopes "spatially intersects".
Definition: Envelope.h:492
te::sam::rtree::Index::Index
Index(const Index &rhs)
No copy constructor allowed.
te::sam::rtree::Index::pickBranch
int pickBranch(const te::gm::Envelope &mbr, NodeType *node) const
Pick a branch.
Definition: Index.h:603
te::sam::rtree::Branch::m_child
NODE * m_child
A pointer to the child node.
Definition: Branch.h:51
te::sam::rtree::PartitionVars::init
void init()
Initializes partition vars.
Definition: PartitionVars.h:54
te::sam::rtree::PartitionVars::m_branchBuf
BRANCH m_branchBuf[MAXNODES+1]
Auxiliary branch buffer.
Definition: PartitionVars.h:50
te::sam::rtree::Index::setMBR
void setMBR(const te::gm::Envelope &mbr)
It sets the bounding box of all elements in the tree.
Definition: Index.h:337
te::sam::rtree::Index::m_size
std::size_t m_size
The size of R-Tree (number of nodes).
Definition: Index.h:257
te::sam::rtree::PartitionVars::m_partition
int m_partition[MAXNODES+1]
Auxiliary partition vector.
Definition: PartitionVars.h:45
te::sam::rtree::Index::loadNodes
void loadNodes(NodeType *n, NodeType *q, PartitionVarsType &p) const
Definition: Index.h:861