63 register float sum = 0.0f;
65 for (
register int x = 0; x < nDimension; x++)
67 const float v = pVector1[x] - pVector2[x];
74 static inline float CrossCorrelation(
const float *pVector1,
const float *pVector2,
int nDimension)
76 register float sum = 0.0f;
78 for (
register int x = 0; x < nDimension; x++)
79 sum += pVector1[x] * pVector2[x];
94 m_EnclosingBox.
pfLow = 0;
102 m_pNearestNeighborList = 0;
105 m_nMaximumLeavesToVisit = 0;
113 delete m_pNodeListBBF;
114 delete m_pNearestNeighborList_;
122 void CKdTree::Build(
float **ppfValues,
int nLow,
int nHigh,
int nBucketSize,
int nDimensions,
int nUserDataSize)
125 m_nBucketSize = nBucketSize;
126 m_nDimensions = nDimensions;
127 m_nUserDataSize = nUserDataSize;
128 m_nTotalVectorSize = m_nDimensions + m_nUserDataSize;
129 m_nLeaves = nHigh - nLow + 1;
135 m_pRoot = BuildRecursive(ppfValues, nLow, nHigh, &m_EnclosingBox, 0);
138 CKdTreeNode* CKdTree::BuildRecursive(
float **ppfValues,
int nLow,
int nHigh,
KdBoundingBox* pCurrentBoundingBox,
int nCurrentDepth)
143 if ((nHigh-nLow) <= (m_nBucketSize - 1))
151 const int nSize = nHigh - nLow + 1;
153 pNewNode->
m_pValues =
new float[nSize * m_nTotalVectorSize];
158 for (
int n = 0 ; n < nSize; n++)
160 for (
int d = 0; d < m_nTotalVectorSize; d++)
161 pValues[d] = ppfValues[nLow + n][d];
163 pValues += m_nTotalVectorSize;
178 const int nDimension = nCurrentDepth % m_nDimensions;
184 const int nMedianIndex = (nHigh - nLow) / 2 + nLow;
185 const float fMedianValue = ppfValues[nMedianIndex][nDimension];
188 const float fHigh = pCurrentBoundingBox->
pfHigh[nDimension];
189 const float fLow = pCurrentBoundingBox->
pfLow[nDimension];
196 pCurrentBoundingBox->
pfHigh[nDimension] = fMedianValue;
199 CKdTreeNode* pNodeLeft = BuildRecursive(ppfValues, nLow, nMedianIndex, pCurrentBoundingBox, nCurrentDepth + 1);
202 pCurrentBoundingBox->
pfHigh[nDimension] = fHigh;
203 pCurrentBoundingBox->
pfLow[nDimension] = fMedianValue;
206 CKdTreeNode* pNodeRight = BuildRecursive(ppfValues, nMedianIndex+1, nHigh, pCurrentBoundingBox, nCurrentDepth + 1);
209 pCurrentBoundingBox->
pfLow[nDimension] = fLow;
231 void CKdTree::Dispose()
234 DisposeRecursive(m_pRoot);
236 if (m_EnclosingBox.
pfLow)
237 delete [] m_EnclosingBox.
pfLow;
239 if (m_EnclosingBox.
pfHigh)
240 delete [] m_EnclosingBox.
pfHigh;
263 m_pNearestNeighborList = 0;
265 m_nMaximumLeavesToVisit = nMaximumLeavesToVisit <= 0 ? m_nLeaves : nMaximumLeavesToVisit;
266 m_fCurrentMinDistance = FLT_MAX;
269 NearestNeighborRecursive(m_pRoot, pQuery);
272 fError = m_fCurrentMinDistance;
273 pfNN = m_pNearestNeighbor;
279 m_pNearestNeighborList = 0;
282 m_nMaximumLeavesToVisit = nMaximumLeavesToVisit <= 0 ? m_nLeaves : nMaximumLeavesToVisit;
283 m_fCurrentMinDistance = FLT_MAX;
286 m_pNodeListBBF->
Empty();
290 NearestNeighborRecursiveBBF(m_pRoot, pQuery, fDistanceBB);
293 fError = m_fCurrentMinDistance;
294 pfNN = m_pNearestNeighbor;
300 m_pNearestNeighborList = m_pNearestNeighborList_;
301 m_pNearestNeighborList->
Empty();
304 m_nMaximumLeavesToVisit = nMaximumLeavesToVisit <= 0 ? m_nLeaves : nMaximumLeavesToVisit;
305 m_fCurrentMinDistance = FLT_MAX;
308 NearestNeighborRecursive(m_pRoot, pQuery);
311 fError = m_fCurrentMinDistance;
312 pNNList = m_pNearestNeighborList;
318 m_pNearestNeighborList = m_pNearestNeighborList_;
319 m_pNearestNeighborList->
Empty();
322 m_nMaximumLeavesToVisit = nMaximumLeavesToVisit <= 0 ? m_nLeaves : nMaximumLeavesToVisit;
323 m_fCurrentMinDistance = FLT_MAX;
326 m_pNodeListBBF->
Empty();
330 NearestNeighborRecursiveBBF(m_pRoot, pQuery, fDistanceBB);
333 fError = m_fCurrentMinDistance;
334 pNNList = m_pNearestNeighborList;
338 void CKdTree::NearestNeighborRecursive(
CKdTreeNode *pNode,
const float *pQuery)
341 if (m_nMaximumLeavesToVisit == 0)
348 const int nSize = pNode->
m_nSize;
350 for (
int i = 0 ; i < nSize; i++)
355 if (fDistance < m_fCurrentMinDistance)
357 m_pNearestNeighbor = pValues;
358 m_fCurrentMinDistance = fDistance;
361 if (m_pNearestNeighborList)
362 m_pNearestNeighborList->
Push(m_fCurrentMinDistance, pValues);
366 m_nMaximumLeavesToVisit--;
374 const bool bFromLeft = fCutDifference < 0.0f;
379 if (m_fCurrentMinDistance >= fCutDifference * fCutDifference)
386 void CKdTree::NearestNeighborRecursiveBBF(
CKdTreeNode* pNode,
const float *pQuery,
float fDistanceBB)
389 if (m_nMaximumLeavesToVisit == 0)
396 const int nSize = pNode->
m_nSize;
398 for (
int i = 0; i < nSize; i++)
402 if (fDistance < m_fCurrentMinDistance)
404 m_pNearestNeighbor = pValues;
405 m_fCurrentMinDistance = fDistance;
408 if (m_pNearestNeighborList)
409 m_pNearestNeighborList->
Push(m_fCurrentMinDistance, pValues);
412 pValues += m_nTotalVectorSize;
415 m_nMaximumLeavesToVisit--;
425 const float fCutDifference = pQuery[nDimension] - pNode->
m_fMedianValue;
427 if (fCutDifference < 0.0f)
430 float fBoxDifference = pNode->
m_Bounding.
fLow - pQuery[nDimension];
433 if (fBoxDifference < 0.0f)
434 fBoxDifference = 0.0f;
439 const float fChildDistanceBB = fDistanceBB - fBoxDifference * fBoxDifference + fCutDifference * fCutDifference;
445 NearestNeighborRecursiveBBF(pNode->
m_pLeftChild, pQuery, fDistanceBB);
453 if (fBoxDifference < 0.0f)
454 fBoxDifference = 0.0f;
459 const float fChildDistanceBB = fDistanceBB - fBoxDifference * fBoxDifference + fCutDifference * fCutDifference;
465 NearestNeighborRecursiveBBF(pNode->
m_pRightChild, pQuery, fDistanceBB);
470 float fChildDistanceBB;
471 m_pNodeListBBF->
Pop(fChildDistanceBB, (
void *&) pNode);
475 if (m_fCurrentMinDistance >= fChildDistanceBB)
476 NearestNeighborRecursiveBBF(pNode, pQuery, fChildDistanceBB);
CKdTree(int nMaximumNumberOfNodes=10000)
void Pop(float &fValue, void *&pMeta)
void NearestNeighbor(const float *pQuery, float &fError, float *&pfNN, int nMaximumLeavesToVisit=-1)
void NearestNeighborBBF(const float *pfQuery, float &fError, float *&pfNN, int nMaximumLeavesToVisit=-1)
CKdTreeNode * m_pRightChild
float GetDistanceFromBox(KdBoundingBox BoundingBox, const float *pValues, int nDimension)
void Build(float **ppfValues, int nLow, int nHigh, int nBucketSize, int nDimensions, int nUserDataSize)
static float CrossCorrelation(const float *pVector1, const float *pVector2, int nDimension)
CKdTreeNode * m_pLeftChild
void Push(float fValue, void *pMeta)
void QuicksortByElementOfVector(float **ppValues, int nLow, int nHigh, int nSortByDimension)
KdBoundingBox CalculateEnclosingBoundingBox(float **ppValues, int nDimension, int nSize)
static float SquaredEuclideanDistance(const float *pVector1, const float *pVector2, int nDimension)