/// <summary> /// Redraws the graph with the specified layout type /// </summary> /// <param name="layout">Type of graph layout</param> /// <param name="isAnimated">Specifies whether or not to animate the graph when it's laid out</param> /// <param name="scope">Specifies the default graph scope</param> /// <param name="rootNode">Specifies the root node for layouts that require one</param> public void LayoutGraph(LayoutBase layout, bool isAnimated, string scope, NodeViewModelBase rootNode) { LayoutManager flyweight = LayoutManager.Instance; // Make sure we have a scope if (String.IsNullOrWhiteSpace(scope)) { scope = this.defaultComponentInstanceScope; } // Get the graph as a GraphMapData object GraphMapData graphMapData = GetGraphComponents(scope).ExportGraph(); // Execute the layout DispatcherHelper.UIDispatcher.BeginInvoke(() => { if (rootNode != null) { layout.CalculateLayout(graphMapData, rootNode.ParentNode); } else { layout.CalculateLayout(graphMapData); } System.Diagnostics.Debug.WriteLine(""); foreach (Delegate d in ContextMenuManager.Instance.GetContextMenuOpeningInvocationList()) { System.Diagnostics.Debug.WriteLine((d.Target as GraphComponents).Scope); } layout.PositionNodes(isAnimated, graphMapData); }); }
/// <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); }
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> /// 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; } } }
// GraphML output is not supported, this only outputs SnaglML internal override string ExportData(GraphMapData graph) { string graphMLDocument = string.Empty; using (TextWriter stringWriter = new StringWriter()) { XmlWriterSettings settings = new XmlWriterSettings { CloseOutput = true, ConformanceLevel = ConformanceLevel.Document, Encoding = Encoding.UTF8, Indent = true, IndentChars = " ", NewLineChars = Environment.NewLine, NewLineHandling = NewLineHandling.Replace }; using (XmlWriter writer = XmlWriter.Create(stringWriter, settings)) { WriteHeader(writer, graph); WriteGraphContent(writer, graph); WriteFooter(writer); writer.Flush(); } graphMLDocument = stringWriter.ToString(); } return(graphMLDocument); }
internal override GraphMapData ImportData(string jsonData) { TracWrapper tracWrapper = GetTracWrapper(jsonData); GraphMapData graph = TracGraphDataFormat.JsonToGraph(tracWrapper); return(graph); }
/// <summary> /// Converts a GraphMapData instance, with data from an import operation, /// to a Graph (GraphComponents) /// </summary> /// <param name="graph">The mapping data to be imported into the Graph</param> /// <param name="graphComponents">The Graph that data is being imported into</param> /// <param name="creationType">The specified CreationType</param> public static void ImportGraph(this GraphMapData graph, GraphComponents graphComponents, CreationType creationType) { // Ensure that valid mapping data was provided if (graph == null) { throw new ArgumentNullException("graph", "No mapping data was provided"); } graphComponents.NodeType = NodeTypes.Text; foreach (NodeMapData objNode in graph.GetNodes()) { if (objNode is IconNodeMapData) { graphComponents.NodeType = NodeTypes.Icon; break; } } // TODO edgedefault? // Loop over the node mapping objects foreach (NodeMapData objNode in graph.GetNodes()) { AddNode(graphComponents, creationType, objNode); } // Edges foreach (EdgeMapData objEdge in graph.GetEdges()) { AddEdge(graphComponents, creationType, objEdge); } }
private static GraphMapData GetClusteredGraph(GraphMapData graphMapData, GraphComponents graphComponents) { GraphMapData graphComponentsMapData = new GraphMapData(); IEnumerable <INodeShape> clusteredComponents = graphComponents.GetNodeViewModels(); foreach (PartitionNode clusteredComponent in clusteredComponents) { NodeMapData nodeMapData = new TextNodeMapData(clusteredComponent.ID); graphComponentsMapData.Add(nodeMapData); // Properties object[] dimensionAndPosition = GetPartitionNodeDimensionAndPosition(graphMapData, clusteredComponent); nodeMapData.Dimension = (Size)dimensionAndPosition[0]; nodeMapData.Position = (Point)dimensionAndPosition[1]; nodeMapData.IsHidden = clusteredComponent.IsHidden; IEnumerable <IEdge> clusteredComponentEdges = graphComponents.GetEdges(clusteredComponent); foreach (IEdge clusteredComponentEdge in clusteredComponentEdges) { EdgeMapData edgeMapData = new EdgeMapData(clusteredComponentEdge.Source.ID, clusteredComponentEdge.Target.ID); graphComponentsMapData.Add(edgeMapData); } } return(graphComponentsMapData); }
/// <summary> /// Resonsible for actually positioning the nodes. This will /// execute on the UI thread, once the background thread /// running the algorithm has completed. /// </summary> /// <param name="isAnimated">Indicates whether or not the layout should be animated</param> /// <param name="graphData">The object containing the graph data with the updated layout</param> public virtual void PositionNodes(bool isAnimated, GraphMapData graphData) { var nodes = graphData.Nodes; var nodeVMs = GraphManager.Instance.DefaultGraphComponentsInstance.NodeViewModels; foreach (NodeViewModelBase node in nodeVMs) { if (nodes.ContainsKey(node.ParentNode.ID)) { // Position or animated this nodeVM if (isAnimated) { node.AnimateTo(nodes[node.ParentNode.ID].Position); } else { node.Position = nodes[node.ParentNode.ID].Position; } } } // Publish appropriate events SnaglEventAggregator.DefaultInstance.GetEvent <LayoutExecutedEvent>().Publish(new LayoutEventArgs(LayoutName)); SnaglEventAggregator.DefaultInstance.GetEvent <UI.TimeConsumingTaskCompletedEvent>().Publish(new UI.TimeConsumingTaskEventArgs()); OnLayoutFinished(EventArgs.Empty); }
internal override GraphMapData ImportData(string anbData) { Chart chart = GetChart(anbData); GraphMapData graph = AnbToGraph(chart); return(graph); }
/// <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; } }
/// <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> public void CalculateLayout(GraphMapData graphData, INode rootNode) { // Publish appropriate events SnaglEventAggregator.DefaultInstance.GetEvent <LayoutExecutingEvent>().Publish(new LayoutEventArgs(LayoutName)); SnaglEventAggregator.DefaultInstance.GetEvent <UI.TimeConsumingTaskExecutingEvent>().Publish(new UI.TimeConsumingTaskEventArgs()); // Perform the layout PerformLayout(graphData, rootNode); }
/// <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; } }
private NodeMapData GetOppositeNode(GraphMapData graph, EdgeMapData edge, NodeMapData node) { if (edge.Source.Equals(node.Id)) { return(graph.Nodes[edge.Target]); } else { return(graph.Nodes[edge.Source]); } }
/// <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; } }
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); }
/// <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); }
/// <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) { BidirectionalGraph <string, WeightedEdge <string> > bGraph = GraphSharpUtility.GetBidirectionalGraph(graph); IDictionary <string, Size> nodeSizes = GraphSharpUtility.GetNodeSizes(graph); IDictionary <string, Vector> nodePositions = GraphSharpUtility.GetNodePositions(graph); CompoundFDPLayoutParameters compoundFDPLayoutParameters = new CompoundFDPLayoutParameters(); CompoundFDPLayoutAlgorithm <string, WeightedEdge <string>, BidirectionalGraph <string, WeightedEdge <string> > > compoundFDPLayoutAlgorithm = new CompoundFDPLayoutAlgorithm <string, WeightedEdge <string>, BidirectionalGraph <string, WeightedEdge <string> > >(bGraph, nodeSizes, null, null, nodePositions, compoundFDPLayoutParameters); compoundFDPLayoutAlgorithm.Compute(); GraphSharpUtility.SetNodePositions(graph, compoundFDPLayoutAlgorithm.VertexPositions); }
/// <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) { BidirectionalGraph <string, WeightedEdge <string> > bGraph = GraphSharpUtility.GetBidirectionalGraph(graph); IDictionary <string, Vector> nodePositions = GraphSharpUtility.GetNodePositions(graph); ISOMLayoutParameters isomLayoutParameters = new ISOMLayoutParameters(); ISOMLayoutAlgorithm <string, WeightedEdge <string>, BidirectionalGraph <string, WeightedEdge <string> > > isomLayoutAlgorithm = new ISOMLayoutAlgorithm <string, WeightedEdge <string>, BidirectionalGraph <string, WeightedEdge <string> > >(bGraph, nodePositions, isomLayoutParameters); isomLayoutAlgorithm.Compute(); GraphSharpUtility.SetNodePositions(graph, isomLayoutAlgorithm.VertexPositions); GraphSharpUtility.FSAOverlapRemoval(graph); }
/// <summary> /// Performs the actual layout algorithm. /// </summary> /// <param name="graph">The object containing the graph data</param> /// <param name="selectedNode">selected node</param> protected override void PerformLayout(GraphMapData graph, INode selectedNode) { BidirectionalGraph <string, WeightedEdge <string> > bGraph = GraphSharpUtility.GetBidirectionalGraph(graph); IDictionary <string, Vector> nodePositions = GraphSharpUtility.GetNodePositions(graph); IDictionary <string, Size> nodeSizes = GraphSharpUtility.GetNodeSizes(graph); BalloonTreeLayoutParameters balloonTreeLayoutParameters = new BalloonTreeLayoutParameters(); BalloonTreeLayoutAlgorithm <string, WeightedEdge <string>, BidirectionalGraph <string, WeightedEdge <string> > > balloonTreeLayoutAlgorithm = new BalloonTreeLayoutAlgorithm <string, WeightedEdge <string>, BidirectionalGraph <string, WeightedEdge <string> > >(bGraph, nodePositions, nodeSizes, balloonTreeLayoutParameters, selectedNode.ID); balloonTreeLayoutAlgorithm.Compute(); GraphSharpUtility.SetNodePositions(graph, balloonTreeLayoutAlgorithm.VertexPositions); }
/// <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) { AdjacencyGraph <string, Edge <string> > adjacencyGraph = GraphSharpUtility.GetAdjacencyGraph(graph); EfficientSugiyamaLayoutParameters efficientSugiyamaLayoutParameters = new EfficientSugiyamaLayoutParameters(); IDictionary <string, Vector> nodePositions = GraphSharpUtility.GetNodePositions(graph); IDictionary <string, Size> nodeSizes = GraphSharpUtility.GetNodeSizes(graph); EfficientSugiyamaLayoutAlgorithm <string, Edge <string>, AdjacencyGraph <string, Edge <string> > > efficientSugiyamaLayoutAlgorithm = new EfficientSugiyamaLayoutAlgorithm <string, Edge <string>, AdjacencyGraph <string, Edge <string> > >(adjacencyGraph, efficientSugiyamaLayoutParameters, nodePositions, nodeSizes); efficientSugiyamaLayoutAlgorithm.Compute(); GraphSharpUtility.SetNodePositions(graph, efficientSugiyamaLayoutAlgorithm.VertexPositions); }
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); }
private static ICollection <EdgeMapData> GetNodesEdges(GraphMapData graph, NodeMapData node) { ICollection <EdgeMapData> edges = new List <EdgeMapData>(); foreach (EdgeMapData edge in graph.GetEdges()) { if (edge.Source.Equals(node.Id) || edge.Target.Equals(node.Id)) { edges.Add(edge); } } return(edges); }
private static double GetNumberOfEdges(GraphMapData graph, NodeMapData node) { double numEdges = 0D; foreach (EdgeMapData edge in graph.GetEdges()) { if (edge.Source.Equals(node.Id) || edge.Target.Equals(node.Id)) { numEdges++; } } return(numEdges); }
/// <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) { // this ensures that the end result will remain the same across multiple runs // because each node will have the same starting position new GridLayout().CalculateLayout(graph); System.Diagnostics.Debug.WriteLine(""); foreach (Delegate d in ContextMenuManager.Instance.GetContextMenuOpeningInvocationList()) { System.Diagnostics.Debug.WriteLine((d.Target as GraphComponents).Scope); } // Create a GraphComponents instance that is a partitioned // representation of the original graph. Each node in this // graph is a partition node. GraphComponents connectedGraphComponents = GraphManager.Instance.GetConnectedComponents(GraphManager.Instance.DefaultGraphComponentsInstance.Scope); IEnumerable <INodeShape> connectedComponents = connectedGraphComponents.GetNodeViewModels(); System.Diagnostics.Debug.WriteLine(""); foreach (Delegate d in ContextMenuManager.Instance.GetContextMenuOpeningInvocationList()) { System.Diagnostics.Debug.WriteLine((d.Target as GraphComponents).Scope); } foreach (PartitionNode connectedComponent in connectedComponents) { using (GraphComponents connectedGraph = connectedComponent.GetGraph()) { LayoutByClusters(graph, connectedGraph); } } // Layout the overall graph GraphMapData connectedGraphMapData = GetClusteredGraph(graph, connectedGraphComponents); IDictionary <string, Point> originalPositions = GetOriginalPositions(connectedGraphMapData); GridLayout gridLayout = new GridLayout(); gridLayout.CalculateLayout(connectedGraphMapData); ApplyOffsetToSubGraphs(graph, connectedGraphComponents, originalPositions, connectedGraphMapData); connectedGraphComponents.Dispose(); System.Diagnostics.Debug.WriteLine(""); foreach (Delegate d in ContextMenuManager.Instance.GetContextMenuOpeningInvocationList()) { System.Diagnostics.Debug.WriteLine((d.Target as GraphComponents).Scope); } }
/// <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(); }
/// <summary> /// Exports the provided graph data /// </summary> /// <param name="scope">The scope of the data being exported</param> /// <returns>a string containing the exported data to be saved to /// a file if the export was successfull; otherwise null</returns> public string Export(string scope) { _logger.WriteLogEntry(LogLevel.DEBUG, "Export started", null, null); SnaglEventAggregator.DefaultInstance.GetEvent <DataExportingEvent>().Publish(new DataLoadedEventArgs(scope, CreationType.Exported)); //GraphMapData graph = MappingExtensions.ExportGraph(scope).ex; GraphMapData graph = GraphManager.Instance.GetGraphComponents(scope).ExportGraph(); // Call the abstract ExportData method string graphMLData = ExportData(graph); _logger.WriteLogEntry(LogLevel.DEBUG, "Export completed", null, null); SnaglEventAggregator.DefaultInstance.GetEvent <DataExportedEvent>().Publish(new DataLoadedEventArgs(scope, CreationType.Exported)); return(graphMLData); }
/// <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) { AdjacencyGraph <string, Edge <string> > adjacencyGraph = GraphSharpUtility.GetAdjacencyGraph(graph); IDictionary <string, Vector> nodePositions = GraphSharpUtility.GetNodePositions(graph); FreeFRLayoutParameters freeFRLayoutParameters = new FreeFRLayoutParameters() { IdealEdgeLength = 125D }; FRLayoutAlgorithm <string, Edge <string>, AdjacencyGraph <string, Edge <string> > > frLayoutAlgorithm = new FRLayoutAlgorithm <string, Edge <string>, AdjacencyGraph <string, Edge <string> > >(adjacencyGraph, nodePositions, freeFRLayoutParameters); frLayoutAlgorithm.Compute(); GraphSharpUtility.SetNodePositions(graph, frLayoutAlgorithm.VertexPositions); GraphSharpUtility.FSAOverlapRemoval(graph); }
/// <summary> /// Determines the ranking of the provided node /// </summary> /// <param name="graph">The object containing the graph data</param> /// <param name="node">The node to get the rank for</param> /// <returns>the rank for this node</returns> private double GetNodeRanking(GraphMapData graph, NodeMapData node) { // Check if we have a custom ranker to use. A custom ranker // is a custom delegate that is used to determine the nodes // rank. if (CustomRootRanker != null) { return(CustomRootRanker(node)); } else { // As a fallback, determine the nodes rank base on the // number of edges that it has return(GetNumberOfEdges(graph, node)); } }