public List <SpatialObj <T> > WindowQuery(Rectangle window) { // Finds objects within a Rectangular range (window) List <SpatialObj <T> > answer = new List <SpatialObj <T> >(); Queue <PartitionNode <T> > searching_nodes = new Queue <PartitionNode <T> >(); searching_nodes.Enqueue(rootNode); while (searching_nodes.Count > 0) { PartitionNode <T> current_node = searching_nodes.Dequeue(); if (current_node.IntersectsWith(window)) { answer.AddRange(current_node.GetRangeQueryObj(window)); if (current_node.HasChildren()) { foreach (PartitionNode <T> child in current_node.GetChildren()) { if (!searching_nodes.Contains(child)) { searching_nodes.Enqueue(child); } } } } } return(answer); }
public PartitionNode <T> AddRectangle(SpatialObj <T> rect, bool reorganize = true) { PartitionNode <T> deepest_field = FindContainingField(rect, rootNode); if (deepest_field.IsFull() && !deepest_field.HasChildren()) { PartitionField(deepest_field); PartitionNode <T> node = AddRectangle(rect); if (reorganize) { ReorganizeOverflownNodes(); } if (node != null) { return(node); } } else { bool overflown = deepest_field.StoreRectangle(rect); } if (deepest_field != null) { Count += 1; } return(deepest_field); }
/// <summary> /// Handles the Mouse Enter event for the highlight polygon /// </summary> /// <param name="sender">The polygon that raised the event</param> /// <param name="e">Specifies properties about the mouse click</param> private void OnHighlightPolygonMouseEnter(object sender, MouseEventArgs e) { Polygon polygon = (Polygon)sender; PartitionNode partitionNode = _clusterPolygons[polygon]; List <string> existingValues = new List <string>(); List <KeyValuePair <string, string> > attributes = new List <KeyValuePair <string, string> >(); IEnumerable <AttributeSimilarityDescriptor> descriptors = AttributeSimilarityManager.Instance.SimilarityDescriptors; if (!_mouseCaptured) { foreach (var descriptor in descriptors) { foreach (var node in partitionNode.Nodes) { var nodeAttributes = from a in node.ParentNode.Attributes where a.Key == descriptor.AttributeName select a; foreach (var attribute in nodeAttributes) { if (!existingValues.Contains(attribute.Value.Value)) { attributes.Add(new KeyValuePair <string, string>(attribute.Key, attribute.Value.Value)); existingValues.Add(attribute.Value.Value); } } } } } // Show the popup ViewModelLocator.AttributePopupVMStatic.Show(attributes); }
public GraphComponents GetClusteredGraph() { IEnumerable <INodeShape> nodes = _sourceGraph.GetNodeViewModels(); _partitionedGraph = new GraphComponents(_sourceGraph.Scope); // Loop over all the nodes in the list foreach (NodeViewModelBase nodeVM in nodes) { // Create a partition node for clusters PartitionNode pn = GetClusterAsPartitionNode(nodeVM); // Add the partition node to the graph _partitionedGraph.AddNodeViewModel(pn); } // Loop over all of the partition nodes in our partition graph foreach (PartitionNode pn in _partitionNodes) { // Loop over all the external connections foreach (Edge edge in pn.ExternalConnections) { INodeShape targetNodeVM = GraphManager.Instance.GetGraphComponents(_sourceGraph.Scope).GetNodeViewModel(edge.Target); // Check if the edge's target node is in our partition collection if (_nodeToPartition.ContainsKey(targetNodeVM)) { IEdge newEdge = edge.Copy(pn, _nodeToPartition[targetNodeVM]); _partitionedGraph.Data.AddEdge(newEdge); } } } return(_partitionedGraph); }
private SpatialObj <T> RemoveRectangle(SpatialObj <T> rect, PartitionNode <T> node) { if (node.DeleteRectangle(rect)) { Count -= 1; } MergeEmptyChildren(node); return(rect); }
public Tuple <PartitionNode <T>, SpatialObj <T> > IncrementalNNFindNext() { if (incrNN_queue is null) { return(null); } while (incrNN_queue.Count > 0) { NodeOrObj current_element = incrNN_queue.Dequeue(); while (incrNN_queue.Count > 0 && incrNN_queue.First().Equals(current_element)) { incrNN_queue.Dequeue(); } if (current_element.IsObj()) { return(Tuple.Create(current_element.GetNode(), current_element.GetObj())); } else { PartitionNode <T> current_node = current_element.GetNode(); double current_dist = current_node.GetDistanceToPointSq(incrNN_origin); if (!current_node.IsEmpty()) { foreach (SpatialObj <T> obj in current_node.GetAllObjects()) { double distance = obj.boundingBox.GetDistanceSqToPoint(incrNN_origin); if (distance >= current_dist) { NodeOrObj obj_nodeOrObj = new NodeOrObj(); obj_nodeOrObj.SetNode(current_node); obj_nodeOrObj.SetObj(obj); incrNN_queue.Enqueue(obj_nodeOrObj, (float)distance); } } } if (current_node.HasChildren()) { foreach (PartitionNode <T> child_node in current_node.GetChildren()) { double distance = child_node.GetDistanceToPointSq(incrNN_origin); if (distance >= current_dist) { NodeOrObj node_nodeOrObj = new NodeOrObj(); node_nodeOrObj.SetNode(child_node); incrNN_queue.Enqueue(node_nodeOrObj, (float)distance); } } } } } return(null); }
private Dictionary <PartitionNode <T>, SpatialObj <T> > FindNearestRectToPoint(Point p, PartitionNode <T> node) { Dictionary <PartitionNode <T>, SpatialObj <T> > answer_dict = new Dictionary <PartitionNode <T>, SpatialObj <T> >(); SimplePriorityQueue <PartitionNode <T> > searching_nodes = new SimplePriorityQueue <PartitionNode <T> >(); searching_nodes.Enqueue(node, 0); SpatialObj <T> answer = default(SpatialObj <T>); PartitionNode <T> answer_node = null; bool used = false; double min_distance_sq = rootNode.GetMaxDistance(); while (searching_nodes.Count > 0) { PartitionNode <T> current_node = searching_nodes.Dequeue(); Dictionary <SpatialObj <T>, double> nearest_rect = current_node.GetNearestRectangle(p); if (nearest_rect.Count > 0) { foreach (KeyValuePair <SpatialObj <T>, double> entry in nearest_rect) { if (entry.Value <= min_distance_sq || entry.Value < Statics.EPSILON) { min_distance_sq = entry.Value; answer = entry.Key; answer_node = current_node; used = false; if (min_distance_sq < Statics.EPSILON) { answer_dict.Add(answer_node, answer); used = true; } } } } if (current_node.HasChildren()) { foreach (PartitionNode <T> child in current_node.GetChildren()) { double field_dist = child.GetDistanceToPointSq(p); if (field_dist <= min_distance_sq) { searching_nodes.Enqueue(child, (float)field_dist); } } } } if (!used) { answer_dict.Add(answer_node, answer); } return(answer_dict); }
private void MergeEmptyChildren(PartitionNode <T> node) { if (node.HasChildren() && node.AreExistingChildrenEmpty()) { node.MergeEmptyChildren(); } if (node.IsRootNode() || !node.IsEmpty() || node.HasChildren()) { return; } foreach (var parent in node.GetParent()) { MergeEmptyChildren(parent); } }
public ICollection <Point> CalculateConvexHullForCluster(PartitionNode pn) { double padding = 0; List <Point> points = new List <Point>(); foreach (NodeViewModelBase nodeVM in pn.Nodes) { points.Add(new Point(nodeVM.Position.X - nodeVM.Width / 2 - padding, nodeVM.Position.Y - nodeVM.Height / 2 - padding)); points.Add(new Point(nodeVM.Position.X - nodeVM.Width / 2 - padding, nodeVM.Position.Y + nodeVM.Height / 2 + padding)); points.Add(new Point(nodeVM.Position.X + nodeVM.Width / 2 + padding, nodeVM.Position.Y + nodeVM.Height / 2 + padding)); points.Add(new Point(nodeVM.Position.X + nodeVM.Width / 2 + padding, nodeVM.Position.Y - nodeVM.Height / 2 - padding)); } return(ConvexHull.CalculateConvexHull(points)); }
public void GetOtherPartitionReturnsTheCorrectPartition() { var factory = new PartitionEntityFactory(); PartitionNode nodeA = new PartitionNode(factory); PartitionNode nodeB = new PartitionNode(factory); IPartition p1, p2; nodeA.Partition = p1 = new DMT.Partition.Data.Partition(factory);; nodeB.Partition = p2 = new DMT.Partition.Data.Partition(factory);; PartitionEdge edge = new PartitionEdge(nodeA, nodeB, Core.Interfaces.EdgeDirection.Both, factory); nodeA.ConnectTo(nodeB, edge); Assert.Equal(p2, edge.GetOtherPartition(p1)); }
public void IsInnerReturnsTrueOnlyForInnerEdges() { var factory = new PartitionEntityFactory(); IPartition partition = new DMT.Partition.Data.Partition(factory); PartitionNode nodeA = new PartitionNode(factory); PartitionNode nodeB = new PartitionNode(factory); nodeA.Partition = partition; nodeB.Partition = partition; PartitionEdge edge = new PartitionEdge(nodeA, nodeB, Core.Interfaces.EdgeDirection.Both, factory); nodeA.ConnectTo(nodeB, edge); Assert.True(edge.IsInner); }
public SpatialObj <T> FindNearestObjAndRemove(Point p) { SpatialObj <T> obj = default(SpatialObj <T>); PartitionNode <T> node = null; foreach (KeyValuePair <PartitionNode <T>, SpatialObj <T> > entry in FindNearestRectToPoint(p, rootNode)) { obj = entry.Value; node = entry.Key; } if (node != null) { return(RemoveRectangle(obj, node)); } return(obj); }
public SpatialObj <T> RemoveObject(SpatialObj <T> rect) { PartitionNode <T> node = null; foreach (KeyValuePair <PartitionNode <T>, SpatialObj <T> > entry in FindNearestRectToPoint(rect.boundingBox.Center, rootNode)) { if (entry.Value.Equals(rect)) { node = entry.Key; } } if (node != null) { return(RemoveRectangle(rect, node)); } return(rect); }
/// <summary> /// /// </summary> /// <param name="initialNode"></param> /// <returns></returns> private PartitionNode GetClusterAsPartitionNode(INodeShape initialNode) { // Determine if the provided node is already // stored in our internal collection. If it // is, return it. if (_nodeToPartition.ContainsKey(initialNode)) { return(_nodeToPartition[initialNode]); } PartitionNode pn = new PartitionNode(_sourceGraph.Scope, "Partition" + (_currentId++).ToString()); _partitionNodes.Add(pn); Dictionary <INodeShape, bool> nodesInCluster = new Dictionary <INodeShape, bool>(); Queue <INodeShape> nodesToTriangulate = new Queue <INodeShape>(); nodesInCluster[initialNode] = true; nodesToTriangulate.Enqueue(initialNode); while (nodesToTriangulate.Count > 0) { List <INodeShape> tempList = FindTrianglesToAdd(nodesToTriangulate.Dequeue(), nodesInCluster); foreach (INodeShape nodeVM in tempList) { // Add the node view model to our queue nodesToTriangulate.Enqueue(nodeVM); } } // Loop over all the node view models in the dictionary foreach (NodeViewModelBase nodeVM in nodesInCluster.Keys) { // Add the node to the partition pn.AddNode(nodeVM); // Save the updated partition node _nodeToPartition[nodeVM] = pn; } return(pn); }
/// <summary> /// Handles the MouseLeftButtonDown event for dragging and dropping of the highlight polygon /// </summary> /// <param name="sender">The polygon that raised the event</param> /// <param name="e">Specifies properties about the mouse click</param> private void OnHighlightPolygonMouseLeftButtonUp(object sender, MouseButtonEventArgs e) { Polygon polygon = (Polygon)sender; PartitionNode partitionNode = _clusterPolygons[polygon]; double horizontalelta = _startMouseHorizontalPosition - (double)polygon.GetValue(Canvas.LeftProperty); double verticleDelta = _startMouseVerticalPosition - (double)polygon.GetValue(Canvas.TopProperty); // Update node positions foreach (NodeViewModelBase node in partitionNode.Nodes) { double x = node.Position.X; double y = node.Position.Y; x -= horizontalelta; y -= verticleDelta; node.Position = new Point(x, y); } _mouseCaptured = false; polygon.ReleaseMouseCapture(); }
public AtlasBuilder(IkonComposite sizes, int margin, Size bucketSize) { this.bucket = new PartitionNode(bucketSize); this.sizes = new Dictionary <string, Rectangle>(); this.margin = margin; var marginPoint = new Size(2 * margin, 2 * margin); foreach (var name in sizes.Keys) { var sizeData = sizes[name].To <IkonArray[]>(); var height = (sizeData[2].To <double[]>()[1] - sizeData[0].To <double[]>()[1]) * bucketSize.Height; var width = (sizeData[2].To <double[]>()[0] - sizeData[0].To <double[]>()[0]) * bucketSize.Width; var size = new Size((int)Math.Round(width) + 2 * margin, (int)Math.Round(height) + 2 * margin); var itemPosition = bucket.Add(size); if (!itemPosition.HasValue) { throw new Exception("Bucket is too small"); } this.sizes[name] = new Rectangle(itemPosition.Value, size); } }
private void ReorganizeNode(PartitionNode <T> node) { // After adding objects and creating new partitions, checks to see if any of the upper level objects can go deeper into the tree. Queue <PartitionNode <T> > all_nodes = new Queue <PartitionNode <T> >(); all_nodes.Enqueue(node); while (all_nodes.Count > 0) { List <SpatialObj <T> > rects_removed = new List <SpatialObj <T> >(); PartitionNode <T> current_node = all_nodes.Dequeue(); foreach (SpatialObj <T> rect in current_node.GetOverflowObjs()) { PartitionNode <T> deepest_field = FindContainingField(rect, current_node); if (!deepest_field.Equals(current_node)) { bool overflown = deepest_field.StoreRectangle(rect); rects_removed.Add(rect); } } if (rects_removed.Count > 0) { current_node.DeleteRectangles(rects_removed, true); } if (current_node.HasChildren()) { foreach (PartitionNode <T> child in current_node.GetChildren()) { all_nodes.Enqueue(child); } } } }
public PartitionNode <T> FindContainingField(SpatialObj <T> rect, PartitionNode <T> starting_node) { if (starting_node.IsPointInNode(rect.boundingBox.Center)) { bool contained_in_node = starting_node.IsObjectInNode(rect); if (contained_in_node && !starting_node.CanSink(rect)) { return(starting_node); } foreach (PartitionNode <T> child in starting_node.GetChildren()) { var potential_node = FindContainingField(rect, child); if (potential_node != null) { return(potential_node); } } if (contained_in_node) { return(starting_node); } } return(null); }
public PartitionFieldTreeStructure(Rectangle bounds, int capacity) { Bounds = bounds; Capacity = capacity; rootNode = new PartitionNode <T>(bounds, capacity, 0, new List <PartitionNode <T> >()); }
private void PartitionField(PartitionNode <T> node) { node.CreateChildren(); }
public Point?Add(Size itemSize) { if (this.size.Width < itemSize.Width || this.size.Height < itemSize.Height || this.filledUp) { return(null); } if (this.dividerPosition != NotSet) { var result = this.leftChild.Add(itemSize); if (result != null) { return(result); } result = this.rightChild.Add(itemSize); if (result != null) { if (this.isDividerVertical) { return(result.Value + new Size(this.dividerPosition, 0)); } else { return(result.Value + new Size(0, this.dividerPosition)); } } else { return(null); } } else if (this.size.Height > itemSize.Height) { this.isDividerVertical = false; this.dividerPosition = itemSize.Height; this.leftChild = new PartitionNode(new Size(this.size.Width, itemSize.Height)); this.rightChild = new PartitionNode(new Size(this.size.Width, this.size.Height - itemSize.Height)); var result = this.leftChild.Add(itemSize); if (result == null) { throw new Exception("Something is wrong with universe..."); } return(result); } else if (this.size.Width > itemSize.Width) { this.isDividerVertical = true; this.dividerPosition = itemSize.Width; this.leftChild = new PartitionNode(new Size(itemSize.Width, this.size.Height)); this.rightChild = new PartitionNode(new Size(this.size.Width - itemSize.Width, this.size.Height)); var result = this.leftChild.Add(itemSize); if (result == null) { throw new Exception("Something is wrong with universe..."); } return(result); } this.filledUp = true; return(new Point()); }
public AtlasBuilder(int margin, Size bucketSize) { this.bucket = new PartitionNode(bucketSize); this.margin = margin; }
private static object[] GetPartitionNodeDimensionAndPosition(GraphMapData graphMapData, PartitionNode partitionNode) { Point topLeft = new Point(double.MaxValue, double.MaxValue); Point bottomRight = new Point(double.MinValue, double.MinValue); // Loop through all node view models to get the bounding area foreach (NodeViewModelBase nodeViewModelBase in partitionNode.Nodes) { NodeMapData nodeMapData = graphMapData.Nodes[nodeViewModelBase.ParentNode.ID]; topLeft.X = Math.Min(topLeft.X, nodeMapData.Position.X - nodeMapData.Dimension.Width / 2D); topLeft.Y = Math.Min(topLeft.Y, nodeMapData.Position.Y - nodeMapData.Dimension.Height / 2D); bottomRight.X = Math.Max(bottomRight.X, nodeMapData.Position.X + nodeMapData.Dimension.Width / 2D); bottomRight.Y = Math.Max(bottomRight.Y, nodeMapData.Position.Y + nodeMapData.Dimension.Height / 2D); } // Set the new dimensions based on the calculation performed double width = Math.Max(bottomRight.X - topLeft.X, 1D); double height = Math.Max(bottomRight.Y - topLeft.Y, 1D); Size dimension = new Size(width, height); // get the center of the partitionNode Point position = new Point(topLeft.X + width / 2D, topLeft.Y + height / 2D); object[] result = new object[] { dimension, position }; return(result); }
/// <summary> /// Creates the polygons that represent the highlights for clustered data /// </summary> /// <param name="pn">The partition node containing nodes in the cluster</param> /// <returns>The polygon created for the highlight</returns> private Polygon CreateHighlightPolygon(PartitionNode pn) { PointCollection convexHull = ConvertListOfPointsToPointCollection(_cluster.CalculateConvexHullForCluster(pn)); return(DrawHighlightPolygon(convexHull)); }
public void SetNode(PartitionNode <T> n) { node = n; isNode = true; }