/// <summary> /// Returns the closest node between currentBest and CurrentNode to point /// </summary> private KDTreeNode <T> getClosestToPoint(IDistanceCalculator <T> distanceCalculator, KDTreeNode <T> currentBest, KDTreeNode <T> currentNode, T[] point) { if (distanceCalculator.Compare(currentBest.Points, currentNode.Points, point) < 0) { return(currentBest); } return(currentNode); }
/// <summary> /// Recursively find leaf node to insert /// at each level comparing against the next dimension. /// </summary> private KDTreeNode <T> findNearestNeighbour(KDTreeNode <T> currentNode, T[] searchPoint, int depth, IDistanceCalculator <T> distanceCalculator) { var currentDimension = depth % dimensions; KDTreeNode <T> currentBest = null; var compareResult = searchPoint[currentDimension] .CompareTo(currentNode.Points[currentDimension]); //move toward search point until leaf is reached if (compareResult < 0) { if (currentNode.Left != null) { currentBest = findNearestNeighbour(currentNode.Left, searchPoint, depth + 1, distanceCalculator); } else { currentBest = currentNode; } //currentBest is greater than point to current node distance //or if right node sits on split plane //then also move left if (currentNode.Right != null && (distanceCalculator.Compare(currentNode.Points[currentDimension], searchPoint[currentDimension], searchPoint, currentBest.Points) < 0 || currentNode.Right.Points[currentDimension] .CompareTo(currentNode.Points[currentDimension]) == 0)) { var rightBest = findNearestNeighbour(currentNode.Right, searchPoint, depth + 1, distanceCalculator); currentBest = getClosestToPoint(distanceCalculator, currentBest, rightBest, searchPoint); } //now recurse up from leaf updating current Best currentBest = getClosestToPoint(distanceCalculator, currentBest, currentNode, searchPoint); } else if (compareResult >= 0) { if (currentNode.Right != null) { currentBest = findNearestNeighbour(currentNode.Right, searchPoint, depth + 1, distanceCalculator); } else { currentBest = currentNode; } //currentBest is greater than point to current node distance //or if search point lies on split plane //then also move left if (currentNode.Left != null && (distanceCalculator.Compare(currentNode.Points[currentDimension], searchPoint[currentDimension], searchPoint, currentBest.Points) < 0 || compareResult == 0)) { var leftBest = findNearestNeighbour(currentNode.Left, searchPoint, depth + 1, distanceCalculator); currentBest = getClosestToPoint(distanceCalculator, currentBest, leftBest, searchPoint); } //now recurse up from leaf updating current Best currentBest = getClosestToPoint(distanceCalculator, currentBest, currentNode, searchPoint); } return(currentBest); }