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 terralib/sam/kdtree/Index.h
22 
23  \brief A class that represents a two dimensional K-d Tree (2-d Tree).
24 */
25 
26 #ifndef __TERRALIB_SAM_KDTREE_INTERNAL_INDEX_H
27 #define __TERRALIB_SAM_KDTREE_INTERNAL_INDEX_H
28 
29 // TerraLib
30 #include "../../geometry/Envelope.h"
31 #include "Node.h"
32 
33 // STL
34 #include <cmath>
35 #include <limits>
36 #include <vector>
37 #include <utility>
38 
39 namespace te
40 {
41  namespace sam
42  {
43  namespace kdtree
44  {
45  /*!
46  \class Index
47 
48  \brief A class that represents a two dimensional K-d Tree (2-d Tree).
49 
50  \note This type of tree stores the data into nodes (not only in the leafs node).
51 
52  \note This tree may be built by two ways:
53  1) Inserting each element in the tree. In this case the tree can becomes unbalanced, but in practical
54  cases this is not the expected, and is the best way to construct the tree (faster way).
55  2) Passing a container with pairs (key/data-item) and using the method buildOptimized after
56  calling kdsort. The tree built this way is almost balanced but will be construct in time O(N log N).
57  Warning: In this case items with the same key will be stores in different nodes!
58 
59  \note This type of tree may be of special interest of EXTENT SEARCH QUERIES.
60 
61  \note If the node type is kd_node_data_single_tag than NodeData and NodeDataItem are the same types.
62  And if one entry with the same key already exist, so they will be overwrite.
63 
64  \note If the node type is kd_node_data_set_tag than NodeData mus have a method called push_back(NodeDataItem)
65  that permits to store elements with the same key in the node.
66  */
67  template<class KdTreeNode> class Index
68  {
69  public:
70 
71  //! Export key type.
72  typedef typename KdTreeNode::kdKey kdKey;
73 
74  //! Export data type.
75  typedef typename KdTreeNode::kdData kdData;
76 
77  //! Export data item type.
78  typedef typename KdTreeNode::kdDataItem kdDataItem;
79 
80  //! Export data type.
81  typedef typename KdTreeNode::kdDataTag kdDataTag;
82 
83  /*! \brief Constructor. */
84  Index(const te::gm::Envelope& mbr)
85  : m_root(0),
86  m_mbr(mbr),
87  m_size(0)
88  {
89  }
90 
91  /*! \brief Destructor. */
93  {
94  clear();
95  }
96 
97  /*! \brief It clears all tree nodes. */
98  void clear()
99  {
100  if(m_root)
101  {
102  erase(m_root);
103  m_root = 0;
104  m_size = 0;
105  }
106  }
107 
108  /*! \brief It returns the number of tree nodes. */
109  const std::size_t& size() const
110  {
111  return m_size;
112  }
113 
114  /*! \brief It returns true if the tree is empty and false otherwise. */
115  bool isEmpty() const
116  {
117  return m_root == 0;
118  }
119 
120  /*! \brief It sets the minimum bounding box of all elements in the tree. */
121  void setMBR(const te::gm::Envelope& mbr)
122  {
123  m_mbr = mbr;
124  }
125 
126  /*! \brief It gets the minimum bounding box of all elements in the tree. */
127  const te::gm::Envelope& getMBR() const
128  {
129  return m_mbr;
130  }
131 
132  /*! \brief It inserts the data with a given key in tree. */
133  inline void insert(const kdKey& key, const kdData& item);
134 
135  /*! \brief It inserts the data in the tree and and keeps it balanced: the kdsort algorithm must be called before. */
136  void buildOptimized(std::vector<std::pair<kdKey, kdData> >& dataSet)
137  {
138  const std::size_t last = dataSet.size() - 1;
139  m_root = buildOptimized(dataSet, 0, last);
140  }
141 
142  /*! \brief Range search query. */
143  void search(const te::gm::Envelope& e, std::vector<KdTreeNode*>& report) const
144  {
145  if(m_root)
146  search(e, m_root, 'x', report);
147  }
148 
149  private:
150 
151  /*! \brief It Erases a node from the tree and all nodes below it. */
152  void erase(KdTreeNode* node)
153  {
154  if(node->hasLeft())
155  erase(node->getLeft());
156 
157  if(node->hasRight())
158  erase(node->getRight());
159 
160  delete node;
161  }
162 
163  /*! \brief It inserts data for single nodes, i.e. nodes that stores only one element. */
164  void insertData(KdTreeNode*& node, const kdData& data, const kd_node_m_datasingle_tag&)
165  {
166  node->setData(data);
167  }
168 
169  // Not build!
170  /*! \brief It inserts data for set nodes, i.e., nodes that may stores many element. */
171  void insertData(KdTreeNode*& node, const kdData& data, const kd_node_m_dataset_tag&)
172  {
173  node->getData().push_back(data);
174  }
175 
176  /*! \brief Recursive range query. */
177  inline void search(const te::gm::Envelope& e, KdTreeNode* node, const char& level, std::vector<KdTreeNode*>& report) const;
178 
179  /*! \brief It builds the tree recursively. */
180  KdTreeNode* buildOptimized(std::vector<std::pair<kdKey, kdData> >& dataSet, const std::size_t& first, const std::size_t& last)
181  {
182  const std::size_t kth = (last - first + 1) / 2;
183 
184  KdTreeNode* newNode = new KdTreeNode(dataSet[first + kth].first);
185 
186  newNode->setData(dataSet[first + kth].second);
187 
188  ++m_size;
189 
190  if(first + kth > first)
191  newNode->setLeft(buildOptimized(dataSet, first, first + kth - 1));
192 
193  if(first + kth < last)
194  newNode->setRight(buildOptimized(dataSet, first + kth + 1, last));
195 
196  return newNode;
197  }
198 
199  /*!
200  \brief No copy constructor allowed.
201 
202  \param rhs The other index.
203  */
204  Index(const Index& rhs);
205 
206  /*!
207  \brief No assignment operator allowed.
208 
209  \param rhs The other index.
210 
211  \return A reference for this.
212  */
213  Index& operator=(const Index& rhs);
214 
215  private:
216 
217  KdTreeNode* m_root; //!< Pointer to the root node.
218  te::gm::Envelope m_mbr; //!< Minimum bounding box of all nodes.
219  std::size_t m_size; //!< The size of the K-d Tree (number of nodes).
220  };
221 
222  template<class KdTreeNode>
223  void Index<KdTreeNode>::insert(const kdKey& key, const kdData& item)
224  {
225  if(m_root == 0)
226  {
227  m_root = new KdTreeNode(key);
228  insertData(m_root, item, kdDataTag());
229  }
230  else
231  {
232  char level = 'x';
233 
234  bool left = false;
235 
236  KdTreeNode* x = m_root;
237  KdTreeNode* y = 0;
238 
239  while(x != 0)
240  {
241  y = x;
242 
243  if(level == 'x')
244  {
245  if(key.getX() > x->getKey().getX()) // if the key is greater than, inserts in the right subtree
246  {
247  x = x->getRight();
248  left = false;
249  }
250  else if(key.getX() < x->getKey().getX()) // if the key is smaller than, inserts in the left subtree
251  {
252  x = x->getLeft();
253  left = true;
254  }
255  else if(key.getY() == x->getKey().getY()) // if the key already exist, in the case of single node the data will be overwrite and in the case of set node they will push_back the item
256  {
257  insertData(x, item, kdDataTag());
258  return;
259  }
260  else // found the same axis partition, so go left
261  {
262  x = x->getLeft();
263  left = true;
264  }
265 
266  level = 'y';
267  }
268  else
269  {
270  if(key.getY() > x->getKey().getY())
271  {
272  x = x->getRight();
273  left = false;
274  }
275  else if(key.getY() < x->getKey().getY())
276  {
277  x = x->getLeft();
278  left = true;
279  }
280  else if(key.getX() == x->getKey().getX())
281  {
282  insertData(x, item, kdDataTag());
283  return;
284  }
285  else
286  {
287  x = x->getLeft();
288  left = true;
289  }
290 
291  level = 'x';
292  }
293  }
294 
295  KdTreeNode* newNode = new KdTreeNode(key);
296 
297  insertData(newNode, item, kdDataTag());
298 
299  if(left)
300  y->setLeft(newNode);
301  else
302  y->setRight(newNode);
303  }
304 
305  ++m_size;
306  }
307 
308  template<class KdTreeNode>
309  void Index<KdTreeNode>::search(const te::gm::Envelope& e, KdTreeNode* node, const char& level, std::vector<KdTreeNode*>& report) const
310  {
311  if((node->getKey().getX() >= e.m_llx) && (node->getKey().getX() <= e.m_urx) &&
312  (node->getKey().getY() >= e.m_lly) && (node->getKey().getY() <= e.m_ury))
313  {
314  report.push_back(node);
315  }
316 
317  if(level == 'x')
318  {
319  if(node->hasLeft())
320  if(node->getKey().getX() >= e.m_llx)
321  search(e, node->getLeft(), 'y', report);
322 
323  if(node->hasRight())
324  if(node->getKey().getX() <= e.m_urx)
325  search(e, node->getRight(), 'y', report);
326  }
327  else
328  {
329  if(node->hasLeft())
330  if(node->getKey().getY() >= e.m_lly)
331  search(e, node->getLeft(), 'x', report);
332 
333  if(node->hasRight())
334  if(node->getKey().getY() <= e.m_ury)
335  search(e, node->getRight(), 'x', report);
336  }
337  }
338 
339  template<typename T>
340  bool Intersects(const T& data, const te::gm::Envelope& e)
341  {
342  // point to the right of envelope
343  if (data.getX() > e.m_urx)
344  return false;
345 
346  // point to the left of envelope
347  if (e.m_llx > data.getX())
348  return false;
349 
350  // point is above envelope
351  if (data.getY() > e.m_ury)
352  return false;
353 
354  // point is below envelope
355  if (e.m_lly > data.getY())
356  return false;
357 
358  return true;
359  }
360 
361  /*!
362  \class AdaptativeIndex
363 
364  \brief A class that represents a two dimensional K-d Tree (2-d Tree) that store data-elements into the leafs.
365 
366  \note This type of tree stores the data only in the leaf nodes.
367 
368  \note The process of construction expect that the tree is almost balanced.
369 
370  \note This type of tree may be of special interest of NEAREST NEIGHBOR SEARCH QUERIES.
371 
372  \note After a extent search it will be necessary to do a refinement.
373  */
374  template<class KdTreeNode> class AdaptativeIndex
375  {
376  public:
377 
378  //! Export key type.
379  typedef typename KdTreeNode::kdKey kdKey;
380 
381  //! Export data type.
382  typedef typename KdTreeNode::kdData kdData;
383 
384  //! Export data item type.
385  typedef typename KdTreeNode::kdDataItem kdDataItem;
386 
387  //! Export node type.
388  typedef KdTreeNode kdNode;
389 
390  /*! \brief Constructor. */
391  AdaptativeIndex(const te::gm::Envelope& mbr, const std::size_t& bucketSize = 12)
392  : m_root(0),
393  m_mbr(mbr),
394  m_size(0),
395  m_bucketSize(bucketSize)
396  {
397  }
398 
399  /*! \brief Destructor. */
401  {
402  clear();
403  }
404 
405  /*! \brief It clears all tree nodes. */
406  void clear()
407  {
408  if(m_root)
409  {
410  erase(m_root);
411  m_root = 0;
412  m_size = 0;
413  }
414  }
415 
416  /*! \brief It returns the number of tree nodes. */
417  const std::size_t& size() const
418  {
419  return m_size;
420  }
421 
422  /*! \brief It returns true if the tree is empty and false otherwise. */
423  bool isEmpty() const
424  {
425  return m_root == 0;
426  }
427 
428  /*! \brief It sets the minimum bounding box of all elements in the tree. */
429  void setMBR(const te::gm::Envelope& mbr)
430  {
431  m_mbr = mbr;
432  }
433 
434  /*! \brief It gets the minimum bounding box of all elements in the tree. */
435  const te::gm::Envelope& getMBR() const
436  {
437  return m_mbr;
438  }
439 
440  /*! \brief It sets bucket size for leaf nodes. */
441  void setBucketSize(const std::size_t& size)
442  {
443  m_bucketSize = size;
444  }
445 
446  /*! \brief It gets bucket size for leaf nodes. */
447  const std::size_t& getBucketSize() const
448  {
449  return m_bucketSize;
450  }
451 
452  /*! \brief It inserts the data set into the tree. */
453  void build(std::vector<std::pair<kdKey, kdDataItem> >& dataSet)
454  {
455  m_root = build(dataSet, 0.0, m_mbr);
456  }
457 
458  /*!
459  \brief It searches the nearest data in nodes: you must pass an array of kdDataItem of size "k"
460  with coordinates values (X() and Y()) adjusted to td::numeric_limits<double>::max() (this dummy values will be replaced at processing time),
461  and if not all neighbors are found so sqrDists will contains td::numeric_limits<double>::max() in array index.
462  */
463  void nearestNeighborSearch(const kdKey& key, std::vector<kdDataItem>& report, std::vector<double>& sqrDists, const std::size_t& k) const
464  {
465  if(m_root)
466  {
467  sqrDists.clear();
468 
469  for(std::size_t i = 0; i < k; ++i)
470  sqrDists.push_back(std::numeric_limits<double>::max());
471 
472  te::gm::Envelope e(-std::numeric_limits<double>::max(), -std::numeric_limits<double>::max(),
473  +std::numeric_limits<double>::max(), +std::numeric_limits<double>::max());
474 
475  nearestNeighborSearch(m_root, key, report, sqrDists, e);
476  }
477  }
478 
479  /*! \brief Range search query. */
480  void search(const te::gm::Envelope& e, std::vector<KdTreeNode*>& report) const
481  {
482  if(m_root)
483  search(e, m_root, report);
484  }
485 
486  /*! \brief Range search query: the refinement is already done. */
487  inline void search(const te::gm::Envelope& e, std::vector<kdDataItem>& report) const;
488 
489  private:
490 
491  /*! \brief It Erases a node from the tree and all nodes below it. */
492  void erase(KdTreeNode* node)
493  {
494  if(node->hasLeft())
495  erase(node->getLeft());
496 
497  if(node->hasRight())
498  erase(node->getRight());
499 
500  delete node;
501  }
502 
503  /*! \brief It builds the tree recursivily. */
504  inline KdTreeNode* build(std::vector<std::pair<kdKey, kdDataItem> >& dataSet, double averageValue, const te::gm::Envelope& mbr);
505 
506  /*! \brief Recursive nearest neighbor search. */
507  inline void nearestNeighborSearch(KdTreeNode* node, const kdKey& key, std::vector<kdDataItem>& report, std::vector<double>& sqrDists, te::gm::Envelope& e) const;
508 
509  /*! \brief Recursive range query. */
510  inline void search(const te::gm::Envelope& e, KdTreeNode* node, std::vector<KdTreeNode*>& report) const;
511 
512  /*! \brief It updates the neighbor list. */
513  inline void update(KdTreeNode* node, const kdKey& key, std::vector<kdDataItem>& report, std::vector<double>& sqrDists, te::gm::Envelope& e) const;
514 
515  /*! \brief It returns the average value along the axis. */
516  double average(std::vector<std::pair<kdKey, kdDataItem> >& dataSet, const char& discriminator) const
517  {
518  const std::size_t size = dataSet.size();
519 
520  double medianValue = 0.0;
521 
522  if(discriminator == 'x')
523  {
524  for(unsigned int i = 0; i < size; ++i)
525  medianValue += dataSet[i].first.getX();
526 
527  return medianValue / size;
528  }
529  else
530  {
531  for(unsigned int i = 0; i < size; ++i)
532  medianValue += dataSet[i].first.getY();
533 
534  return medianValue / size;
535  }
536  }
537 
538  /*!
539  \brief No copy constructor allowed.
540 
541  \param rhs The other index.
542  */
544 
545  /*!
546  \brief No assignment operator allowed.
547 
548  \param rhs The other index.
549 
550  \return A reference for this.
551  */
553 
554  private:
555 
556  KdTreeNode* m_root; //!< Pointer to the root node.
557  te::gm::Envelope m_mbr; //!< Minimum bounding box of all nodes.
558  std::size_t m_size; //!< The size of the K-d Tree (number of nodes).
559  std::size_t m_bucketSize; //!< Bucket size (maximum number of elements in each node).
560  };
561 
562  template<class KdTreeNode>
563  void AdaptativeIndex<KdTreeNode>::search(const te::gm::Envelope& e, std::vector<kdDataItem>& report) const
564  {
565  std::vector<KdTreeNode*> reportNodes;
566 
567  search(e, reportNodes);
568 
569  std::size_t nNodes = reportNodes.size();
570 
571  for(std::size_t i = 0; i < nNodes; ++i)
572  {
573  std::size_t nElements = reportNodes[i]->getData().size();
574 
575  for(std::size_t j = 0; j < nElements; ++j)
576  {
577  if(Intersects((reportNodes[i])->getData()[j], e))
578  report.push_back((reportNodes[i])->getData()[j]);
579  }
580  }
581  }
582 
583  template<class KdTreeNode>
584  KdTreeNode* AdaptativeIndex<KdTreeNode>::build(std::vector<std::pair<kdKey, kdDataItem> >& dataSet, double averageValue, const te::gm::Envelope& mbr)
585  {
586  ++m_size;
587 
588  if(dataSet.size() <= m_bucketSize)
589  {
590  KdTreeNode* node = new KdTreeNode(averageValue);
591 
592  node->setDiscriminator('l');
593 
594  std::size_t size = dataSet.size();
595 
596  for(std::size_t i = 0; i < size; ++i)
597  node->getData().push_back(dataSet[i].second);
598 
599  return node;
600  }
601 
602  te::gm::Envelope newMbr1(mbr);
603  te::gm::Envelope newMbr2(mbr);
604 
605  char discriminator = 'x';
606 
607  std::vector<std::pair<kdKey, kdDataItem> > leftDataSet;
608  std::vector<std::pair<kdKey, kdDataItem> > rightDataSet;
609 
610  // Finds the largest dimension
611  if((mbr.m_urx - mbr.m_llx) > (mbr.m_ury - mbr.m_lly))
612  {
613  // Finds the median along "x" axis
614  averageValue = average(dataSet, 'x');
615 
616  // Adjust box for left and right branchs
617  newMbr1.m_urx = averageValue;
618  newMbr2.m_llx = averageValue;
619 
620  std::size_t size = dataSet.size();
621 
622  for(std::size_t i = 0; i < size; ++ i)
623  {
624  if(dataSet[i].first.getX() <= averageValue)
625  leftDataSet.push_back(dataSet[i]);
626  else
627  rightDataSet.push_back(dataSet[i]);
628  }
629  }
630  else
631  {
632  discriminator = 'y';
633 
634  // Finds the median along "y" axis
635  averageValue = average(dataSet, 'y');
636 
637  // Adjust box for left and right branchs
638  newMbr1.m_ury = averageValue;
639  newMbr2.m_lly = averageValue;
640 
641  std::size_t size = dataSet.size();
642 
643  for(std::size_t i = 0; i < size; ++ i)
644  {
645  if(dataSet[i].first.getY() <= averageValue)
646  leftDataSet.push_back(dataSet[i]);
647  else
648  rightDataSet.push_back(dataSet[i]);
649  }
650  }
651 
652  dataSet.clear();
653 
654  KdTreeNode* node = new KdTreeNode(averageValue);
655 
656  if(rightDataSet.size() == 0) // If all coordinates have the same coordinate values, the right vector will be empty so we need stop division to
657  {
658  node->setDiscriminator('l');
659 
660  std::size_t size = leftDataSet.size();
661 
662  for(std::size_t i = 0; i < size; ++i)
663  node->getData().push_back(leftDataSet[i].second);
664  }
665  else if(leftDataSet.size() == 0) // If all coordinates have the same coordinate values, the left vector is empty, so we need to stop
666  {
667  node->setDiscriminator('l');
668 
669  std::size_t size = rightDataSet.size();
670 
671  for(std::size_t i = 0; i < size; ++i)
672  node->getData().push_back(rightDataSet[i].second);
673  }
674  else
675  {
676  node->setDiscriminator(discriminator);
677  node->setLeft(build(leftDataSet, averageValue, newMbr1));
678  node->setRight(build(rightDataSet, averageValue, newMbr2));
679  }
680 
681  return node;
682  }
683 
684  template<class KdTreeNode>
685  void AdaptativeIndex<KdTreeNode>::nearestNeighborSearch(KdTreeNode* node, const kdKey& key, std::vector<kdDataItem>& report, std::vector<double>& sqrDists, te::gm::Envelope& e) const
686  {
687  if(node->getDiscriminator() == 'l')
688  {
689  update(node, key, report, sqrDists, e); // this is a leaf node -> update list of neighbours
690  }
691  else if(node->getDiscriminator() == 'x')
692  {
693  if(key.getX() <= node->getKey())
694  {
695  nearestNeighborSearch(node->getLeft(), key, report, sqrDists, e);
696 
697  if((e.m_llx < node->getKey()) && (node->getKey() < e.m_urx))
698  nearestNeighborSearch(node->getRight(), key, report, sqrDists, e);
699  }
700  else
701  {
702  nearestNeighborSearch(node->getRight(), key, report, sqrDists, e);
703 
704  if((e.m_llx < node->getKey()) &&(node->getKey() < e.m_urx))
705  nearestNeighborSearch(node->getLeft(), key, report, sqrDists, e);
706  }
707  }
708  else if(node->getDiscriminator() == 'y')
709  {
710  if(key.getY() <= node->getKey())
711  {
712  nearestNeighborSearch(node->getLeft(), key, report, sqrDists, e);
713 
714  if((e.m_lly < node->getKey()) &&(node->getKey() < e.m_ury))
715  nearestNeighborSearch(node->getRight(), key, report, sqrDists, e);
716  }
717  else
718  {
719  nearestNeighborSearch(node->getRight(), key, report, sqrDists, e);
720 
721  if((e.m_lly < node->getKey()) &&(node->getKey() < e.m_ury))
722  nearestNeighborSearch(node->getLeft(), key, report, sqrDists, e);
723  }
724  }
725  }
726 
727  template<class KdTreeNode>
728  void AdaptativeIndex<KdTreeNode>::search(const te::gm::Envelope& e, KdTreeNode* node, std::vector<KdTreeNode*>& report) const
729  {
730  if(node->getDiscriminator() == 'x')
731  {
732  if(node->hasLeft())
733  if(e.m_llx <= node->getKey())
734  search(e, node->getLeft(), report);
735 
736  if(node->hasRight())
737  if(e.m_urx >= node->getKey())
738  search(e, node->getRight(), report);
739  }
740  else if(node->getDiscriminator() == 'y')
741  {
742  if(node->hasLeft())
743  if(e.m_lly <= node->getKey())
744  search(e, node->getLeft(), report);
745 
746  if(node->hasRight())
747  if(e.m_ury >= node->getKey())
748  search(e, node->getRight(), report);
749  }
750  else
751  report.push_back(node);
752  }
753 
754  template<class KdTreeNode>
755  void AdaptativeIndex<KdTreeNode>::update(KdTreeNode* node, const kdKey& key, std::vector<kdDataItem>& report, std::vector<double>& sqrDists, te::gm::Envelope& e) const
756  {
757  const std::size_t size = node->getData().size();
758 
759  const std::size_t nNeighbors = report.size();
760 
761 // for each element in the node, we need to search for distances less than of some one of sqrDists
762  for(std::size_t i = 0; i < size; ++i)
763  {
764  double dx = (key.getX() - node->getData()[i].getX());
765  double dy = (key.getY() - node->getData()[i].getY());
766 
767  double dkp = (dx * dx) + (dy * dy); // square distance from the key point to the node
768 
769 // if the distance of "i-th" element is less than the maximum distance in the sqrDists
770  if(dkp < sqrDists[nNeighbors - 1])
771  {
772 // so the element must be reported
773 // and the srqDists vector must be rearranged
774  for(std::size_t j = 0; j < nNeighbors; ++j)
775  {
776  if(dkp < sqrDists[j]) // if the position is found
777  {
778 // move the elements to the right
779  for(std::size_t k = nNeighbors - 1; k > j; --k)
780  {
781  report[k] = report[k - 1];
782  sqrDists[k] = sqrDists[k - 1];
783  }
784 
785 // inserts the element in the report and update its distance
786  report[j] = node->getData()[i];
787 
788  sqrDists[j] = dkp;
789 
790  break;
791  }
792  }
793  }
794  }
795 
796  double maxDist = sqrDists[nNeighbors - 1];
797 
798  if(maxDist != std::numeric_limits<double>::max())
799  maxDist = sqrt(maxDist);
800 
801  e.m_llx = key.getX() - maxDist;
802  e.m_lly = key.getY() - maxDist;
803  e.m_urx = key.getX() + maxDist;
804  e.m_ury = key.getY() + maxDist;
805  }
806 
807  } // end namespace kdtree
808  } // end namespace sam
809 } // end namespace te
810 
811 #endif // __TERRALIB_SAM_KDTREE_INTERNAL_INDEX_H
te::gm::Envelope
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:52
te::sam::kdtree::AdaptativeIndex::kdKey
KdTreeNode::kdKey kdKey
Export key type.
Definition: Index.h:379
te
TerraLib.
Definition: AddressGeocodingOp.h:52
te::sam::kdtree::AdaptativeIndex::m_size
std::size_t m_size
The size of the K-d Tree (number of nodes).
Definition: Index.h:558
te::sam::kdtree::Index::insert
void insert(const kdKey &key, const kdData &item)
It inserts the data with a given key in tree.
Definition: Index.h:223
te::sam::kdtree::Index::clear
void clear()
It clears all tree nodes.
Definition: Index.h:98
te::sam::kdtree::AdaptativeIndex::kdNode
KdTreeNode kdNode
Export node type.
Definition: Index.h:388
te::sam::kdtree::Index::Index
Index(const Index &rhs)
No copy constructor allowed.
te::sam::kdtree::AdaptativeIndex::setBucketSize
void setBucketSize(const std::size_t &size)
It sets bucket size for leaf nodes.
Definition: Index.h:441
te::sam::kdtree::AdaptativeIndex::isEmpty
bool isEmpty() const
It returns true if the tree is empty and false otherwise.
Definition: Index.h:423
te::sam::kdtree::AdaptativeIndex::operator=
AdaptativeIndex & operator=(const AdaptativeIndex &rhs)
No assignment operator allowed.
te::sam::kdtree::AdaptativeIndex::clear
void clear()
It clears all tree nodes.
Definition: Index.h:406
te::sam::kdtree::Index::kdDataTag
KdTreeNode::kdDataTag kdDataTag
Export data type.
Definition: Index.h:81
te::sam::kdtree::AdaptativeIndex::~AdaptativeIndex
~AdaptativeIndex()
Destructor.
Definition: Index.h:400
te::sam::kdtree::Index::kdDataItem
KdTreeNode::kdDataItem kdDataItem
Export data item type.
Definition: Index.h:78
te::sam::kdtree::Index
A class that represents a two dimensional K-d Tree (2-d Tree).
Definition: Index.h:68
te::gm::Envelope::m_llx
double m_llx
Lower left corner x-coordinate.
Definition: Envelope.h:344
te::sam::kdtree::AdaptativeIndex::average
double average(std::vector< std::pair< kdKey, kdDataItem > > &dataSet, const char &discriminator) const
It returns the average value along the axis.
Definition: Index.h:516
te::sam::kdtree::AdaptativeIndex::AdaptativeIndex
AdaptativeIndex(const te::gm::Envelope &mbr, const std::size_t &bucketSize=12)
Constructor.
Definition: Index.h:391
te::sam::kdtree::Index::operator=
Index & operator=(const Index &rhs)
No assignment operator allowed.
te::sam::kdtree::Index::setMBR
void setMBR(const te::gm::Envelope &mbr)
It sets the minimum bounding box of all elements in the tree.
Definition: Index.h:121
te::sam::kdtree::AdaptativeIndex::getMBR
const te::gm::Envelope & getMBR() const
It gets the minimum bounding box of all elements in the tree.
Definition: Index.h:435
te::sam::kdtree::AdaptativeIndex::size
const std::size_t & size() const
It returns the number of tree nodes.
Definition: Index.h:417
Node.h
A class that represents an R-tree node.
te::sam::kdtree::kd_node_m_dataset_tag
Kd-Tree node type for nodes with multuple elements (used by template instantiation).
Definition: Node.h:39
te::gm::Envelope::m_urx
double m_urx
Upper right corner x-coordinate.
Definition: Envelope.h:346
te::sam::kdtree::AdaptativeIndex::setMBR
void setMBR(const te::gm::Envelope &mbr)
It sets the minimum bounding box of all elements in the tree.
Definition: Index.h:429
te::sam::kdtree::AdaptativeIndex::update
void update(KdTreeNode *node, const kdKey &key, std::vector< kdDataItem > &report, std::vector< double > &sqrDists, te::gm::Envelope &e) const
It updates the neighbor list.
Definition: Index.h:755
te::sam::kdtree::Index::m_mbr
te::gm::Envelope m_mbr
Minimum bounding box of all nodes.
Definition: Index.h:218
te::sam::kdtree::AdaptativeIndex::kdData
KdTreeNode::kdData kdData
Export data type.
Definition: Index.h:382
te::sam::kdtree::Index::buildOptimized
KdTreeNode * buildOptimized(std::vector< std::pair< kdKey, kdData > > &dataSet, const std::size_t &first, const std::size_t &last)
It builds the tree recursively.
Definition: Index.h:180
te::sam::kdtree::Index::erase
void erase(KdTreeNode *node)
It Erases a node from the tree and all nodes below it.
Definition: Index.h:152
te::sam::kdtree::Index::kdKey
KdTreeNode::kdKey kdKey
Export key type.
Definition: Index.h:72
te::sam::kdtree::Index::m_root
KdTreeNode * m_root
Pointer to the root node.
Definition: Index.h:217
te::sam::kdtree::AdaptativeIndex::search
void search(const te::gm::Envelope &e, std::vector< KdTreeNode * > &report) const
Range search query.
Definition: Index.h:480
te::sam::kdtree::Index::search
void search(const te::gm::Envelope &e, std::vector< KdTreeNode * > &report) const
Range search query.
Definition: Index.h:143
te::sam::kdtree::AdaptativeIndex
A class that represents a two dimensional K-d Tree (2-d Tree) that store data-elements into the leafs...
Definition: Index.h:375
te::sam::kdtree::AdaptativeIndex::m_mbr
te::gm::Envelope m_mbr
Minimum bounding box of all nodes.
Definition: Index.h:557
te::sam::kdtree::Index::Index
Index(const te::gm::Envelope &mbr)
Constructor.
Definition: Index.h:84
te::sam::kdtree::Index::getMBR
const te::gm::Envelope & getMBR() const
It gets the minimum bounding box of all elements in the tree.
Definition: Index.h:127
te::gm::Envelope::m_lly
double m_lly
Lower left corner y-coordinate.
Definition: Envelope.h:345
te::sam::kdtree::AdaptativeIndex::build
void build(std::vector< std::pair< kdKey, kdDataItem > > &dataSet)
It inserts the data set into the tree.
Definition: Index.h:453
te::sam::kdtree::AdaptativeIndex::m_bucketSize
std::size_t m_bucketSize
Bucket size (maximum number of elements in each node).
Definition: Index.h:559
te::sam::kdtree::Index::~Index
~Index()
Destructor.
Definition: Index.h:92
te::sam::kdtree::Index::insertData
void insertData(KdTreeNode *&node, const kdData &data, const kd_node_m_datasingle_tag &)
It inserts data for single nodes, i.e. nodes that stores only one element.
Definition: Index.h:164
te::sam::kdtree::Index::isEmpty
bool isEmpty() const
It returns true if the tree is empty and false otherwise.
Definition: Index.h:115
te::sam::kdtree::AdaptativeIndex::m_root
KdTreeNode * m_root
Pointer to the root node.
Definition: Index.h:556
te::sam::kdtree::kd_node_m_datasingle_tag
Kd-tree node type for nodes with single elements (used by template instantiation).
Definition: Node.h:36
te::sam::kdtree::Index::kdData
KdTreeNode::kdData kdData
Export data type.
Definition: Index.h:75
te::sam::kdtree::Index::search
void search(const te::gm::Envelope &e, KdTreeNode *node, const char &level, std::vector< KdTreeNode * > &report) const
Recursive range query.
Definition: Index.h:309
te::sam::kdtree::Index::m_size
std::size_t m_size
The size of the K-d Tree (number of nodes).
Definition: Index.h:219
te::sam::kdtree::AdaptativeIndex::AdaptativeIndex
AdaptativeIndex(const AdaptativeIndex &rhs)
No copy constructor allowed.
te::sam::kdtree::AdaptativeIndex::kdDataItem
KdTreeNode::kdDataItem kdDataItem
Export data item type.
Definition: Index.h:385
te::sam::kdtree::Index::buildOptimized
void buildOptimized(std::vector< std::pair< kdKey, kdData > > &dataSet)
It inserts the data in the tree and and keeps it balanced: the kdsort algorithm must be called before...
Definition: Index.h:136
te::sam::kdtree::AdaptativeIndex::erase
void erase(KdTreeNode *node)
It Erases a node from the tree and all nodes below it.
Definition: Index.h:492
te::sam::kdtree::Index::size
const std::size_t & size() const
It returns the number of tree nodes.
Definition: Index.h:109
te::sam::kdtree::Intersects
bool Intersects(const T &data, const te::gm::Envelope &e)
Definition: Index.h:340
te::gm::Envelope::m_ury
double m_ury
Upper right corner y-coordinate.
Definition: Envelope.h:347
te::sam::kdtree::Index::insertData
void insertData(KdTreeNode *&node, const kdData &data, const kd_node_m_dataset_tag &)
It inserts data for set nodes, i.e., nodes that may stores many element.
Definition: Index.h:171
te::sam::kdtree::AdaptativeIndex::nearestNeighborSearch
void nearestNeighborSearch(const kdKey &key, std::vector< kdDataItem > &report, std::vector< double > &sqrDists, const std::size_t &k) const
It searches the nearest data in nodes: you must pass an array of kdDataItem of size "k" with coordina...
Definition: Index.h:463
te::sam::kdtree::AdaptativeIndex::getBucketSize
const std::size_t & getBucketSize() const
It gets bucket size for leaf nodes.
Definition: Index.h:447