/// <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); }
public CompoundFDPLayoutAlgorithm( TGraph visitedGraph, IDictionary <TVertex, Size> vertexSizes, IDictionary <TVertex, Thickness> vertexBorders, IDictionary <TVertex, CompoundVertexInnerLayoutType> layoutTypes, IDictionary <TVertex, Point> vertexPositions, CompoundFDPLayoutParameters oldParameters) : base(visitedGraph, vertexPositions, oldParameters) { _vertexSizes = vertexSizes; _vertexBorders = vertexBorders; _layoutTypes = layoutTypes; if (VisitedGraph is ICompoundGraph <TVertex, TEdge> ) { _compoundGraph = new CompoundGraph <TVertex, TEdge>(VisitedGraph as ICompoundGraph <TVertex, TEdge>); } else { _compoundGraph = new CompoundGraph <TVertex, TEdge>(VisitedGraph); } }
public void RefineLayout(int iterations) { // Prepare state for algorithm. BidirectionalGraph<string, IEdge<string>> graph = new BidirectionalGraph<string, IEdge<string>>(false); Dictionary<string, Point> positions = new Dictionary<string, Point>(); // Anything to do? if (BayesianNetwork.VariablesOrdered.Any() == false) { this.Positions = new Dictionary<string, Point>(); IterationCount += iterations; return; } Random random = new Random(0); foreach (var rv in BayesianNetwork.VariablesOrdered) { graph.AddVertex(rv.Name); foreach (var child in rv.Children.Select(c => BayesianNetwork.GetVariable(c))) { graph.AddVertex(child.Name); graph.AddEdge(new Edge<string>(rv.Name, child.Name)); } // If we have no existing layout yet, lets try to prime the // alg by putting pure parents at top and pure children at // bottom. if (Positions.Count != 0) { // We have existing layout. Start with it but add slight // randomness. Point positionNoised; if (Positions.ContainsKey(rv.Name)) { positionNoised = Positions[rv.Name]; } else { positionNoised = new Point(); } positionNoised.X += (random.NextDouble() - 0.5) * 0.01; positionNoised.Y += (random.NextDouble() - 0.5) * 0.01; positions[rv.Name] = positionNoised; } } // Initialize algorithm. var layoutAlgorithms = new StandardLayoutAlgorithmFactory<string, IEdge<string>, IBidirectionalGraph<string, IEdge<string>>>(); var layoutContext = new LayoutContext<string, IEdge<string>, IBidirectionalGraph<string, IEdge<string>>>( graph, positions, _sizes, LayoutMode.Simple); ILayoutAlgorithm<string, IEdge<string>, IBidirectionalGraph<string, IEdge<string>>> layoutAlgorithm; var algorithm = this._options.Algorithm; // Hack: SugiyamaEfficient breaks if no edges. if (algorithm == NetworkLayoutOptions.AlgorithmEnum.KK || graph.Edges.Count() == 0) { var layoutParameters = new KKLayoutParameters(); layoutParameters.Height = 1000; layoutParameters.Width = 1000; layoutParameters.MaxIterations = iterations; layoutParameters.LengthFactor = 1.35; layoutParameters.K *= 10.1; layoutParameters.AdjustForGravity = false; layoutAlgorithm = layoutAlgorithms.CreateAlgorithm("KK", layoutContext, layoutParameters); } else if (algorithm == NetworkLayoutOptions.AlgorithmEnum.SugiyamaEfficient) { var layoutParameters = new EfficientSugiyamaLayoutParameters(); layoutParameters.MinimizeEdgeLength = true; layoutParameters.OptimizeWidth = true; layoutParameters.WidthPerHeight = 1.65; layoutParameters.VertexDistance = this._options.NodeSeparationTarget; layoutParameters.LayerDistance = 5.0; layoutAlgorithm = layoutAlgorithms.CreateAlgorithm("EfficientSugiyama", layoutContext, layoutParameters); } else if (algorithm == NetworkLayoutOptions.AlgorithmEnum.Sugiyama) { var layoutParameters = new SugiyamaLayoutParameters(); layoutParameters.MaxWidth = 1024; layoutParameters.VerticalGap = 1.0f; layoutParameters.DirtyRound = true; layoutAlgorithm = layoutAlgorithms.CreateAlgorithm("Sugiyama", layoutContext, layoutParameters); } else if (algorithm == NetworkLayoutOptions.AlgorithmEnum.CompoundFDP) { var layoutParameters = new CompoundFDPLayoutParameters(); layoutParameters.GravitationFactor = 0.8; layoutParameters.IdealEdgeLength = 30; layoutParameters.RepulsionConstant = 300; layoutAlgorithm = layoutAlgorithms.CreateAlgorithm("CompoundFDP", layoutContext, layoutParameters); } else { throw new InvalidOperationException("Unknown layout."); } // Compute. layoutAlgorithm.Compute(); // Store Results. this.Positions = layoutAlgorithm.VertexPositions.ToDictionary( (kvp) => kvp.Key, (kvp) => kvp.Value ); // Done. IterationCount += iterations; }