/// <summary> /// Performs the actual layout algorithm. This will execute on a background thread. /// </summary> /// <param name="graphData">The object containing the graph data</param> /// <param name="rootNode">Root node</param> protected override Dictionary<INodeShape, NodePosition> PerformLayout(GraphMapData graphData, INode rootNode) { IList<NodeMapData> nodeVMs = new List<NodeMapData>(graphData.GetNodes()); IDictionary<INodeShape, NodePosition> nodes = new Dictionary<INodeShape, NodePosition>(); double currentAngle = 0; // Represents the current angle double radius = GetRadius(nodeVMs); // The computed radius of the circle // Loop through each visible node, perform the appropriate calculations, // then move it to the correct position on the graph. bool firstPass = true; foreach (NodeMapData nodeVM in nodeVMs) { // Determine the angle for the current node if (!firstPass) currentAngle += GetAngle(nodeVM, radius); //Calculate radians (radians = degrees * PI/180) double radians = currentAngle * Math.PI / 180; double x = Math.Cos(radians) * radius; double y = Math.Sin(radians) * radius; // We're no longer on the first pass firstPass = false; // Return the node position nodes.Add(nodeVM, new NodePosition(new Point(x, y), currentAngle)); } return nodes; }
/// <summary> /// Performs the actual layout algorithm. /// </summary> /// <param name="graph">The object containing the graph data</param> /// <param name="rootNode">Root node</param> protected override void PerformLayout(GraphMapData graph, INode rootNode) { double currentAngle = 0D; // Represents the current angle int numNodes = graph.Nodes.Count; double angle = GetAngle(numNodes); double radius = GetRadius(numNodes); // The computed radius of the circle // Loop through each node, perform the appropriate calculations, // then move it to the correct position on the graph. foreach (NodeMapData node in graph.GetNodes()) { if (rootNode != null && node.Id.Equals(rootNode.ID)) { Point position = new Point(0D, 0D); node.Position = position; } else { //Calculate radians double radians = Math.PI * currentAngle / 180D; double x = Math.Cos(radians) * radius; double y = Math.Sin(radians) * radius; Point position = new Point(x, y); node.Position = position; currentAngle += angle; } } }
/// <summary> /// Removes node overlap occurring in the input graph /// </summary> /// <param name="graph">GraphMapData</param> public static void FSAOverlapRemoval(GraphMapData graph) { ICollection<NodeMapData> nodes = graph.GetNodes(); IDictionary<string, Rect> rectangles = new Dictionary<string, Rect>(nodes.Count); foreach (NodeMapData node in nodes) { Point location = new Point(node.Position.X, node.Position.Y); Rect rect = new Rect(location, node.Dimension); rectangles[node.Id] = rect; } OverlapRemovalParameters overlapRemovalParameters = new OverlapRemovalParameters() { HorizontalGap = 0F, VerticalGap = 0F }; FSAAlgorithm<string> overlapRemoval = new FSAAlgorithm<string>(rectangles, overlapRemovalParameters); overlapRemoval.Compute(); foreach (NodeMapData node in nodes) { Rect rect = overlapRemoval.Rectangles[node.Id]; Point pos = new Point(rect.X, rect.Y); node.Position = pos; } }
public static Chart GraphToAnb(GraphMapData graph) { Chart chart = new Chart(); chart.chartItemCollection = new ChartItemCollection(); chart.chartItemCollection.chartItems = new Collection<ChartItem>(); foreach (IconNodeMapData node in graph.GetNodes()) { ChartItem chartItem = new ChartItem(); chart.chartItemCollection.chartItems.Add(chartItem); chartItem.attrLabel = node.Label; string hexBackgroundColor = String.Format("#{0:x2}{1:x2}{2:x2}{3:x2}", node.BackgroundColor.A, node.BackgroundColor.R, node.BackgroundColor.G, node.BackgroundColor.B); chartItem.ciStyle = new CIStyle(); chartItem.ciStyle.font = new Font(); chartItem.ciStyle.font.attrBackColour = hexBackgroundColor; chartItem.end = new End(); chartItem.end.entity = new Entity(); chartItem.end.entity.icon = new Icon(); chartItem.end.entity.icon.iconStyle = new IconStyle(); chartItem.attributeCollection = new AttributeCollection(); chartItem.attributeCollection.attributes = new Collection<Anb.Attribute>(); foreach (KeyValuePair<string, AttributeMapData> kvp in node.Attributes) { Anb.Attribute attribute = new Anb.Attribute(); chartItem.attributeCollection.attributes.Add(attribute); attribute.attrAttributeClass = kvp.Key; attribute.attrValue = kvp.Value.Value; } } foreach (EdgeMapData edge in graph.GetEdges()) { ChartItem chartItem = new ChartItem(); chart.chartItemCollection.chartItems.Add(chartItem); chartItem.link = new Link(); chartItem.link.attrEnd1Id = edge.Source; chartItem.link.attrEnd2Id = edge.Target; chartItem.link.linkStyle = new LinkStyle(); chartItem.link.linkStyle.attrType = edge.Label; } return chart; }
/// <summary> /// Performs the actual layout algorithm. /// </summary> /// <param name="graph">The object containing the graph data</param> /// <param name="rootNode">Root node</param> protected override void PerformLayout(GraphMapData graph, INode rootNode) { ICollection<NodeMapData> nodes = graph.GetNodes(); // First we determine the amount of space that we are dealing with double totalArea = 0D; foreach (NodeMapData node in nodes) { double nodeWidth = node.Dimension.Width + MARGIN.Left + MARGIN.Right; double nodeHeight = node.Dimension.Height + MARGIN.Top + MARGIN.Bottom; totalArea += nodeWidth * nodeHeight; } // TODO NEED TO DECOUPLE THIS GraphViewModel graphVM = ViewModelLocator.GraphDataStatic; // Calculate the bounding height and width of our square double boundingHeight = Math.Sqrt(totalArea); double boundingWidth = boundingHeight * (graphVM.Width / graphVM.Height); boundingHeight = boundingHeight / (graphVM.Width / graphVM.Height); //TODO: THE LINES ABOVE ARE THE ONLY REASON WE ARE COUPLED TO THE GRAPH VIEW MODEL double currentX = 0D; double currentY = 0D; double maxColumnWidth = 0D; double maxHeight = nodes.Max(node => node.Dimension.Height) + MARGIN.Top + MARGIN.Bottom; int columnSize = (int)Math.Round(boundingHeight / maxHeight); List<NodeMapData> nodesList = nodes.ToList<NodeMapData>(); nodesList.Sort(NodeSizeComparer); foreach (NodeMapData node in nodesList) { if (currentY > boundingHeight) { currentX += maxColumnWidth + MARGIN.Left + MARGIN.Right; maxColumnWidth = 0D; currentY = 0D; } maxColumnWidth = Math.Max(node.Dimension.Width, maxColumnWidth); Point position = new Point(currentX, currentY); node.Position = position; currentY += maxHeight; } }
/// <summary> /// Get adjacency graph from input graph /// </summary> /// <param name="graph">GraphMapData</param> /// <returns>AdjacencyGraph</returns> public static AdjacencyGraph<string, Edge<string>> GetAdjacencyGraph(GraphMapData graph) { ICollection<NodeMapData> nodes = graph.GetNodes(); AdjacencyGraph<string, Edge<string>> adjacencyGraph = new AdjacencyGraph<string, Edge<string>>(true, nodes.Count); foreach (NodeMapData node in nodes) { adjacencyGraph.AddVertex(node.Id); } foreach (EdgeMapData edge in graph.GetEdges()) { Edge<string> quickGraphEdge = new Edge<string>(edge.Source, edge.Target); adjacencyGraph.AddEdge(quickGraphEdge); } return adjacencyGraph; }
/// <summary> /// Performs the actual layout algorithm. /// </summary> /// <param name="graph">The object containing the graph data</param> /// <param name="rootNode">Root node</param> protected override void PerformLayout(GraphMapData graph, INode rootNode) { NodeMapData nodeToProcess = null; if (rootNode != null) { nodeToProcess = graph.Nodes[rootNode.ID]; } // Loop over the nodes until they have all been positioned while (processedNodes.Count != graph.Nodes.Count) { // Get the highest rank node that has not already been // positioned if (nodeToProcess == null) { double maxRanking = double.MinValue; // Loop over the nodes looking for the highest ranked one foreach (NodeMapData node in graph.GetNodes()) { double currentRanking = GetNodeRanking(graph, node); if (!processedNodes.Contains(node.Id) && (nodeToProcess == null || maxRanking < currentRanking)) { maxRanking = currentRanking; nodeToProcess = node; } } } // Position the node SaveNodePosition(nodeToProcess, maxXPosition, 0D); processedNodes.Add(nodeToProcess.Id); AddToLayer(nodeToProcess, 0); // Layer the graph CalulateSubtreePosition(graph, nodeToProcess, 1); nodeToProcess = null; } // reset for next run maxXPosition = 0D; processedNodes.Clear(); layers.Clear(); layerSpans.Clear(); }
private static IDictionary<string, Point> GetOriginalPositions(GraphMapData clusteredGraphMapData) { ICollection<NodeMapData> nodes = clusteredGraphMapData.GetNodes(); IDictionary<string, Point> originalPositions = new Dictionary<string, Point>(nodes.Count); foreach (NodeMapData node in nodes) { originalPositions[node.Id] = node.Position; } return originalPositions; }
private static void WriteHeader(XmlWriter writer, GraphMapData graph) { writer.WriteStartDocument(); writer.WriteStartElement("graphml", "http://graphml.graphdrawing.org/xmlns"); writer.WriteAttributeString("xmlns", "berico", string.Empty, BERICO_NAMESPACE_URI); writer.WriteAttributeString("xmlns", "xsi", string.Empty, "http://www.w3.org/2001/XMLSchema-instance"); writer.WriteAttributeString("xsi", "schemaLocation", string.Empty, "http://graphml.graphdrawing.org.xmlns/1.0/graphml.xsd"); if (graph.GetNodes().Count > 0) { bool graphHasIconNode = false; foreach (NodeMapData objNode in graph.GetNodes()) { if (objNode is IconNodeMapData) { graphHasIconNode = true; break; } } if (graphHasIconNode) { WritePropKey(writer, NODE_PROPERTY_PREFIX, "ImageSource", "node"); } WritePropKey(writer, NODE_PROPERTY_PREFIX, "Description", "node"); WritePropKey(writer, NODE_PROPERTY_PREFIX, "DisplayValue", "node"); WritePropKey(writer, NODE_PROPERTY_PREFIX, "Width", "node"); WritePropKey(writer, NODE_PROPERTY_PREFIX, "Height", "node"); WritePropKey(writer, NODE_PROPERTY_PREFIX, "Position", "node"); WritePropKey(writer, NODE_PROPERTY_PREFIX, "IsHidden", "node"); WritePropKey(writer, NODE_PROPERTY_PREFIX, "BackgroundColor", "node"); WritePropKey(writer, NODE_PROPERTY_PREFIX, "SelectionColor", "node"); } if (graph.GetEdges().Count > 0) { WritePropKey(writer, EDGE_PROPERTY_PREFIX, "DisplayValue", "edge"); WritePropKey(writer, EDGE_PROPERTY_PREFIX, "LabelTextUnderline", "edge"); WritePropKey(writer, EDGE_PROPERTY_PREFIX, "Thickness", "edge"); WritePropKey(writer, EDGE_PROPERTY_PREFIX, "Color", "edge"); WritePropKey(writer, EDGE_PROPERTY_PREFIX, "LabelBackgroundColor", "edge"); WritePropKey(writer, EDGE_PROPERTY_PREFIX, "LabelForegroundColor", "edge"); WritePropKey(writer, EDGE_PROPERTY_PREFIX, "LabelFontStyle", "edge"); WritePropKey(writer, EDGE_PROPERTY_PREFIX, "LabelFontWeight", "edge"); WritePropKey(writer, EDGE_PROPERTY_PREFIX, "LabelFont", "edge"); } ISet<string> seenAttributes = new HashSet<string>(); foreach (NodeMapData objNode in graph.GetNodes()) { foreach (KeyValuePair<string, AttributeMapData> kvp in objNode.Attributes) { if (seenAttributes.Add(kvp.Key)) { WriteAttrKey(writer, NODE_ATTRIBUTE_PREFIX, kvp.Value.Name, "node"); } } } seenAttributes.Clear(); foreach (EdgeMapData objEdge in graph.GetEdges()) { foreach (KeyValuePair<string, AttributeMapData> kvp in objEdge.Attributes) { if (seenAttributes.Add(kvp.Key)) { WriteAttrKey(writer, EDGE_ATTRIBUTE_PREFIX, kvp.Value.Name, "edge"); } } } }
private static void WriteGraphContent(XmlWriter writer, GraphMapData graph) { writer.WriteStartElement("graph"); writer.WriteAttributeString("id", "snagl_export_graph"); GraphType edgedefault = GraphType.Undirected; foreach (EdgeMapData objEdge in graph.GetEdges()) { if (objEdge.Type == EdgeType.Directed) { edgedefault = GraphType.Directed; break; } } writer.WriteAttributeString("edgedefault", edgedefault.ToString()); NodeTypes defaultNodeType = NodeTypes.Text; foreach (NodeMapData objNode in graph.GetNodes()) { if (objNode is IconNodeMapData) { defaultNodeType = NodeTypes.Icon; break; } } writer.WriteAttributeString("berico", "nodeType", BERICO_NAMESPACE_URI, defaultNodeType.ToString()); foreach (NodeMapData objNode in graph.GetNodes()) { WriteNode(writer, objNode); } foreach (EdgeMapData objEdge in graph.GetEdges()) { WriteEdge(writer, objEdge); } writer.WriteEndElement(); }
/// <summary> /// Get bidirectional graph from input graph /// </summary> /// <param name="graph">GraphMapData</param> /// <returns>BidirectionalGraph</returns> public static BidirectionalGraph<string, WeightedEdge<string>> GetBidirectionalGraph(GraphMapData graph) { ICollection<NodeMapData> nodes = graph.GetNodes(); BidirectionalGraph<string, WeightedEdge<string>> bidirectionalGraph = new BidirectionalGraph<string, WeightedEdge<string>>(true, nodes.Count); foreach (NodeMapData node in nodes) { bidirectionalGraph.AddVertex(node.Id); } foreach (EdgeMapData edge in graph.GetEdges()) { WeightedEdge<string> weightedEdge = new WeightedEdge<string>(edge.Source, edge.Target, edge.Weight); bidirectionalGraph.AddEdge(weightedEdge); } return bidirectionalGraph; }
/// <summary> /// Updates the input graph node positions with those from the input mapping /// </summary> /// <param name="graph">GraphMapData</param> /// <param name="vertexPositions">map of node id to vector</param> public static void SetNodePositions(GraphMapData graph, IDictionary<string, Vector> vertexPositions) { ICollection<NodeMapData> nodes = graph.GetNodes(); foreach (NodeMapData node in nodes) { Vector vPos = vertexPositions[node.Id]; Point pPos = new Point(vPos.X, vPos.Y); node.Position = pPos; } }
/// <summary> /// Gets a mapping of node id to size /// </summary> /// <param name="graph">GraphMapData</param> /// <returns>map of node id to size</returns> public static IDictionary<string, Size> GetNodeSizes(GraphMapData graph) { ICollection<NodeMapData> nodes = graph.GetNodes(); IDictionary<string, Size> nodeSizes = new Dictionary<string, Size>(nodes.Count); foreach (NodeMapData node in nodes) { nodeSizes[node.Id] = node.Dimension; } return nodeSizes; }
/// <summary> /// Gets a mapping of node id to vector /// </summary> /// <param name="graph">GraphMapData</param> /// <returns>map of node id to vector</returns> public static IDictionary<string, Vector> GetNodePositions(GraphMapData graph) { ICollection<NodeMapData> nodes = graph.GetNodes(); IDictionary<string, Vector> nodePositions = new Dictionary<string, Vector>(nodes.Count); foreach (NodeMapData node in nodes) { Vector vPos = new Vector(node.Position.X, node.Position.Y); nodePositions[node.Id] = vPos; } return nodePositions; }