1 #ifndef TIL_KDTREE_TPP_
2 #define TIL_KDTREE_TPP_
7 //----------------------------------------------------------------------------------
13 template < typename TKDTree >
14 void KDTreeFactory<TKDTree>::build(TKDTree & res)
16 // Create a vector containing the indices of the collection elements
17 makeIndexVector(m_v, m_vIndex);
19 // Set kdtree as a global variable inside the class
22 // Start kdtree building iterations
23 typename std::vector<index_type>::iterator left = m_vIndex.begin();
24 typename std::vector<index_type>::iterator right = m_vIndex.end()-1;
25 genKDIter(left, right, m_pKdt->addChild(0, 0u), 0);
29 template < typename TKDTree >
30 void KDTreeFactory<TKDTree>::genKDIter
32 typename std::vector<index_type>::iterator left,
33 typename std::vector<index_type>::iterator right,
34 typename TKDTree::iterator iRes,
38 // We want the median to have a mean index.
39 typename std::vector<index_type>::iterator median = left+(right-left)/2;
42 // NB: The right+1 is because STL algorithms expect to have an element out
43 // of range as the "end" element.
45 std::nth_element(left, median, right+1, m_compare);
46 iRes->value() = *median;
49 // Iterate right and left, if range permits it
52 genKDIter(left, median-1, m_pKdt->addChild(iRes, TKDTree::LEFT), (dim+1)%3);
56 genKDIter(median+1, right, m_pKdt->addChild(iRes, TKDTree::RIGHT), (dim+1)%3);
60 template < typename TKDTree >
61 void KDTreeFactory<TKDTree>::makeIndexVector(const Collection & v, std::vector<index_type> & vIndex)
63 vIndex.resize(size(v));
64 typename std::vector<indexed_type>::const_iterator iV = v.begin();
65 typename std::vector<index_type>::iterator iVIndex = vIndex.begin();
66 for (; iV != v.end(); ++iV, ++iVIndex)
68 getIndex(iV, *iVIndex);
69 //*iVIndex = til::getIndex<index_type>(v, iV);
74 //----------------------------------------------------------------------------------
81 template < typename TPrecision, typename TKDTree >
82 typename Find_closest<TPrecision,TKDTree>::index_type
83 Find_closest<TPrecision,TKDTree>::operator()(const indexed_type & vec)
87 lookMax(m_pKdt->root());
91 template < typename TPrecision, typename TKDTree >
92 void Find_closest<TPrecision,TKDTree>::init()
94 m_min = std::numeric_limits<TPrecision>::max();
99 template < typename TPrecision, typename TKDTree >
100 void Find_closest<TPrecision,TKDTree>::lookMax(typename TKDTree::const_iterator iNode)
103 // Stop here if we reached end of tree
104 // TODO: this test might be put below, to avoid an extra function call
105 // everytime we reach an end point.
106 if (iNode == 0) return;
107 index_type node = *iNode;
108 //NB: this was used when node is a pointer. Dunno if its removal changes something. hope not.
109 //if (node == 0) return;
111 // Compute the distance to the current node point
112 TPrecision dist2point = dist2(m_pKdt->get(node), m_vec, prec<TPrecision>());
113 //std::cout << dist2point << "*" << std::flush;
114 if (dist2point < m_min)
120 // Continue looking downwards, starting from the lower half or the higher
121 // half, depending on which the vector belongs to.
122 TPrecision diffWall = m_vec[iNode->dim()] - m_pKdt->get(node)[iNode->dim()];
126 // Point belong to lower half: process this half first
127 lookMax(iNode.child(TKDTree::LEFT));
128 // We process the other half only if the min distance found so far
129 // is larger than the distance to the halfplane border
130 if (m_min > square(diffWall))
132 lookMax(iNode.child(TKDTree::RIGHT));
137 // Point belong to higher half: process this half first
138 lookMax(iNode.child(TKDTree::RIGHT));
139 // We process the other half only if the min distance found so far
140 // is larger than the distance to the halfplane border
141 if (m_min > square(diffWall))
143 lookMax(iNode.child(TKDTree::LEFT));
151 #endif /*KDTREE_TPP_*/