public void InfiniteShouldReturnTheSameResultInBothVerison() { var minPoint = new Coordinate { Latitude = 6544, Longitude = 5577 }; var maxPoint = new Coordinate { Latitude = 9687, Longitude = 1254 }; var minPointA = new[] { minPoint.Latitude, minPoint.Longitude }; var maxPointA = new[] { maxPoint.Latitude, maxPoint.Longitude }; var hyperRect = new HyperRect <double>(); hyperRect.MinPoint = minPointA; hyperRect.MaxPoint = maxPointA; var hyperRectCoordinate = new HyperRectCoordinate <Coordinate>(); hyperRectCoordinate.MinPoint = minPoint; hyperRectCoordinate.MaxPoint = maxPoint; var rect = hyperRect.Clone(); var rectCoordinate = hyperRectCoordinate.Clone(); var res1 = HyperRect <double> .Infinite(2, double.MaxValue, double.MinValue); var res2 = HyperRectCoordinate <Coordinate> .Infinite(2, double.MaxValue, double.MinValue); res1.MaxPoint[0].Should().Be(res2.MaxPoint.Latitude); res1.MaxPoint[1].Should().Be(res2.MaxPoint.Longitude); res1.MinPoint[0].Should().Be(res2.MinPoint.Latitude); res1.MinPoint[1].Should().Be(res2.MinPoint.Longitude); }
private static KDNode Process(Tuple <Vector2d, int>[] pointList, HyperRect hr, int depth) { if (pointList.Length == 0) { return(null); } // Sort point list and choose median as pivot element var sorted = pointList.OrderBy(p => GetValue(p.Item1, depth)).ToArray(); var medianIndex = sorted.Length / 2; var location = sorted[medianIndex]; // Create node and construct subtree var node = new KDNode(sorted[medianIndex].Item1, sorted[medianIndex].Item2, hr, depth); var split = hr.Split(node.median, depth); if (pointList.Length > 1) { var lnodes = pointList.Where(p => GetValue(p.Item1, depth) < node.median).ToArray(); var rnodes = pointList.Where(p => GetValue(p.Item1, depth) >= node.median && p.Item2 != node.key).ToArray(); node.lChild = Process(lnodes, split.Item1, depth + 1); node.rChild = Process(rnodes, split.Item2, depth + 1); } return(node); }
public void CloneGenerateTheSameResultInBothVersion() { var minPoint = new Coordinate { Latitude = 6544, Longitude = 5577 }; var maxPoint = new Coordinate { Latitude = 9687, Longitude = 1254 }; var minPointA = new[] { minPoint.Latitude, minPoint.Longitude }; var maxPointA = new[] { maxPoint.Latitude, maxPoint.Longitude }; var hyperRect = new HyperRect <double>(); hyperRect.MinPoint = minPointA; hyperRect.MaxPoint = maxPointA; var hyperRectCoordinate = new HyperRectCoordinate <Coordinate>(); hyperRectCoordinate.MinPoint = minPoint; hyperRectCoordinate.MaxPoint = maxPoint; var rect = hyperRect.Clone(); var rectCoordinate = hyperRectCoordinate.Clone(); rect.MinPoint[0].Should().Be(rectCoordinate.MinPoint.Latitude); rect.MinPoint[1].Should().Be(rectCoordinate.MinPoint.Longitude); rect.MaxPoint[0].Should().Be(rectCoordinate.MaxPoint.Latitude); rect.MaxPoint[1].Should().Be(rectCoordinate.MaxPoint.Longitude); }
public void GtClosestPointGenerateTheSameResultInBothVersion() { var minPoint = new Coordinate { Latitude = 6544, Longitude = 5577 }; var maxPoint = new Coordinate { Latitude = 9687, Longitude = 1254 }; var minPointA = new[] { minPoint.Latitude, minPoint.Longitude }; var maxPointA = new[] { maxPoint.Latitude, maxPoint.Longitude }; var targetPoint = new Coordinate { Latitude = 3322, Longitude = 4562 }; var targetPointA = new[] { targetPoint.Latitude, targetPoint.Longitude }; var hyperRect = new HyperRect <double>(); hyperRect.MinPoint = minPointA; hyperRect.MaxPoint = maxPointA; var hyperRectCoordinate = new HyperRectCoordinate <Coordinate>(); hyperRectCoordinate.MinPoint = minPoint; hyperRectCoordinate.MaxPoint = maxPoint; var rect = hyperRect.GetClosestPoint(targetPointA); var rectCoordinate = hyperRectCoordinate.GetClosestPoint(targetPoint); rect[0].Should().Be(rectCoordinate.Latitude); rect[1].Should().Be(rectCoordinate.Longitude); }
public HyperRect <T> Clone() { var rect = new HyperRect <T>(); rect.MinPoint = MinPoint; rect.MaxPoint = MaxPoint; return(rect); }
private KDNode(Vector2d location, int key, HyperRect hr, int depth) { this.location = location; this.key = key; this.hr = hr; this.depth = depth; median = GetValue(location, depth); }
/// <inheritdoc /> public IEnumerable <int> NearestNeighborIndexes(TNode target, int k) { var point = this.PointSelector(target); var nearestNeighborList = new BoundablePriorityList <int, double>(k, true); var rect = HyperRect <double> .Infinite(this.Dimensions, double.MaxValue, double.MinValue); this.SearchForNearestNeighbors(this.rootNode, point, rect, 0, nearestNeighborList, double.MaxValue); return(nearestNeighborList); }
public HyperRect <T> Clone() { var rect = new HyperRect <T> { MinPoint = MinPoint, MaxPoint = MaxPoint }; return(rect); }
private int area(HyperRect <int> rect) { var returnInt = 1; for (int i = 0; i < 3; i++) { returnInt = returnInt * (rect.MaxPoint[i] - rect.MinPoint[i]); } return(returnInt < 0 ? -returnInt : returnInt); }
public static HyperRect <T> Infinite(int dimensions, ITypeMath <T> math) { var rect = new HyperRect <T>(); rect.MinPoint = new T[dimensions]; rect.MaxPoint = new T[dimensions]; for (var dimension = 0; dimension < dimensions; dimension++) { rect.MinPoint[dimension] = math.NegativeInfinity; rect.MaxPoint[dimension] = math.PositiveInfinity; } return(rect); }
/// <inheritdoc /> public IEnumerable <int> RadialSearchIndexes(TNode center, double radius) { var nearestNeighbors = new BoundablePriorityList <int, double>(); var centerPoint = this.PointSelector(center); this.SearchForNearestNeighbors( this.rootNode, centerPoint, HyperRect <double> .Infinite(this.Dimensions, double.MaxValue, double.MinValue), 0, nearestNeighbors, radius); return(nearestNeighbors); }
static HyperRect() { var accessor = default(TArrayAccessor); var arithmetic = default(TArithmetic); var dim = Dimension; var rect = new HyperRect(); for (int i = 0; i < dim; i++) { accessor.At(ref rect.MinPoint, i) = arithmetic.NegativeInfinity; accessor.At(ref rect.MaxPoint, i) = arithmetic.PositiveInfinity; } Infinite = rect; }
public Tuple <HyperRect, HyperRect> Split(double x, int dim) { var lRect = new HyperRect(MinPoint, MaxPoint); var rRect = new HyperRect(MinPoint, MaxPoint); if (dim % 2 == 0) { lRect.MaxPoint.X = x; rRect.MinPoint.X = x; } else { lRect.MaxPoint.Y = x; rRect.MinPoint.Y = x; } return(new Tuple <HyperRect, HyperRect>(lRect, rRect)); }
public static KDNode Process(IEnumerable <Tuple <Vector2d, int> > pointList) { return(Process(pointList.ToArray(), HyperRect.GetInfinite(), 0)); }
/// <summary> /// A top-down recursive method to find the nearest neighbors of a given point. /// </summary> /// <param name="node">The index of the node for the current recursion branch.</param> /// <param name="target">The point whose neighbors we are trying to find.</param> /// <param name="rect">The <see cref="HyperRect{T}"/> containing the possible nearest neighbors.</param> /// <param name="dimension">The current splitting dimension for this recursion branch.</param> /// <param name="nearestNeighbors">The <see cref="BoundedPriorityList{TElement,TPriority}"/> containing the nearest neighbors already discovered.</param> /// <param name="maxSearchRadius">The radius of the current largest distance to search from the <paramref name="target"/></param> private void SearchForNearestNeighbors( KDNode node, double[] target, HyperRect <double> rect, int dimension, BoundablePriorityList <int, double> nearestNeighbors, double maxSearchRadius) { if (node == null) { return; } // Work out the current dimension var dim = dimension % this.Dimensions; // Get the coordinate of the current node. var coordinate = this.PointSelector(this.InternalList[node.ElementIndex]); // Split our hyper-rectangle into 2 sub rectangles along the current // node's point on the current dimension var leftRect = rect.Clone(); leftRect.MaxPoint[dim] = coordinate[dim]; var rightRect = rect.Clone(); rightRect.MinPoint[dim] = coordinate[dim]; // Determine which side the target resides in var comparison = target[dim] <= coordinate[dim]; var nearerRect = comparison ? leftRect : rightRect; var furtherRect = comparison ? rightRect : leftRect; var nearerNode = comparison ? node.Left : node.Right; var furtherNode = comparison ? node.Right : node.Left; // Move down into the nearer branch this.SearchForNearestNeighbors( nearerNode, target, nearerRect, dimension + 1, nearestNeighbors, maxSearchRadius); // Walk down into the further branch but only if our capacity hasn't been reached // OR if there's a region in the further rectangle that's closer to the target than our // current furtherest nearest neighbor var closestPointInFurtherRect = furtherRect.GetClosestPoint(target); var distanceToTarget = this.Metric(closestPointInFurtherRect, target); if (distanceToTarget.CompareTo(maxSearchRadius) <= 0) { if (nearestNeighbors.IsFull) { if (distanceToTarget.CompareTo(nearestNeighbors.MaxPriority) < 0) { this.SearchForNearestNeighbors( furtherNode, target, furtherRect, dimension + 1, nearestNeighbors, maxSearchRadius); } } else { this.SearchForNearestNeighbors( furtherNode, target, furtherRect, dimension + 1, nearestNeighbors, maxSearchRadius); } } // Try to add the current node to our nearest neighbors list distanceToTarget = this.Metric(coordinate, target); if (distanceToTarget.CompareTo(maxSearchRadius) <= 0) { nearestNeighbors.Add(node.ElementIndex, distanceToTarget); } }