private void DescendPath(KDNode_Rednaxela <T> pCursor) { KDNode_Rednaxela <T> pNotTaken; // If the seach point is larger, select the right path. if (tSearchPoint[pCursor.splitDimension] > pCursor.fSplitValue) { pNotTaken = pCursor.pLeft; pCursor = pCursor.pRight; } else { pNotTaken = pCursor.pRight; pCursor = pCursor.pLeft; } // Calculate the shortest distance between the search point and the min and max bounds of the kd-node. double fDistance = kDistanceFunction.DistanceToRectangle(tSearchPoint, pNotTaken.minBound, pNotTaken.maxBound); //// If it is greater than the threshold, skip. //if (fThreshold >= 0 && fDistance > fThreshold) //{ // //pPending.Insert(fDistance, pNotTaken); // continue; //} // Only add the path we need more points or the node is closer than furthest point on list so far. if (pEvaluated.Size < iPointsRemaining || fDistance <= pEvaluated.MaxKey) { pPending.Insert(fDistance, pNotTaken); } }
/// <summary> /// Check for the next iterator item. /// </summary> /// <returns>True if we have one, false if not.</returns> public bool MoveNext() { // Bail if we are finished. if (iPointsRemaining == 0) { _Current = default(T); return(false); } // While we still have paths to evaluate. while (pPending.Size > 0 && (pEvaluated.Size == 0 || (pPending.MinKey < pEvaluated.MinKey))) { // If there are pending paths possibly closer than the nearest evaluated point, check it out KDNode <T> pCursor = pPending.Min; pPending.RemoveMin(); // Descend the tree, recording paths not taken while (!pCursor.IsLeaf) { KDNode <T> pNotTaken; // If the seach point is larger, select the right path. if (tSearchPoint[pCursor.iSplitDimension] > pCursor.fSplitValue) { pNotTaken = pCursor.pLeft; pCursor = pCursor.pRight; } else { pNotTaken = pCursor.pRight; pCursor = pCursor.pLeft; } // Calculate the shortest distance between the search point and the min and max bounds of the kd-node. float fDistance = kDistanceFunction.DistanceToRectangle(tSearchPoint, pNotTaken.tMinBound, pNotTaken.tMaxBound); // If it is greater than the threshold, skip. if (fThreshold >= 0 && fDistance > fThreshold) { //pPending.Insert(fDistance, pNotTaken); continue; } // Only add the path we need more points or the node is closer than furthest point on list so far. if (pEvaluated.Size < iPointsRemaining || fDistance <= pEvaluated.MaxKey) { pPending.Insert(fDistance, pNotTaken); } } // If all the points in this KD node are in one place. if (pCursor.bSinglePoint) { // Work out the distance between this point and the search point. float fDistance = kDistanceFunction.Distance(pCursor.tPoints[0], tSearchPoint); // Skip if the point exceeds the threshold. // Technically this should never happen, but be prescise. if (fThreshold >= 0 && fDistance >= fThreshold) { continue; } // Add the point if either need more points or it's closer than furthest on list so far. if (pEvaluated.Size < iPointsRemaining || fDistance <= pEvaluated.MaxKey) { for (int i = 0; i < pCursor.Size; ++i) { // If we don't need any more, replace max if (pEvaluated.Size == iPointsRemaining) { pEvaluated.ReplaceMax(fDistance, pCursor.tData[i]); } // Otherwise insert. else { pEvaluated.Insert(fDistance, pCursor.tData[i]); } } } } // If the points in the KD node are spread out. else { // Treat the distance of each point seperately. for (int i = 0; i < pCursor.Size; ++i) { // Compute the distance between the points. float fDistance = kDistanceFunction.Distance(pCursor.tPoints[i], tSearchPoint); // Skip if it exceeds the threshold. if (fThreshold >= 0 && fDistance >= fThreshold) { continue; } // Insert the point if we have more to take. if (pEvaluated.Size < iPointsRemaining) { pEvaluated.Insert(fDistance, pCursor.tData[i]); } // Otherwise replace the max. else if (fDistance < pEvaluated.MaxKey) { pEvaluated.ReplaceMax(fDistance, pCursor.tData[i]); } } } } // Select the point with the smallest distance. if (pEvaluated.Size == 0) { return(false); } iPointsRemaining--; _CurrentDistance = pEvaluated.MinKey; _Current = pEvaluated.Min; pEvaluated.RemoveMin(); return(true); }