public void RunTestGroup(int maxEntries, int numberOfItems) { RBush <Item> rBush = new RBush <Item>(maxEntries); double spaceScale = 50; IEnumerable <Item> items = ItemListGenerator.GenerateItems(numberOfItems, spaceScale); Console.WriteLine("maxEntries = " + maxEntries); // Tests: RunTest("BulkLoad", numberOfItems, () => { rBush.BulkLoad(items); }); RunTest("Search OLD", numberOfItems, () => { rBush.Search_Old(); }); RunTest("Search NEW", numberOfItems, () => { rBush.Search(); }); RunTest("Search envelope (Inf. bounds) OLD", numberOfItems, () => { rBush.Search_Old(Envelope.InfiniteBounds); }); RunTest("Search envelope (Inf. bounds) NEW", numberOfItems, () => { rBush.Search(Envelope.InfiniteBounds); }); RunTest("Iterate through IEnumerable [for comparison]", numberOfItems, () => { foreach (Item i in items) { } }); Console.ReadLine(); }
public static IReadOnlyList <T> KnnToPointSearch <T>(this RBush <T> tree, double x, double y, int n, Func <T, bool> predicate = null, double maxDist = -1) where T : ISpatialData { return(tree.KnnSearch(new KnnToPointQuery { X = x, Y = y }, n, predicate, maxDist)); }
public void FindNeighborsThatSatisfyAGivenPredicate() { RBush <Box> bush = new RBush <Box>(); bush.BulkLoad(richData); IEnumerable <Box> result = bush.KnnToPointSearch(2, 4, 1, b => b.Version < 5); if (result.Count() == 1) { Box item = result.First(); if (item.Envelope.MinX == 3 && item.Envelope.MinY == 3 && item.Envelope.MaxX == 3 && item.Envelope.MaxY == 3 && item.Version == 2) { //Test passes. Found the correct item } else { //Could not find the correct item Assert.True(false); } } else { //Could not find the correct item Assert.True(false); } }
public void BasicRemoveTest() { var tree = new RBush <Point>(maxEntries: 4); tree.BulkLoad(points); var len = points.Length; tree.Delete(points[0]); tree.Delete(points[1]); tree.Delete(points[2]); tree.Delete(points[len - 1]); tree.Delete(points[len - 2]); tree.Delete(points[len - 3]); var shouldFindPoints = points .Skip(3).Take(len - 6) .OrderBy(x => x) .ToList(); var foundPoints = tree.Search() .OrderBy(x => x) .ToList(); Assert.Equal(shouldFindPoints, foundPoints); }
public void DeleteAndSearchTest() { var tree = new RBush <Point>(maxEntries: 4); tree.BulkLoad(points); var len = points.Length; // Delete an existent point. bool resultExistent = tree.Delete(points[0]); var shouldFindPointsExistent = points .Skip(1) .OrderBy(x => x) .ToList(); var foundPointsExistent = tree.Search() .OrderBy(x => x) .ToList(); // Try to delete a non-existent point. bool resultNonExistent = tree.Delete(new Point(1245, 1233, 1245, 1233)); var shouldFindPointsNonExistent = shouldFindPointsExistent; var foundPointsNonExistent = tree.Search() .OrderBy(x => x) .ToList(); Assert.True(resultExistent); Assert.Equal(shouldFindPointsExistent, foundPointsExistent); Assert.False(resultNonExistent); Assert.Equal(shouldFindPointsNonExistent, foundPointsNonExistent); }
public void RootLeafSplitWorks() { var data = GetPoints(12); var tree = new RBush <Point>(); for (var i = 0; i < 9; i++) { tree.Insert(data[i]); } Assert.Equal(1, tree.Root.Height); Assert.Equal(9, tree.Root.children.Count); Assert.True(tree.Root.IsLeaf); Assert.Equal(0, tree.Root.Envelope.MinX); Assert.Equal(0, tree.Root.Envelope.MinY); Assert.Equal(8, tree.Root.Envelope.MaxX); Assert.Equal(8, tree.Root.Envelope.MaxY); tree.Insert(data[9]); Assert.Equal(2, tree.Root.Height); Assert.Equal(2, tree.Root.children.Count); Assert.False(tree.Root.IsLeaf); Assert.Equal(0, tree.Root.Envelope.MinX); Assert.Equal(0, tree.Root.Envelope.MinY); Assert.Equal(9, tree.Root.Envelope.MaxX); Assert.Equal(9, tree.Root.Envelope.MaxY); }
public static IEnumerable <IPoint> Execute(IGeometry line1, IGeometry line2) { IDictionary <string, IPoint> unique = new Dictionary <string, IPoint>(); IList <IPoint> intersections = new List <IPoint>(); RBush <Extensions.SpatialDataWrapper <Segment> > tree = new RBush <Extensions.SpatialDataWrapper <Segment> >(); tree.BulkLoad(LineSegment.Execute(line2).Select(a => a.AsSpatialData <Segment>())); foreach (Segment segment in LineSegment.Execute(line1)) { foreach (Extensions.SpatialDataWrapper <Segment> match in tree.Search(segment.BBox.AsEnvelope())) { IPoint intersect = Intersects(segment.LineString, match.GetOriginalData <Segment>().LineString); if (intersect != null) { var key = string.Join(",", intersect.X, intersect.Y); if (!unique.ContainsKey(key)) { unique.Add(key, intersect); intersections.Add(intersect); } } } } return(intersections); }
public void TestSearch_AfterBulkLoadWithSplitRoot() { int maxEntries = 4; var tree = new RBush <Point>(maxEntries); int numFirstSet = maxEntries * maxEntries + 2; // Split-root will occur twice. var firstSet = points.Take(numFirstSet); Envelope firstSetEnvelope = new Envelope( firstSet.Min(p => p.Envelope.MinX), firstSet.Min(p => p.Envelope.MinY), firstSet.Max(p => p.Envelope.MaxX), firstSet.Max(p => p.Envelope.MaxY)); tree.BulkLoad(firstSet); int numExtraPoints = 5; var extraPointsSet = points.TakeLast(numExtraPoints); Envelope extraPointsSetEnvelope = new Envelope( extraPointsSet.Min(p => p.Envelope.MinX), extraPointsSet.Min(p => p.Envelope.MinY), extraPointsSet.Max(p => p.Envelope.MaxX), extraPointsSet.Max(p => p.Envelope.MaxY)); foreach (var p in extraPointsSet) { tree.Insert(p); } Assert.Equal(extraPointsSet.OrderBy(x => x), tree.Search(extraPointsSetEnvelope).OrderBy(x => x)); }
public void FindNeighborsThatSatisfyAGivenPredicate() { RBush <Box> bush = new RBush <Box>(); bush.BulkLoad(richData); IEnumerable <Box> result = bush.KnnToLineSegmentSearch(6386.5, 3349.5, 6393, 3353.5, 1, b => b.Version > 2); if (result.Count() == 1) { Box item = result.First(); if (item.Envelope.MinX == 6393.8 && item.Envelope.MinY == 3354.0 && item.Envelope.MaxX == 6395.3 && item.Envelope.MaxY == 3356.0 && item.Version == 3) { //Test passes. Found the correct item } else { Assert.True(false, "Could not find the correct item"); } } else { Assert.True(false, "Could not find the correct item"); } }
public void FindsNNeighbors1() { RBush <Box> bush = new RBush <Box>(); bush.BulkLoad(boxes); IEnumerable <Box> result = bush.KnnToLineSegmentSearch(6362, 3343.5, 6360.75, 3344, 10); Box[] mustBeReturned = Box.CreateBoxes(new double[, ] { { 6359.0, 3343.0, 6362.5, 3345.0 }, { 6357.0, 3342.0, 6363.5, 3343.0 }, { 6360.5, 3340.0, 6361.5, 3342.0 }, { 6364.0, 3342.0, 6365.0, 3344.5 }, { 6362.0, 3340.5, 6363.0, 3341.5 }, { 6358.5, 3337.5, 6360.5, 3341.5 }, { 6361.0, 3339.0, 6363.0, 3340.0 }, { 6364.5, 3340.5, 6368.0, 3341.0 }, { 6363.5, 3337.5, 6365.0, 3340.0 }, { 6367.0, 3342.0, 6368.0, 3344.0 }, }); Assert.True(mustBeReturned.Length == result.Count()); Assert.True(result.ElementAt(0).CompareTo(mustBeReturned[0]) == 0); Assert.True(result.ElementAt(1).CompareTo(mustBeReturned[1]) == 0); Assert.True(result.ElementAt(2).CompareTo(mustBeReturned[2]) == 0); Assert.True(result.ElementAt(3).CompareTo(mustBeReturned[3]) == 0 || result.ElementAt(3).CompareTo(mustBeReturned[4]) == 0); Assert.True(result.ElementAt(4).CompareTo(mustBeReturned[3]) == 0 || result.ElementAt(4).CompareTo(mustBeReturned[4]) == 0); Assert.True(result.ElementAt(5).CompareTo(mustBeReturned[5]) == 0); Assert.True(result.ElementAt(6).CompareTo(mustBeReturned[6]) == 0); Assert.True(result.ElementAt(7).CompareTo(mustBeReturned[7]) == 0); Assert.True(result.ElementAt(8).CompareTo(mustBeReturned[8]) == 0); Assert.True(result.ElementAt(9).CompareTo(mustBeReturned[9]) == 0); }
public void TestSearchAfterInsertWithSplitRoot() { var maxEntries = 4; var tree = new RBush <Point>(maxEntries); var numFirstSet = maxEntries * maxEntries + 2; // Split-root will occur twice. var firstSet = points.Take(numFirstSet); foreach (var p in firstSet) { tree.Insert(p); } var numExtraPoints = 5; var extraPointsSet = points.Skip(points.Length - numExtraPoints); var extraPointsSetEnvelope = extraPointsSet.Aggregate(Envelope.EmptyBounds, (e, p) => e.Extend(p.Envelope)); foreach (var p in extraPointsSet) { tree.Insert(p); } // first 10 entries and last 5 entries are completely mutually exclusive // so searching the bounds of the new set should only return the new set exactly Assert.Equal(extraPointsSet.OrderBy(x => x), tree.Search(extraPointsSetEnvelope).OrderBy(x => x)); }
public void BasicRemoveTest() { var tree = new RBush <Point>(maxEntries: 4); tree.BulkLoad(points); var len = points.Length; tree.Delete(points[0]); tree.Delete(points[1]); tree.Delete(points[2]); tree.Delete(points[len - 1]); tree.Delete(points[len - 2]); tree.Delete(points[len - 3]); var shouldFindPoints = points .Skip(3).Take(len - 6) .OrderBy(x => x) .ToList(); var foundPoints = tree.Search() .OrderBy(x => x) .ToList(); Assert.Equal(shouldFindPoints, foundPoints); Assert.Equal(shouldFindPoints.Count, tree.Count); Assert.Equal( shouldFindPoints.Aggregate(Envelope.EmptyBounds, (e, p) => e.Extend(p.Envelope)), tree.Envelope); }
public void NonExistentItemCanBeDeleted() { var tree = new RBush <Point>(maxEntries: 4); tree.BulkLoad(points); tree.Delete(new Point(13, 13, 13, 13)); }
public void SearchReturnsEmptyResultIfNothingFound() { var tree = new RBush <Point>(maxEntries: 4); tree.BulkLoad(points); Assert.Equal(new Point[] { }, tree.Search(new Envelope(200, 200, 210, 210))); }
public void Delete_TreeIsEmpty_ShouldNotThrow() { var tree = new RBush <Point>(); tree.Delete(new Point(1, 1, 1, 1)); Assert.Equal(0, tree.Count); }
public static IReadOnlyList <T> KnnToLineSegmentSearch <T>(this RBush <T> tree, double x0, double y0, double x1, double y1, int n, Func <T, bool> predicate = null, double maxDist = -1) where T : ISpatialData { return(tree.KnnSearch(new KnnToLineSegmentQuery { X0 = x0, Y0 = y0, X1 = x1, Y1 = y1 }, n, predicate, maxDist)); }
public void DoesNotThrowIfRequestingTooManyItems() { var bush = new RBush <Box>(); bush.BulkLoad(boxes); bush.Knn(1000, 40, 40); }
public void DoesNotThrowIfRequestingTooManyItemsForMaxDistance() { var bush = new RBush <Box>(); bush.BulkLoad(boxes); bush.Knn(1000, 40, 40, maxDistance: 10); }
public void BulkLoadTestData() { var tree = new RBush <Point>(); tree.BulkLoad(points); Assert.Equal(points.Length, tree.Count); Assert.Equal(points.OrderBy(x => x).ToList(), tree.Search().OrderBy(x => x).ToList()); }
public void NonExistentItemCanBeDeleted() { var tree = new RBush <Point>(maxEntries: 4); tree.BulkLoad(points); tree.Delete(new Point(13, 13, 13, 13)); Assert.Equal(points.Length, tree.Count); }
public void ClearWorks() { var tree = new RBush <Point>(maxEntries: 4); tree.BulkLoad(points); tree.Clear(); Assert.Equal(0, tree.Count); Assert.Empty(tree.Root.children); }
public void BulkLoadSplitsTreeProperly() { var tree = new RBush <Point>(maxEntries: 4); tree.BulkLoad(points); tree.BulkLoad(points); Assert.Equal(points.Length * 2, tree.Count); Assert.Equal(4, tree.Root.Height); }
internal static IReadOnlyList <T> KnnSearch <T>(this RBush <T> tree, object query, int n, Func <T, bool> predicate = null, double maxDist = -1) where T : ISpatialData { var distCalculator = new DistanceToSpatialCalculator(); if (maxDist > 0) { maxDist = maxDist * maxDist; //compare quadratic distances } List <T> result = new List <T>(); //priority queue var queue = new C5.IntervalHeap <IDistanceToSpatial>(new DistComparer()); RBush <T> .Node node = tree.Root; while (node != null) { foreach (ISpatialData child in node.Children) //for each child { var childDistData = distCalculator.CalculateDistanceToSpatial(query, child); //calc distance to box if (maxDist < 0 || childDistData.SquaredDistanceToBox <= maxDist) //check if distance less than max distance { queue.Add(childDistData); //add to queue } } //dequeue all objects that are items stored in RBush while (queue.Count > 0 && queue.FindMin().SpatialData is T) { var candidateWr = queue.DeleteMin(); //this item goes to result T candidate = (T)candidateWr.SpatialData; if (predicate == null || predicate.Invoke(candidate)) //if element satisfy the condition { result.Add(candidate); //add to result } if (n > 0 && result.Count == n) //if the desired amount is already in the result { return(result); //return result } } //process next element in queue if (queue.Count > 0) { node = queue.DeleteMin().SpatialData as RBush <T> .Node; } else { node = null; } } return(result); }
public void Delete_DeletingLastPoint_ShouldNotThrow() { var tree = new RBush <Point>(); Point p = new Point(1, 1, 1, 1); tree.Insert(p); tree.Delete(p); Assert.Equal(0, tree.Count); }
/// <summary> /// Search k nearest neighbors to given point or to to given line segment /// </summary> /// <typeparam name="T">type of RBush items</typeparam> /// <param name="tree">RBush object</param> /// <param name="x1">x coordinate of query point. /// Or if x2 and y2 not null, x coordinate of first endpoint of query line segment</param> /// <param name="y1">y coordinate of query point. /// Or if x2 and y2 not null, y coordinate of first endpoint of query line segment</param> /// <param name="n">number of nearest neighbors to get</param> /// <param name="predicate">condition for neighbors</param> /// <param name="maxDist">max distance for nearest neighbors</param> /// <param name="x2">if not null is x coordinate of second endpoint of query line segment</param> /// <param name="y2">if not null is y coordinate of second endpoint of query line segment</param> /// <returns></returns> public static IReadOnlyList <T> KnnSearch <T>(this RBush <T> tree, double x1, double y1, int n, Func <T, bool> predicate = null, double maxDist = -1, double?x2 = null, double?y2 = null) where T : ISpatialData { if (maxDist > 0) { maxDist = maxDist * maxDist; //All distances are quadratic!!! } List <T> result = new List <T>(); //priority queue C5.IntervalHeap <SpatialDataWrapper> queue = new C5.IntervalHeap <SpatialDataWrapper>(new DistComparer()); RBush <T> .Node node = tree.Root; while (node != null) { foreach (ISpatialData child in node.Children) //for each child { SpatialDataWrapper childDistData = new SpatialDataWrapper(child, x1, y1, x2, y2); //calc distance to box if (maxDist < 0 || childDistData.SquaredDistanceToBox <= maxDist) //check if distance less than max distance { queue.Add(childDistData); //add to queue } } //dequeue all objects that are items stored in RBush while (queue.Count > 0 && queue.FindMin().SpatialData is T) { SpatialDataWrapper candidate = queue.DeleteMin(); //this item goes to result T _candidate = (T)candidate.SpatialData; if (predicate == null || predicate.Invoke(_candidate)) //if element satisfy the condition { result.Add(_candidate); //add to result } if (n > 0 && result.Count == n) //if the desired amount is already in the result { return(result); //return result } } //process next element in queue if (queue.Count > 0) { node = queue.DeleteMin().SpatialData as RBush <T> .Node; } else { node = null; } } return(result); }
public void InsertTestData() { var tree = new RBush <Point>(); foreach (var p in points) { tree.Insert(p); } Assert.Equal(points.Length, tree.Count); Assert.Equal(points.OrderBy(x => x), tree.Search().OrderBy(x => x)); }
public void FindsNNeighbors() { var bush = new RBush <Box>(); bush.BulkLoad(boxes); var result = bush.Knn(10, 40, 40); var expected = boxes .OrderBy(b => b.DistanceTo(40, 40)) .Take(10) .ToList(); Assert.Equal(expected, result); }
public void FindAllNeighborsForMaxDistance() { RBush <Box> bush = new RBush <Box>(); bush.BulkLoad(boxes); IEnumerable <Box> result = bush.KnnToPointSearch(40, 40, 0, maxDist: 10); foreach (Box resBox in result) { Assert.True(CalcBoxDist(resBox, 40, 40) <= 10); } }
/// <summary> /// Method used to split all the bounding boxes into a predefined config based smaller buckets to be able to parallely searched /// </summary> private void SplitToBuckets() { int subListSize = BoundingBoxes.Count / MaxConcurrentEngines; int elementsIterated = 0; while (elementsIterated < BoundingBoxes.Count) { int remainingElements = Math.Min(BoundingBoxes.Count - elementsIterated, subListSize); var newBush = new RBush <BoundingBox>(); newBush.BulkLoad((BoundingBoxes as List <BoundingBox>).GetRange(elementsIterated, remainingElements)); BoxesEnginesBuckets.Add(newBush); elementsIterated += subListSize; } }
public void FindAllNeighborsForMaxDistance() { var bush = new RBush <Box>(); bush.BulkLoad(boxes); var result = bush.Knn(0, 40, 40, maxDistance: 10); var expected = boxes .Where(b => b.DistanceTo(40, 40) <= 10) .OrderBy(b => b.DistanceTo(40, 40)) .ToList(); Assert.Equal(expected, result); }