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