public void SerializeQuadTree() { { var tree = new QuadTree <string>(); VerifyTreeClone(tree); } { var tree = new QuadTree <string>(); tree.AddItem("(0, 0)", new Vector2r()); tree.AddItem("(1, -1)", new Vector2r(1, -1)); tree.AddMonitor(new TestMonitor <string>(), new Bound(0, 10, 5)); VerifyTreeClone(tree); } { var tree = new QuadTree <string>(); tree.AddMonitor(new TestMonitor <string>(), new Bound(0, 0, 100)); tree.AddMonitor(new TestMonitor <string>(), new Bound(0, 5, 100)); VerifyTreeClone(tree); } }
public void CollectFromQuadTree(int worldScale) { var tree = new QuadTree <string>(worldScale); var added = new List <string>() { "-8,0", "-5,0", "0,0", "5,0", "8,0" }; tree.AddItem(added[0], new Vector2r(-8, 0)); tree.AddItem(added[1], new Vector2r(-5, 0)); tree.AddItem(added[2], new Vector2r(0, 0)); tree.AddItem(added[3], new Vector2r(5, 0)); tree.AddItem(added[4], new Vector2r(8, 0)); // collect everything (both positive and negative) { List <string> everything = tree.CollectItems <List <string> >(new Bound(0, 0, 200)); Assert.Equal(5, everything.Count); Assert.Contains(added[0], everything); Assert.Contains(added[1], everything); Assert.Contains(added[2], everything); Assert.Contains(added[3], everything); Assert.Contains(added[4], everything); } // collection a positive region { var positiveOnly = tree.CollectItems <List <string> >(new Bound(5, 0, 4)); Assert.Equal(2, positiveOnly.Count); Assert.Contains(added[3], positiveOnly); Assert.Contains(added[4], positiveOnly); } // collect a negative region { var negativeOnly = tree.CollectItems <List <string> >(new Bound(-5, 0, 4)); Assert.Equal(2, negativeOnly.Count); Assert.Contains(added[0], negativeOnly); Assert.Contains(added[1], negativeOnly); } // collect an empty region { var nothing = tree.CollectItems <List <string> >(new Bound(100, 0, 5)); Assert.Empty(nothing); } }
public void SimpleLeafTest() { var tree = new QuadTree <Tuple <int, int> >(new Rect(0, 0, 100, 100), GetTupleRect); tree.AddItem(Tuple.Create(25, 25)); tree.AddItem(Tuple.Create(25, 75)); tree.AddItem(Tuple.Create(75, 25)); tree.AddItem(Tuple.Create(75, 75)); Assert.Equal(4, tree.GetContainedItems(new Rect(0, 0, 100, 100)).Count); Assert.Equal(4, tree.GetContainedItems(new Rect(25, 25, 50, 50)).Count); Assert.Single(tree.GetContainedItems(new Rect(0, 0, 50, 50))); Assert.Single(tree.GetContainedItems(new Rect(50, 0, 50, 50))); Assert.Single(tree.GetContainedItems(new Rect(0, 50, 50, 50))); Assert.Single(tree.GetContainedItems(new Rect(50, 50, 50, 50))); }
private Task UpdateSnapPoints(bool allowCancellation = true) { var oldTokenSource = updateSnapPointsCancellationTokenSource; updateSnapPointsCancellationTokenSource = new CancellationTokenSource(); oldTokenSource.Cancel(); var token = updateSnapPointsCancellationTokenSource.Token; var width = ActualWidth; var height = ActualHeight; updateSnapPointsTask = Task.Run(() => { // populate the snap points var transformedQuadTree = new QuadTree <TransformedSnapPoint>(new Rect(0, 0, width, height), t => new Rect(t.ControlPoint.X, t.ControlPoint.Y, 0.0, 0.0)); foreach (var layer in Workspace.Drawing.GetLayers(token)) { token.ThrowIfCancellationRequested(); foreach (var entity in layer.GetEntities(token)) { token.ThrowIfCancellationRequested(); foreach (var snapPoint in entity.GetSnapPoints()) { transformedQuadTree.AddItem(new TransformedSnapPoint(snapPoint.Point, Project(snapPoint.Point), snapPoint.Kind)); } } } snapPointsQuadTree = transformedQuadTree; }); return(updateSnapPointsTask); }
/// <summary> /// Get all transformed snap points for the drawing with the given display transform. /// </summary> public static QuadTree <TransformedSnapPoint> GetSnapPoints(this Drawing drawing, Matrix4 displayTransform, double width, double height, CancellationToken cancellationToken = default) { // populate the snap points var transformedQuadTree = new QuadTree <TransformedSnapPoint>(new Rect(0, 0, width, height), t => new Rect(t.ControlPoint.X, t.ControlPoint.Y, 0.0, 0.0)); foreach (var layer in drawing.GetLayers(cancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); foreach (var entity in layer.GetEntities(cancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); foreach (var snapPoint in entity.GetSnapPoints()) { var projected = displayTransform.Transform(snapPoint.Point); transformedQuadTree.AddItem(new TransformedSnapPoint(snapPoint.Point, projected, snapPoint.Kind)); } } } // calculate intersections // TODO: can this be done in a meanintful way in a separate task? var primitives = drawing.GetEntities().SelectMany(e => e.GetPrimitives()).ToList(); for (int startIndex = 0; startIndex < primitives.Count; startIndex++) { cancellationToken.ThrowIfCancellationRequested(); var first = primitives[startIndex]; for (int i = startIndex + 1; i < primitives.Count; i++) { cancellationToken.ThrowIfCancellationRequested(); var current = primitives[i]; foreach (var intersection in first.IntersectionPoints(current)) { cancellationToken.ThrowIfCancellationRequested(); var projected = displayTransform.Transform(intersection); transformedQuadTree.AddItem(new TransformedSnapPoint(intersection, projected, SnapPointKind.Intersection)); } } } cancellationToken.ThrowIfCancellationRequested(); return(transformedQuadTree); }
public void ParentNodeTest() { var tree = new QuadTree <Tuple <int, int> >(new Rect(0, 0, 100, 100), GetTupleRect); tree.AddItem(Tuple.Create(25, 25)); tree.AddItem(Tuple.Create(25, 75)); tree.AddItem(Tuple.Create(75, 25)); tree.AddItem(Tuple.Create(75, 75)); tree.AddItem(Tuple.Create(50, 50)); tree.AddItem(Tuple.Create(10, 10)); Assert.Equal(6, tree.GetContainedItems(new Rect(0, 0, 100, 100)).Count); Assert.Equal(5, tree.GetContainedItems(new Rect(25, 25, 50, 50)).Count); Assert.Equal(3, tree.GetContainedItems(new Rect(0, 0, 50, 50)).Count); Assert.Equal(2, tree.GetContainedItems(new Rect(50, 0, 50, 50)).Count); Assert.Equal(2, tree.GetContainedItems(new Rect(0, 50, 50, 50)).Count); Assert.Equal(2, tree.GetContainedItems(new Rect(50, 50, 50, 50)).Count); }
public void MonitorTests(int worldScale) { var tree = new QuadTree <object>(worldScale); // test a monitor on an initially empty tree, add an object to the tree and ensure that // the monitor contains it, update the monitor to a position that doesn't contain the // item in the tree, ensure the monitor is empty, update the monitor so that it contains // the item again, ensure the monitor contains the item, update the monitor so that it // still contains the item & verify, then remove the monitor and ensure it is empty { var monitor = new TestMonitor <object>(); // inserting a monitor into an empty tree should result in an empty monitor tree.AddMonitor(monitor, new Bound(0, 0, 25)); Assert.Empty(monitor.Contained); // add an object to (0,0) var added = new object(); tree.AddItem(added, new Vector2r()); Assert.Contains(added, monitor.Contained); // update the position of the monitor so that it doesn't contain anything tree.UpdateMonitor(monitor, new Bound(0, 0, 25), new Bound(100, 100, 25)); Assert.Empty(monitor.Contained); // update the position of the monitor so that it contains the item tree.UpdateMonitor(monitor, new Bound(100, 100, 25), new Bound(5, 5, 25)); Assert.Contains(added, monitor.Contained); // update it back to its original position so that it contains everything tree.UpdateMonitor(monitor, new Bound(5, 5, 25), new Bound(0, 0, 25)); Assert.Contains(added, monitor.Contained); // remove the monitor tree.RemoveMonitor(monitor, new Bound(0, 0, 25)); Assert.Empty(monitor.Contained); } // test a monitor on a non-empty tree { var monitor = new TestMonitor <object>(); // the monitor should have the object already in the tree added to it tree.AddMonitor(monitor, new Bound(0, 0, 25)); Assert.NotEmpty(monitor.Contained); // add an object to (0,0) var added = new object(); tree.AddItem(added, new Vector2r()); Assert.Contains(added, monitor.Contained); // remove the monitor tree.RemoveMonitor(monitor, new Bound(0, 0, 25)); Assert.Empty(monitor.Contained); } // test a monitor on a non-empty tree that doesn't contain the objects already in the // tree { var monitor = new TestMonitor <object>(); // the monitor should remain empty when being added to the tree tree.AddMonitor(monitor, new Bound(100, 100, 25)); Assert.Empty(monitor.Contained); // add an object to (0,0); it should not be added to the monitor var added = new object(); tree.AddItem(added, new Vector2r()); Assert.Empty(monitor.Contained); // remove the monitor tree.RemoveMonitor(monitor, new Bound(100, 100, 25)); Assert.Empty(monitor.Contained); } }