/// <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(LabelType); return(false); } // While we still have paths to evaluate. while (pPending.Size > 0 && (pEvaluated.Size == 0 || (pPending.MinKey.CompareTo(pEvaluated.MinKey) == -1))) { // If there are pending paths possibly closer than the nearest evaluated point, check it out KDNode <DomainType, DistanceType, LabelType> pCursor = pPending.Min; pPending.RemoveMin(); // Descend the tree, recording paths not taken while (!pCursor.IsLeaf) { KDNode <DomainType, DistanceType, LabelType> pNotTaken; // If the seach point is larger, select the right path. if (search_point[pCursor.d_split_dimension].CompareTo(pCursor.d_split_value) == 1) { 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. DistanceType fDistance = distance_function.ComputeToRectangle(search_point, pNotTaken.tMinBound, pNotTaken.tMaxBound); // If it is greater than or equal to the threshold, skip. if (d_use_threshold && (fDistance.CompareTo(fThreshold) != -1)) { //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) if (pEvaluated.Size < iPointsRemaining || fDistance.CompareTo(pEvaluated.MaxKey) != 1) { 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. DistanceType fDistance = distance_function.Compute(pCursor.d_points[0], search_point); // If it is greater than or equal to the threshold, skip. if (d_use_threshold && (fDistance.CompareTo(fThreshold) != -1)) { continue; } // Add the point if either need more points or it's closer than furthest on list so far. if (pEvaluated.Size < iPointsRemaining || (fDistance.CompareTo(pEvaluated.MaxKey) != 1)) { 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.d_values[i]); } // Otherwise insert. else { pEvaluated.Insert(fDistance, pCursor.d_values[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. DistanceType fDistance = distance_function.Compute(pCursor.d_points[i], search_point); // If it is greater than or equal to the threshold, skip. if (d_use_threshold && (fDistance.CompareTo(fThreshold) != -1)) { continue; } // Insert the point if we have more to take. if (pEvaluated.Size < iPointsRemaining) { pEvaluated.Insert(fDistance, pCursor.d_values[i]); } // Otherwise replace the max. else if (fDistance.CompareTo(pEvaluated.MaxKey) == -1) { pEvaluated.ReplaceMax(fDistance, pCursor.d_values[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); }