/// <summary> /// Find the nearest N elements in the KD Tree to the specified element. /// </summary> /// <param name="_item">The item to search for</param> /// <param name="_count">The number of closest elements to return</param> /// <returns> /// An enumeration of the closest N elements to the item specified /// </returns> public IEnumerable <T> FindNearest(T _item, int _count) { if (ExploredNodes != null) { ExploredNodes.Clear(); } var closest = new ClosestObjects <T>(_count); FindNearest(_item, 0, 0, closest); return(closest.GetClosestObjects()); }
/// <summary> /// Find all items that are within a certain distance of an item /// </summary> /// <param name="_item">The item to find close other items for</param> /// <param name="_maxDistance">The maximum distance from _item to include</param> /// <returns> /// An enumeration of objects that are closer than _distance to _item /// </returns> public IEnumerable <T> FindClose(T _item, double _maxDistance) { if (ExploredNodes != null) { ExploredNodes.Clear(); } var closest = new ClosestObjects <T>(_maxDistance); FindNearest(_item, 0, 0, closest); return(closest.GetClosestObjects()); }
/// <summary> /// Find the nearest element in the KD Tree to the specified element. /// </summary> /// <param name="_item">The item to search for</param> /// <returns>The closest node in the KD tree to the node specified</returns> public T FindNearest(T _item) { if (ExploredNodes != null) { ExploredNodes.Clear(); } var closest = new ClosestObjects <T>(); FindNearest(_item, 0, 0, closest); return(closest.GetClosestSingle()); }
/// <summary> /// Internal method for finding the closest N items to some item /// </summary> /// <param name="_item">The item to search for</param> /// <param name="_nodeIdx">The index of the node to start searching</param> /// <param name="_axis">The axis of the node at the index specified</param> /// <param name="_closest">A collection of close and valid nodes</param> private void FindNearest(T _item, int _nodeIdx, int _axis, ClosestObjects <T> _closest) { var currentItem = m_tree[_nodeIdx]; // we are below a leaf node, so the parent IS the leaf node to kick off the // unwinding of the recursion if (currentItem == null) { return; } var nextAxis = (_axis + 1) % m_axisCount; var itemCoord = m_selector(_item, _axis); var currentNodeCoord = m_selector(currentItem, _axis); var nextIdx = m_tree.GetLeftIndex(_nodeIdx); if (itemCoord > currentNodeCoord) // actually need the... { nextIdx++; // ... right child } FindNearest(_item, nextIdx, nextAxis, _closest); var thisDist = m_distanceFunction(currentItem, _item); var worstClosestDistance = _closest.Add(currentItem, thisDist); if (ExploredNodes != null) // for debugging { ExploredNodes.Add(currentItem); } var distFromAxis = itemCoord - currentNodeCoord; // This deals with the SQUARE of the distances- Could be more flexible distFromAxis *= distFromAxis; // The item is closer to the axis than the worst closest node in _closest if (distFromAxis < worstClosestDistance) { // so now we need to check the opposite side of the tree at the current node // The sibling is either one element after, or one element before, depending // on the coordinate relative to "_item"'s coordinate var siblingIndex = (itemCoord > currentNodeCoord) ? nextIdx - 1 : nextIdx + 1; // ... and go down that side of the tree FindNearest(_item, siblingIndex, nextAxis, _closest); } }