26 #ifndef __TERRALIB_SAM_KDTREE_INTERNAL_INDEX_H
27 #define __TERRALIB_SAM_KDTREE_INTERNAL_INDEX_H
30 #include "../../geometry/Envelope.h"
31 #include "../../geometry/Utils.h"
67 template<
class KdTreeNode>
class Index
72 typedef typename KdTreeNode::kdKey
kdKey;
75 typedef typename KdTreeNode::kdData
kdData;
109 const std::size_t&
size()
const
133 inline void insert(
const kdKey& key,
const kdDataItem& item);
138 const std::size_t last = dataSet.size() - 1;
155 erase(node->getLeft());
158 erase(node->getRight());
177 inline void search(
const te::gm::Envelope& e, KdTreeNode* node,
const char& level, std::vector<KdTreeNode*>& report)
const;
180 KdTreeNode*
buildOptimized(std::vector<std::pair<kdKey, kdDataItem> >& dataSet,
const std::size_t& first,
const std::size_t& last)
182 const std::size_t kth = (last - first + 1) / 2;
184 KdTreeNode* newNode =
new KdTreeNode(dataSet[first + kth].first);
186 newNode->setData(dataSet[first + kth].second);
190 if(first + kth > first)
191 newNode->setLeft(
buildOptimized(dataSet, first, first + kth - 1));
193 if(first + kth < last)
194 newNode->setRight(
buildOptimized(dataSet, first + kth + 1, last));
222 template<
class KdTreeNode>
227 m_root =
new KdTreeNode(key);
236 KdTreeNode* x = m_root;
245 if(key.getX() > x->getKey().getX())
250 else if(key.getX() < x->getKey().getX())
255 else if(key.getY() == x->getKey().getY())
270 if(key.getY() > x->getKey().getY())
275 else if(key.getY() < x->getKey().getY())
280 else if(key.getX() == x->getKey().getX())
295 KdTreeNode* newNode =
new KdTreeNode(key);
302 y->setRight(newNode);
308 template<
class KdTreeNode>
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))
314 report.push_back(node);
320 if(node->getKey().getX() >= e.
m_llx)
321 search(e, node->getLeft(),
'y', report);
324 if(node->getKey().getX() <= e.
m_urx)
325 search(e, node->getRight(),
'y', report);
330 if(node->getKey().getY() >= e.
m_lly)
331 search(e, node->getLeft(),
'x', report);
334 if(node->getKey().getY() <= e.
m_ury)
335 search(e, node->getRight(),
'x', report);
357 typedef typename KdTreeNode::kdKey
kdKey;
360 typedef typename KdTreeNode::kdData
kdData;
395 const std::size_t&
size()
const
431 void build(std::vector<std::pair<kdKey, kdDataItem> >& dataSet)
441 void nearestNeighborSearch(
const kdKey& key, std::vector<kdDataItem>& report, std::vector<double>& sqrDists,
const std::size_t& k)
const
447 for(std::size_t i = 0; i < k; ++i)
448 sqrDists.push_back(std::numeric_limits<double>::max());
450 te::gm::Envelope e(-std::numeric_limits<double>::max(), -std::numeric_limits<double>::max(),
451 +std::numeric_limits<double>::max(), +std::numeric_limits<double>::max());
473 erase(node->getLeft());
476 erase(node->getRight());
482 inline KdTreeNode*
build(std::vector<std::pair<kdKey, kdDataItem> >& dataSet,
double averageValue,
const te::gm::Envelope& mbr);
491 inline void update(KdTreeNode* node,
const kdKey& key, std::vector<kdDataItem>& report, std::vector<double>& sqrDists,
te::gm::Envelope& e)
const;
494 double average(std::vector<std::pair<kdKey, kdDataItem> >& dataSet,
const char& discriminator)
const
496 const std::size_t
size = dataSet.size();
498 double medianValue = 0.0;
500 if(discriminator ==
'x')
502 for(
unsigned int i = 0; i <
size; ++i)
503 medianValue += dataSet[i].first.getX();
505 return medianValue /
size;
509 for(
unsigned int i = 0; i <
size; ++i)
510 medianValue += dataSet[i].first.getY();
512 return medianValue /
size;
540 template<
class KdTreeNode>
543 std::vector<KdTreeNode*> reportNodes;
545 search(e, reportNodes);
547 std::size_t nNodes = reportNodes.size();
549 for(std::size_t i = 0; i < nNodes; ++i)
551 std::size_t nElements = reportNodes[i]->getData().size();
553 for(std::size_t j = 0; j < nElements; ++j)
556 report.push_back((reportNodes[i])->getData()[j]);
561 template<
class KdTreeNode>
566 if(dataSet.size() <= m_bucketSize)
568 KdTreeNode* node =
new KdTreeNode(averageValue);
570 node->setDiscriminator(
'l');
572 std::size_t size = dataSet.size();
574 for(std::size_t i = 0; i < size; ++i)
575 node->getData().push_back(dataSet[i].second);
583 char discriminator =
'x';
585 std::vector<std::pair<kdKey, kdDataItem> > leftDataSet;
586 std::vector<std::pair<kdKey, kdDataItem> > rightDataSet;
592 averageValue = average(dataSet,
'x');
595 newMbr1.
m_urx = averageValue;
596 newMbr2.
m_llx = averageValue;
598 std::size_t size = dataSet.size();
600 for(std::size_t i = 0; i < size; ++ i)
602 if(dataSet[i].first.getX() <= averageValue)
603 leftDataSet.push_back(dataSet[i]);
605 rightDataSet.push_back(dataSet[i]);
613 averageValue = average(dataSet,
'y');
616 newMbr1.
m_ury = averageValue;
617 newMbr2.
m_lly = averageValue;
619 std::size_t size = dataSet.size();
621 for(std::size_t i = 0; i < size; ++ i)
623 if(dataSet[i].first.getY() <= averageValue)
624 leftDataSet.push_back(dataSet[i]);
626 rightDataSet.push_back(dataSet[i]);
632 KdTreeNode* node =
new KdTreeNode(averageValue);
634 if(rightDataSet.size() == 0)
636 node->setDiscriminator(
'l');
638 std::size_t size = leftDataSet.size();
640 for(std::size_t i = 0; i < size; ++i)
641 node->getData().push_back(leftDataSet[i].second);
643 else if(leftDataSet.size() == 0)
645 node->setDiscriminator(
'l');
647 std::size_t size = rightDataSet.size();
649 for(std::size_t i = 0; i < size; ++i)
650 node->getData().push_back(rightDataSet[i].second);
654 node->setDiscriminator(discriminator);
655 node->setLeft(build(leftDataSet, averageValue, newMbr1));
656 node->setRight(build(rightDataSet, averageValue, newMbr2));
662 template<
class KdTreeNode>
665 if(node->getDiscriminator() ==
'l')
667 update(node, key, report, sqrDists, e);
669 else if(node->getDiscriminator() ==
'x')
671 if(key.getX() <= node->getKey())
673 nearestNeighborSearch(node->getLeft(), key, report, sqrDists, e);
675 if((e.
m_llx < node->getKey()) && (node->getKey() < e.
m_urx))
676 nearestNeighborSearch(node->getRight(), key, report, sqrDists, e);
680 nearestNeighborSearch(node->getRight(), key, report, sqrDists, e);
682 if((e.
m_llx < node->getKey()) &&(node->getKey() < e.
m_urx))
683 nearestNeighborSearch(node->getLeft(), key, report, sqrDists, e);
686 else if(node->getDiscriminator() ==
'y')
688 if(key.getY() <= node->getKey())
690 nearestNeighborSearch(node->getLeft(), key, report, sqrDists, e);
692 if((e.
m_lly < node->getKey()) &&(node->getKey() < e.
m_ury))
693 nearestNeighborSearch(node->getRight(), key, report, sqrDists, e);
697 nearestNeighborSearch(node->getRight(), key, report, sqrDists, e);
699 if((e.
m_lly < node->getKey()) &&(node->getKey() < e.
m_ury))
700 nearestNeighborSearch(node->getLeft(), key, report, sqrDists, e);
705 template<
class KdTreeNode>
708 if(node->getDiscriminator() ==
'x')
711 if(e.
m_llx <= node->getKey())
712 search(e, node->getLeft(), report);
715 if(e.
m_urx >= node->getKey())
716 search(e, node->getRight(), report);
718 else if(node->getDiscriminator() ==
'y')
721 if(e.
m_lly <= node->getKey())
722 search(e, node->getLeft(), report);
725 if(e.
m_ury >= node->getKey())
726 search(e, node->getRight(), report);
729 report.push_back(node);
732 template<
class KdTreeNode>
735 const std::size_t size = node->getData().size();
737 const std::size_t nNeighbors = report.size();
740 for(std::size_t i = 0; i < size; ++i)
742 double dx = (key.getX() - node->getData()[i].getX());
743 double dy = (key.getY() - node->getData()[i].getY());
745 double dkp = (dx * dx) + (dy * dy);
748 if(dkp < sqrDists[nNeighbors - 1])
752 for(std::size_t j = 0; j < nNeighbors; ++j)
754 if(dkp < sqrDists[j])
757 for(std::size_t k = nNeighbors - 1; k > j; --k)
759 report[k] = report[k - 1];
760 sqrDists[k] = sqrDists[k - 1];
764 report[j] = node->getData()[i];
774 double maxDist = sqrDists[nNeighbors - 1];
776 if(maxDist != std::numeric_limits<double>::max())
777 maxDist = sqrt(maxDist);
779 e.
m_llx = key.getX() - maxDist;
780 e.
m_lly = key.getY() - maxDist;
781 e.
m_urx = key.getX() + maxDist;
782 e.
m_ury = key.getY() + maxDist;
789 #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.
void clear()
It clears all tree nodes.
void setMBR(const te::gm::Envelope &mbr)
It sets the minimum bounding box of all elements in the tree.
const te::gm::Envelope & getMBR() const
It gets the minimum bounding box of all elements in the tree.
KdTreeNode::kdDataTag kdDataTag
Export data type.
A class that represents an Kd-tree node.
std::size_t m_bucketSize
Bucket size (maximum number of elements in each node).
void search(const te::gm::Envelope &e, std::vector< KdTreeNode * > &report) const
Range search query.
void erase(KdTreeNode *node)
It Erases a node from the tree and all nodes below it.
KdTreeNode::kdKey kdKey
Export key type.
A class that represents a two dimensional K-d Tree (2-d Tree) that store data-elements into the leafs...
te::gm::Envelope m_mbr
Minimum bounding box of all nodes.
double m_urx
Upper right corner x-coordinate.
KdTreeNode kdNode
Export node type.
KdTreeNode::kdData kdData
Export data type.
const std::size_t & size() const
It returns the number of tree nodes.
bool isEmpty() const
It returns true if the tree is empty and false otherwise.
double average(std::vector< std::pair< kdKey, kdDataItem > > &dataSet, const char &discriminator) const
It returns the average value along the axis.
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.
KdTreeNode * m_root
Pointer to the root node.
KdTreeNode::kdData kdData
Export data type.
std::size_t m_size
The size of the K-d Tree (number of nodes).
void setBucketSize(const std::size_t &size)
It sets bucket size for leaf nodes.
double m_llx
Lower left corner x-coordinate.
An Envelope defines a 2D rectangular region.
const std::size_t & size() const
It returns the number of tree nodes.
void build(std::vector< std::pair< kdKey, kdDataItem > > &dataSet)
It inserts the data set into the tree.
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...
const te::gm::Envelope & getMBR() const
It gets the minimum bounding box of all elements in the tree.
AdaptativeIndex(const te::gm::Envelope &mbr, const std::size_t &bucketSize=12)
Constructor.
te::gm::Envelope m_mbr
Minimum bounding box of all nodes.
const std::size_t & getBucketSize() const
It gets bucket size for leaf nodes.
A class that represents a two dimensional K-d Tree (2-d Tree).
bool Intersects(const T1 &o1, const T2 &o2)
double m_lly
Lower left corner y-coordinate.
KdTreeNode::kdDataItem kdDataItem
Export data item type.
KdTreeNode * m_root
Pointer to the root node.
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.
Kd-tree node type for nodes with single elements (used by template instantiation).
AdaptativeIndex & operator=(const AdaptativeIndex &rhs)
No assignment operator allowed.
double m_ury
Upper right corner y-coordinate.
void clear()
It clears all tree nodes.
KdTreeNode::kdDataItem kdDataItem
Export data item type.
std::size_t m_size
The size of the K-d Tree (number of nodes).
void setMBR(const te::gm::Envelope &mbr)
It sets the minimum bounding box of all elements in the tree.
Index(const te::gm::Envelope &mbr)
Constructor.
bool isEmpty() const
It returns true if the tree is empty and false otherwise.
void search(const te::gm::Envelope &e, std::vector< KdTreeNode * > &report) const
Range search query.
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...
Index & operator=(const Index &rhs)
No assignment operator allowed.
~AdaptativeIndex()
Destructor.
KdTreeNode * buildOptimized(std::vector< std::pair< kdKey, kdDataItem > > &dataSet, const std::size_t &first, const std::size_t &last)
It builds the tree recursively.
void erase(KdTreeNode *node)
It Erases a node from the tree and all nodes below it.
KdTreeNode::kdKey kdKey
Export key type.