public Node[] RadialSearch(GetIndex <K> center, K radius, int count) { var nearestNeighbours = new NearestNeighbourList <Node, K>(count, this._minValue, this._compareKey); AddNearestNeighbours( _root, center, HyperRect <K> .Infinite(_dimensions, this._minValue, this._maxValue, this._compareKey), 0, nearestNeighbours, this._multiply(radius, radius)); count = nearestNeighbours.Count; var neighbourArray = new Node[count]; for (var index = 0; index < count; index++) { neighbourArray[count - index - 1] = nearestNeighbours.RemoveFurtherest(); } return(neighbourArray); }
public Node[] GetNearestNeighbours(GetIndex <K> point, int count) { if (count > Count) { count = Count; } if (count < 0) { throw new ArgumentException("Number of neighbors cannot be negative"); } if (count == 0) { return(new Node[0]); } var neighbours = new Node[count]; var nearestNeighbours = new NearestNeighbourList <Node, K>(count, this._minValue, this._compareKey); var rect = HyperRect <K> .Infinite(_dimensions, this._minValue, this._maxValue, this._compareKey); AddNearestNeighbours(_root, point, rect, 0, nearestNeighbours, this._maxValue); count = nearestNeighbours.Count; var neighbourArray = new Node[count]; for (var index = 0; index < count; index++) { neighbourArray[count - index - 1] = nearestNeighbours.RemoveFurtherest(); } return(neighbourArray); }
internal void AddNearestNeighbours( Node node, GetIndex <K> target, HyperRect <K> rect, int depth, NearestNeighbourList <Node, K> nearestNeighbours, K maxSearchRadiusSquared) { if (node == null) { return; } // Work out the current dimension int dimension = depth % _dimensions; // Split our hyper-rect into 2 sub rects along the current // node's point on the current dimension var leftRect = rect.Clone(); leftRect.MaxPoint[dimension] = this._locate(node.Value)(dimension); var rightRect = rect.Clone(); rightRect.MinPoint[dimension] = this._locate(node.Value)(dimension); // Which side does the target reside in? CompareResult compareTargetPoint = this._compareKey(target(dimension), this._locate(node.Value)(dimension)); int compareTargetPoint_as_int; switch (compareTargetPoint) { case Equal: compareTargetPoint_as_int = 0; break; case Less: compareTargetPoint_as_int = -1; break; case Greater: compareTargetPoint_as_int = 1; break; default: throw new System.NotImplementedException(); } var nearerRect = compareTargetPoint_as_int <= 0 ? leftRect : rightRect; var furtherRect = compareTargetPoint_as_int <= 0 ? rightRect : leftRect; var nearerNode = compareTargetPoint_as_int <= 0 ? node.LeftChild : node.RightChild; var furtherNode = compareTargetPoint_as_int <= 0 ? node.RightChild : node.LeftChild; // Let's walk down into the nearer branch if (nearerNode != null) { AddNearestNeighbours( nearerNode, target, nearerRect, depth + 1, nearestNeighbours, maxSearchRadiusSquared); } K distanceSquaredToTarget; // Walk down into the further branch but only if our capacity hasn't been reached // OR if there's a region in the further rect that's closer to the target than our // current furtherest nearest neighbour GetIndex <K> closestPointInFurtherRect = furtherRect.GetClosestPoint(target, this._dimensions); distanceSquaredToTarget = DistanceSquaredBetweenPoints(closestPointInFurtherRect, target); if (this._compareKey(distanceSquaredToTarget, maxSearchRadiusSquared) == (Less | Equal)) { if (nearestNeighbours.IsCapacityReached) { if (this._compareKey(distanceSquaredToTarget, nearestNeighbours.GetFurtherestDistance()) == Less) { AddNearestNeighbours( furtherNode, target, furtherRect, depth + 1, nearestNeighbours, maxSearchRadiusSquared); } } else { AddNearestNeighbours( furtherNode, target, furtherRect, depth + 1, nearestNeighbours, maxSearchRadiusSquared); } } // Try to add the current node to our nearest neighbours list distanceSquaredToTarget = DistanceSquaredBetweenPoints(this._locate(node.Value), target); if (this._compareKey(distanceSquaredToTarget, maxSearchRadiusSquared) == (Less | Equal)) { nearestNeighbours.Add(node, distanceSquaredToTarget); } }