private double EvaluateEdgeLength( CompoundGraph <object, IEdge <object> > compoundGraph, CompoundFDPLayoutAlgorithm <object, IEdge <object>, CompoundGraph <object, IEdge <object> > > algorithm, Dictionary <object, Size> sizes, double idealEdgeLength, double nestingFactor) { double edgeLengthError = 0.0; foreach (var edge in compoundGraph.Edges) { var uPos = algorithm.VertexPositions[edge.Source]; var vPos = algorithm.VertexPositions[edge.Target]; var uSize = sizes[edge.Source]; var vSize = sizes[edge.Target]; var uPoint = LayoutUtil.GetClippingPoint(uSize, uPos, vPos); var vPoint = LayoutUtil.GetClippingPoint(vSize, vPos, uPos); double length = (uPoint - vPoint).Length; bool isInterEdge = compoundGraph.GetParent(edge.Source) != compoundGraph.GetParent(edge.Target); var iel = isInterEdge ? idealEdgeLength * (algorithm.LevelOfVertex(edge.Source) + algorithm.LevelOfVertex(edge.Target) + 1) * nestingFactor : idealEdgeLength; double err = Math.Pow(length - iel, 2); edgeLengthError += err; } return(edgeLengthError); }
private static double EvaluateEdgeLength( [NotNull] ICompoundGraph <object, IEdge <object> > compoundGraph, [NotNull] CompoundFDPLayoutAlgorithm <object, IEdge <object>, CompoundGraph <object, IEdge <object> > > algorithm, [NotNull] IReadOnlyDictionary <object, Size> verticesSizes, double idealEdgeLength, double nestingFactor) { double edgeLengthError = 0.0; foreach (IEdge <object> edge in compoundGraph.Edges) { Point uPos = algorithm.VerticesPositions[edge.Source]; Point vPos = algorithm.VerticesPositions[edge.Target]; Size uSize = verticesSizes[edge.Source]; Size vSize = verticesSizes[edge.Target]; Point uPoint = LayoutUtils.GetClippingPoint(uSize, uPos, vPos); Point vPoint = LayoutUtils.GetClippingPoint(vSize, vPos, uPos); double length = (uPoint - vPoint).Length; bool isInterEdge = compoundGraph.GetParent(edge.Source) != compoundGraph.GetParent(edge.Target); double iel = isInterEdge ? idealEdgeLength * (algorithm.LevelOfVertex(edge.Source) + algorithm.LevelOfVertex(edge.Target) + 1) * nestingFactor : idealEdgeLength; double error = Math.Pow(length - iel, 2); edgeLengthError += error; } return(edgeLengthError); }
/// <summary> /// Uses GraphSharp CompoundFDPLayoutAlgorithm, i.e. a force-based algorithm. /// /// Pretty effective - for not too complicated graphs it is capable of providing flawless solution. /// </summary> /// <returns>raw set of coordinates of vertices</returns> private IDictionary <string, Point> Create4() { var algo4 = new CompoundFDPLayoutAlgorithm <string, Edge <string>, BidirectionalGraph <string, Edge <string> > >( graph, vertexSizes, vertexBorders, new Dictionary <string, CompoundVertexInnerLayoutType>()); algo4.Compute(); //while (algo4.State != ComputationState.Finished) // Thread.Sleep(250); return(algo4.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, 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); }
private int EvaluateEdgeCrossing( CompoundGraph <object, IEdge <object> > compoundGraph, CompoundFDPLayoutAlgorithm <object, IEdge <object>, CompoundGraph <object, IEdge <object> > > algorithm, Dictionary <object, Size> sizes) { int crossings = 0; foreach (var edge in compoundGraph.Edges) { var uPos1 = algorithm.VertexPositions[edge.Source]; var vPos1 = algorithm.VertexPositions[edge.Target]; var uSize1 = sizes[edge.Source]; var vSize1 = sizes[edge.Target]; var uPoint1 = LayoutUtil.GetClippingPoint(uSize1, uPos1, vPos1); var vPoint1 = LayoutUtil.GetClippingPoint(vSize1, vPos1, uPos1); foreach (var edge2 in compoundGraph.Edges) { if (edge == edge2) { continue; } var uPos2 = algorithm.VertexPositions[edge.Source]; var vPos2 = algorithm.VertexPositions[edge.Target]; var uSize2 = sizes[edge.Source]; var vSize2 = sizes[edge.Target]; var uPoint2 = LayoutUtil.GetClippingPoint(uSize2, uPos2, vPos2); var vPoint2 = LayoutUtil.GetClippingPoint(vSize2, vPos2, uPos2); Vector v1 = (vPoint1 - uPoint1); Vector v2 = (vPoint2 - uPoint2); if (v1 == v2 || v1 == -v2) { continue; //parallel edges } var t2 = (uPoint1.Y - uPoint2.Y + (uPoint2.X - uPoint1.X) * v1.Y / v1.X) / (v2.Y - v2.X * v1.Y / v1.X); var t1 = (uPoint2.X - uPoint1.X + t2 * v2.X) / v1.X; var p = uPoint1 + t1 * v1; var b1 = t1 > 0 && (p - uPoint1).Length < (vPoint1 - uPoint1).Length; var b2 = t2 > 0 && (p - uPoint2).Length < (vPoint2 - uPoint2).Length; if (b1 && b2) { crossings++; } } } return(crossings); }
private static void EvaluateNodeDistances( [NotNull] ICompoundGraph <object, IEdge <object> > compoundGraph, [NotNull] CompoundFDPLayoutAlgorithm <object, IEdge <object>, CompoundGraph <object, IEdge <object> > > algorithm, [NotNull] IReadOnlyDictionary <object, Size> verticesSizes, out double minimalMinDistance, out double averageMinDistance, out double maximalMinDistance) { minimalMinDistance = 0.0; averageMinDistance = 0.0; maximalMinDistance = 0.0; foreach (HashSet <object> level in algorithm.Levels) { foreach (object u in level) { double m = double.PositiveInfinity; foreach (object v in level) { if (ReferenceEquals(u, v) || compoundGraph.GetParent(u) != compoundGraph.GetParent(v)) { continue; } Point uPoint = LayoutUtils.GetClippingPoint( verticesSizes[u], algorithm.VerticesPositions[u], algorithm.VerticesPositions[v]); Point vPoint = LayoutUtils.GetClippingPoint( verticesSizes[v], algorithm.VerticesPositions[v], algorithm.VerticesPositions[u]); double distance = (uPoint - vPoint).Length; m = Math.Min(m, distance); } if (double.IsPositiveInfinity(m)) { continue; } minimalMinDistance = Math.Min(minimalMinDistance, m); averageMinDistance += m; maximalMinDistance = Math.Max(maximalMinDistance, m); } } }
public void Constructor() { var graph = new BidirectionalGraph <string, Edge <string> >(); var verticesPositions = new Dictionary <string, Point>(); var verticesSizes = new Dictionary <string, Size>(); var verticesThicknesses = new Dictionary <string, Thickness>(); var verticesTypes = new Dictionary <string, CompoundVertexInnerLayoutType>(); var algorithm = new CompoundFDPLayoutAlgorithm <string, Edge <string>, IBidirectionalGraph <string, Edge <string> > >(graph, verticesSizes, verticesThicknesses, verticesTypes); AssertFDPAlgorithmProperties(algorithm, graph); algorithm = new CompoundFDPLayoutAlgorithm <string, Edge <string>, IBidirectionalGraph <string, Edge <string> > >(graph, verticesSizes, verticesThicknesses, verticesTypes); algorithm.IterationEnded += (sender, args) => { }; AssertFDPAlgorithmProperties(algorithm, graph, expectedReportIterationEnd: true); algorithm = new CompoundFDPLayoutAlgorithm <string, Edge <string>, IBidirectionalGraph <string, Edge <string> > >(graph, verticesSizes, verticesThicknesses, verticesTypes); algorithm.ProgressChanged += (sender, args) => { }; AssertFDPAlgorithmProperties(algorithm, graph, expectedReportProgress: true); algorithm = new CompoundFDPLayoutAlgorithm <string, Edge <string>, IBidirectionalGraph <string, Edge <string> > >(graph, verticesSizes, verticesThicknesses, verticesTypes); algorithm.IterationEnded += (sender, args) => { }; algorithm.ProgressChanged += (sender, args) => { }; AssertFDPAlgorithmProperties(algorithm, graph, expectedReportIterationEnd: true, expectedReportProgress: true); algorithm = new CompoundFDPLayoutAlgorithm <string, Edge <string>, IBidirectionalGraph <string, Edge <string> > >(graph, verticesPositions, verticesSizes, verticesThicknesses, verticesTypes); AssertFDPAlgorithmProperties(algorithm, graph, verticesPositions); var parameters = new CompoundFDPLayoutParameters(); algorithm = new CompoundFDPLayoutAlgorithm <string, Edge <string>, IBidirectionalGraph <string, Edge <string> > >(graph, verticesSizes, verticesThicknesses, verticesTypes, parameters); AssertFDPAlgorithmProperties(algorithm, graph, p: parameters); algorithm = new CompoundFDPLayoutAlgorithm <string, Edge <string>, IBidirectionalGraph <string, Edge <string> > >(graph, verticesPositions, verticesSizes, verticesThicknesses, verticesTypes, parameters); AssertFDPAlgorithmProperties(algorithm, graph, verticesPositions, p: parameters); #region Local function void AssertFDPAlgorithmProperties <TVertex, TEdge, TGraph>( CompoundFDPLayoutAlgorithm <TVertex, TEdge, TGraph> algo, TGraph g, IDictionary <TVertex, Point> pos = null, bool expectedReportIterationEnd = false, bool expectedReportProgress = false, CompoundFDPLayoutParameters p = null) where TVertex : class
private static void CheckCompoundFDPLayout <TVertex, TEdge, TGraph>( [NotNull] IBidirectionalGraph <TVertex, TEdge> graph, [NotNull] CompoundFDPLayoutAlgorithm <TVertex, TEdge, TGraph> algorithm) where TVertex : class where TEdge : IEdge <TVertex> where TGraph : IBidirectionalGraph <TVertex, TEdge> { CollectionAssert.AreEquivalent(graph.Vertices, algorithm.Levels.SelectMany(level => level)); if (graph is ICompoundGraph <TVertex, TEdge> compoundGraph) { CollectionAssert.AreEquivalent(compoundGraph.CompoundVertices, algorithm.InnerCanvasSizes.Keys); } else { CollectionAssert.IsEmpty(algorithm.InnerCanvasSizes.Keys); } }
private void EvaluateNodeDistances( CompoundGraph <object, IEdge <object> > compoundGraph, CompoundFDPLayoutAlgorithm <object, IEdge <object>, CompoundGraph <object, IEdge <object> > > algorithm, Dictionary <object, Size> sizes, out double minimalMinDistance, out double averageMinDistance, out double maximalMinDistance) { minimalMinDistance = 0.0; averageMinDistance = 0.0; maximalMinDistance = 0.0; double count = 0; foreach (var level in algorithm.Levels) { foreach (var u in level) { double m = double.PositiveInfinity; foreach (var v in level) { if (u == v || compoundGraph.GetParent(u) != compoundGraph.GetParent(v)) { continue; } var uPoint = LayoutUtil.GetClippingPoint(sizes[u], algorithm.VertexPositions[u], algorithm.VertexPositions[v]); var vPoint = LayoutUtil.GetClippingPoint(sizes[v], algorithm.VertexPositions[v], algorithm.VertexPositions[u]); double distance = (uPoint - vPoint).Length; m = Math.Min(m, distance); } if (double.IsPositiveInfinity(m)) { continue; } minimalMinDistance = Math.Min(minimalMinDistance, m); averageMinDistance += m; count++; maximalMinDistance = Math.Max(maximalMinDistance, m); } } }
private static double EvaluateNodeOverlaps( [NotNull] ICompoundGraph <object, IEdge <object> > compoundGraph, [NotNull] CompoundFDPLayoutAlgorithm <object, IEdge <object>, CompoundGraph <object, IEdge <object> > > algorithm, [NotNull] IDictionary <object, Size> verticesSizes) { double overlapArea = 0.0; foreach (HashSet <object> level in algorithm.Levels) { foreach (object u in level) { foreach (object v in level) { if (ReferenceEquals(u, v) || compoundGraph.GetParent(u) != compoundGraph.GetParent(v)) { continue; } Point uPosition = algorithm.VerticesPositions[u]; Point vPosition = algorithm.VerticesPositions[v]; Size uSize = verticesSizes[u]; Size vSize = verticesSizes[v]; var uRect = new Rect(uPosition, uSize); var vRect = new Rect(vPosition, vSize); // Get the overlap size uRect.Intersect(vRect); if (double.IsNegativeInfinity(uRect.Width) || double.IsNegativeInfinity(uRect.Height)) { continue; } overlapArea += uRect.Width * uRect.Height; } } } return(overlapArea); }
private double EvaluateNodeOverlaps( CompoundGraph <object, IEdge <object> > compoundGraph, CompoundFDPLayoutAlgorithm <object, IEdge <object>, CompoundGraph <object, IEdge <object> > > algorithm, IDictionary <object, Size> vertexSizes) { double overlapArea = 0.0; foreach (var level in algorithm.Levels) { foreach (var u in level) { foreach (var v in level) { if (u == v || compoundGraph.GetParent(u) != compoundGraph.GetParent(v)) { continue; } var uSize = vertexSizes[u]; var vSize = vertexSizes[v]; var uPosition = algorithm.VertexPositions[u]; var vPosition = algorithm.VertexPositions[v]; var uRect = new Rect(uPosition, uSize); var vRect = new Rect(vPosition, vSize); //get the overlap size uRect.Intersect(vRect); if (double.IsNegativeInfinity(uRect.Width) || double.IsNegativeInfinity(uRect.Height)) { continue; } overlapArea += uRect.Width * uRect.Height; } } } return(overlapArea); }
private Size EvaluateCanvasSize( CompoundGraph <object, IEdge <object> > compoundGraph, CompoundFDPLayoutAlgorithm <object, IEdge <object>, CompoundGraph <object, IEdge <object> > > algorithm, Dictionary <object, Size> sizes) { Point topLeft = new Point(double.PositiveInfinity, double.PositiveInfinity); Point bottomRight = new Point(double.NegativeInfinity, double.NegativeInfinity); foreach (var v in compoundGraph.Vertices) { var pos = algorithm.VertexPositions[v]; var size = sizes[v]; topLeft.X = Math.Min(topLeft.X, pos.X - size.Width / 2.0); topLeft.Y = Math.Min(topLeft.Y, pos.Y - size.Height / 2.0); bottomRight.X = Math.Max(bottomRight.X, pos.X + size.Width / 2.0); bottomRight.Y = Math.Max(bottomRight.Y, pos.Y + size.Height / 2.0); } var sizeVector = bottomRight - topLeft; return(new Size(sizeVector.X, sizeVector.Y)); }
private void ShowGraph(int graphIndex) { CompoundGraph <object, IEdge <object> > g = graphs[graphIndex]; _rectDict.Clear(); _lineDict.Clear(); lc.Children.Clear(); var origo = new Ellipse(); origo.Width = 100; origo.Height = 100; origo.Fill = Brushes.Black; origo.OpacityMask = new RadialGradientBrush(Colors.Black, Colors.Transparent); Canvas.SetLeft(origo, -5); Canvas.SetTop(origo, -5); lc.Children.Add(origo); var sizes = new Dictionary <object, Size>(); var borders = new Dictionary <object, Thickness>(); var layoutType = new Dictionary <object, CompoundVertexInnerLayoutType>(); var s = new Size(20, 20); foreach (var v in g.SimpleVertices) { sizes[v] = s; } var b = new Thickness(5, 10, 5, 5); foreach (var v in g.CompoundVertices) { sizes[v] = new Size(); borders[v] = b; layoutType[v] = CompoundVertexInnerLayoutType.Automatic; } var worker = new BackgroundWorker(); worker.WorkerReportsProgress = true; worker.DoWork += (sender, e) => { var layoutAlgorithm = new CompoundFDPLayoutAlgorithm <object, IEdge <object>, ICompoundGraph <object, IEdge <object> > >( g, sizes, borders, layoutType, null, parameters); layoutAlgorithm.IterationEnded += (o, evt) => { var args = evt as TestingCompoundLayoutIterationEventArgs <object, IEdge <object>, TestingCompoundVertexInfo, object>; var positions = args.VertexPositions; var innerSizes = (args as ICompoundLayoutIterationEventArgs <object>).InnerCanvasSizes; var vertexInfos = args.VertexInfos; Dispatcher.Invoke(new Action(delegate { var pDict = new Dictionary <object, Point>(); var compoundVerticesToCheck = new Queue <object>(); var compoundVertices = new List <object>(); var root = g.CompoundVertices.Where( cv => g.GetParent(cv) == null); foreach (var r in root) { compoundVerticesToCheck.Enqueue(r); } while (compoundVerticesToCheck.Count > 0) { var next = compoundVerticesToCheck.Dequeue(); if (!g.IsCompoundVertex(next)) { continue; } compoundVertices.Add(next); foreach ( var childrenVertex in g.GetChildrenVertices(next)) { compoundVerticesToCheck.Enqueue( childrenVertex); } } //draw the compound vertices foreach (var v in compoundVertices) { var size = innerSizes[v]; size.Width += b.Left + b.Right; size.Height += b.Top + b.Bottom; var pos = positions[v]; pDict[v] = pos; AddRect(v, pos, size); } //draw the simple vertices foreach (var v in g.SimpleVertices) { var pos = positions[v]; pDict[v] = pos; AddRect(v, pos, s); } //draw the simple edges foreach (var edge in g.Edges) { var pos1 = pDict[edge.Source]; var pos2 = pDict[edge.Target]; AddLine(edge, pos1, pos2, true); } //draw the containment edges /*foreach (var v in g.CompoundVertices) * { * var pos1 = pDict[v]; * foreach (var c in g.GetChildrenVertices(v)) * { * var pos2 = pDict[c]; * AddLine(c, pos1, pos2, false); * } * }*/ //draw the lines of the forces foreach (var forceLine in _forceLines) { lc.Children.Remove(forceLine); } var springColor = Brushes.Orange; var repulsionColor = Brushes.Red; var gravityColor = Brushes.Green; var applicationColor = Brushes.Yellow; foreach (var kvp in vertexInfos) { var line = CreateLine(pDict[kvp.Key], kvp.Value.SpringForce, springColor); lc.Children.Add(line); _forceLines.Add(line); line = CreateLine(pDict[kvp.Key], kvp.Value.RepulsionForce, repulsionColor); lc.Children.Add(line); _forceLines.Add(line); line = CreateLine(pDict[kvp.Key], kvp.Value.GravityForce, gravityColor); lc.Children.Add(line); _forceLines.Add(line); line = CreateLine(pDict[kvp.Key], kvp.Value.ApplicationForce, applicationColor); lc.Children.Add(line); _forceLines.Add(line); } //set the position of the gravity center Animate(origo, Canvas.LeftProperty, args.GravitationCenter.X - origo.Width / 2.0, animationDuration); Animate(origo, Canvas.TopProperty, args.GravitationCenter.Y - origo.Height / 2.0, animationDuration); txtMessage.Text = args.Message; })); do { Thread.Sleep((int)animationDuration.TimeSpan.TotalMilliseconds); } while (_paused); }; layoutAlgorithm.Compute(); }; worker.RunWorkerAsync(); }
public void Evaluate(int SpreadMax) { if (FBuild[0] || (pd.InputChanged && init)) { graph.Clear(); VSize.Clear(); VThickness.Clear(); VType.Clear(); VPos.Clear(); VCache.Clear(); for (int i = 0; i < FVertices.SliceCount; i++) { graph.AddVertex(FVertices[i]); VSize.Add(FVertices[i], new Size(FVSize[i], FVSize[i])); VThickness.Add(FVertices[i], new Thickness(1.0)); VType.Add(FVertices[i], FVType[i]); VPos.Add(FVertices[i], new Point(FVPos[i].x, FVPos[i].y)); VCache.Add(FVertices[i]); } for (int i = 0; i < Math.Max(FEdgeFrom.SliceCount, FEdgeTo.SliceCount); i++) { graph.AddEdge(new Edge <string>(FEdgeFrom[i], FEdgeTo[i])); } var cparams = new CompoundFDPLayoutParameters(); foreach (var prop in typeof(CompoundFDPLayoutParameters).GetProperties()) { var input = pd.InputPins[prop.Name].Spread[0]; if (!(input.ToString().StartsWith("0") && input.ToString().EndsWith("0"))) { prop.SetValue(cparams, pd.InputPins[prop.Name].Spread[0]); } } layout = new CompoundFDPLayoutAlgorithm <string, IEdge <string>, CompoundGraph <string, IEdge <string> > >(graph, VSize, VThickness, VType, VPos, cparams); foreach (var prop in typeof(CompoundFDPLayoutParameters).GetProperties()) { var input = pd.InputPins[prop.Name].Spread[0]; if (!(input.ToString().StartsWith("0") && input.ToString().EndsWith("0"))) { prop.SetValue(layout.Parameters, pd.InputPins[prop.Name].Spread[0]); } } layout.Finished += (sender, args) => { FPosOut.SliceCount = VCache.Count; for (int i = 0; i < VCache.Count; i++) { var point = layout.VertexPositions[VCache[i]]; FPosOut[i] = new Vector2D(point.X, point.Y); } }; if (FAsync[0]) { Task.Run(() => { layout.Compute(); }); } else { layout.Compute(); } init = true; } if (layout != null) { FState[0] = layout.State.ToString(); } }
public void StandardFactory() { var positions = new Dictionary <TestVertex, Point>(); var sizes = new Dictionary <TestVertex, Size>(); var borders = new Dictionary <TestVertex, Thickness>(); var layoutTypes = new Dictionary <TestVertex, CompoundVertexInnerLayoutType>(); var graph = new BidirectionalGraph <TestVertex, Edge <TestVertex> >(); var simpleContext = new LayoutContext <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > >( graph, positions, sizes, LayoutMode.Simple); var compoundContext1 = new LayoutContext <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > >( graph, positions, sizes, LayoutMode.Compound); var compoundContext2 = new CompoundLayoutContext <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > >( graph, positions, sizes, LayoutMode.Compound, borders, layoutTypes); var nullGraphContext = new LayoutContext <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > >( null, positions, sizes, LayoutMode.Simple); var factory = new StandardLayoutAlgorithmFactory <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > >(); CollectionAssert.AreEqual( new[] { "Circular", "Tree", "FR", "BoundedFR", "KK", "ISOM", "LinLog", "Sugiyama", "CompoundFDP", "Random" }, factory.AlgorithmTypes); Assert.IsNull( factory.CreateAlgorithm( string.Empty, simpleContext, new CircularLayoutParameters())); Assert.IsNull( factory.CreateAlgorithm( "NotExist", simpleContext, new CircularLayoutParameters())); Assert.IsNull( factory.CreateAlgorithm( "Circular", nullGraphContext, new CircularLayoutParameters())); Assert.IsInstanceOf <CircularLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > > >( factory.CreateAlgorithm( "Circular", simpleContext, new CircularLayoutParameters())); Assert.IsInstanceOf <SimpleTreeLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > > >( factory.CreateAlgorithm( "Tree", simpleContext, new SimpleTreeLayoutParameters())); Assert.IsInstanceOf <FRLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > > >( factory.CreateAlgorithm( "FR", simpleContext, new FreeFRLayoutParameters())); Assert.IsInstanceOf <FRLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > > >( factory.CreateAlgorithm( "BoundedFR", simpleContext, new BoundedFRLayoutParameters())); Assert.IsInstanceOf <KKLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > > >( factory.CreateAlgorithm( "KK", simpleContext, new KKLayoutParameters())); Assert.IsInstanceOf <ISOMLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > > >( factory.CreateAlgorithm( "ISOM", simpleContext, new ISOMLayoutParameters())); Assert.IsInstanceOf <LinLogLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > > >( factory.CreateAlgorithm( "LinLog", simpleContext, new LinLogLayoutParameters())); Assert.IsInstanceOf <SugiyamaLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > > >( factory.CreateAlgorithm( "Sugiyama", simpleContext, new SugiyamaLayoutParameters())); Assert.IsInstanceOf <CompoundFDPLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > > >( factory.CreateAlgorithm( "CompoundFDP", simpleContext, new CompoundFDPLayoutParameters())); Assert.IsInstanceOf <RandomLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > > >( factory.CreateAlgorithm( "Random", simpleContext, new RandomLayoutParameters())); Assert.IsNull( factory.CreateAlgorithm( "CompoundFDP", compoundContext1, new CompoundFDPLayoutParameters())); Assert.IsNull( factory.CreateAlgorithm( "Circular", compoundContext2, new CompoundFDPLayoutParameters())); Assert.IsInstanceOf <CompoundFDPLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > > >( factory.CreateAlgorithm( "CompoundFDP", compoundContext2, new CompoundFDPLayoutParameters())); var testParameters = new TestLayoutParameters(); var circularParameters = new CircularLayoutParameters(); ILayoutParameters createdParameters = factory.CreateParameters(string.Empty, circularParameters); Assert.IsNull(createdParameters); createdParameters = factory.CreateParameters("NotExist", circularParameters); Assert.IsNull(createdParameters); createdParameters = factory.CreateParameters("Circular", null); Assert.IsInstanceOf <CircularLayoutParameters>(createdParameters); Assert.AreNotSame(circularParameters, createdParameters); createdParameters = factory.CreateParameters("Circular", testParameters); Assert.IsInstanceOf <CircularLayoutParameters>(createdParameters); Assert.AreNotSame(testParameters, createdParameters); createdParameters = factory.CreateParameters("Circular", circularParameters); Assert.IsInstanceOf <CircularLayoutParameters>(createdParameters); Assert.AreNotSame(circularParameters, createdParameters); var treeParameters = new SimpleTreeLayoutParameters(); createdParameters = factory.CreateParameters("Tree", null); Assert.IsInstanceOf <SimpleTreeLayoutParameters>(createdParameters); Assert.AreNotSame(treeParameters, createdParameters); createdParameters = factory.CreateParameters("Tree", testParameters); Assert.IsInstanceOf <SimpleTreeLayoutParameters>(createdParameters); Assert.AreNotSame(testParameters, createdParameters); createdParameters = factory.CreateParameters("Tree", treeParameters); Assert.IsInstanceOf <SimpleTreeLayoutParameters>(createdParameters); Assert.AreNotSame(treeParameters, createdParameters); var frParameters = new FreeFRLayoutParameters(); createdParameters = factory.CreateParameters("FR", null); Assert.IsInstanceOf <FreeFRLayoutParameters>(createdParameters); Assert.AreNotSame(frParameters, createdParameters); createdParameters = factory.CreateParameters("FR", testParameters); Assert.IsInstanceOf <FreeFRLayoutParameters>(createdParameters); Assert.AreNotSame(treeParameters, createdParameters); createdParameters = factory.CreateParameters("FR", frParameters); Assert.IsInstanceOf <FreeFRLayoutParameters>(createdParameters); Assert.AreNotSame(frParameters, createdParameters); var boundedFrParameters = new BoundedFRLayoutParameters(); createdParameters = factory.CreateParameters("BoundedFR", null); Assert.IsInstanceOf <BoundedFRLayoutParameters>(createdParameters); Assert.AreNotSame(boundedFrParameters, createdParameters); createdParameters = factory.CreateParameters("BoundedFR", testParameters); Assert.IsInstanceOf <BoundedFRLayoutParameters>(createdParameters); Assert.AreNotSame(treeParameters, createdParameters); createdParameters = factory.CreateParameters("BoundedFR", boundedFrParameters); Assert.IsInstanceOf <BoundedFRLayoutParameters>(createdParameters); Assert.AreNotSame(boundedFrParameters, createdParameters); var kkParameters = new KKLayoutParameters(); createdParameters = factory.CreateParameters("KK", null); Assert.IsInstanceOf <KKLayoutParameters>(createdParameters); Assert.AreNotSame(kkParameters, createdParameters); createdParameters = factory.CreateParameters("KK", testParameters); Assert.IsInstanceOf <KKLayoutParameters>(createdParameters); Assert.AreNotSame(treeParameters, createdParameters); createdParameters = factory.CreateParameters("KK", kkParameters); Assert.IsInstanceOf <KKLayoutParameters>(createdParameters); Assert.AreNotSame(kkParameters, createdParameters); var isomParameters = new ISOMLayoutParameters(); createdParameters = factory.CreateParameters("ISOM", null); Assert.IsInstanceOf <ISOMLayoutParameters>(createdParameters); Assert.AreNotSame(isomParameters, createdParameters); createdParameters = factory.CreateParameters("ISOM", testParameters); Assert.IsInstanceOf <ISOMLayoutParameters>(createdParameters); Assert.AreNotSame(treeParameters, createdParameters); createdParameters = factory.CreateParameters("ISOM", isomParameters); Assert.IsInstanceOf <ISOMLayoutParameters>(createdParameters); Assert.AreNotSame(isomParameters, createdParameters); var linLogParameters = new LinLogLayoutParameters(); createdParameters = factory.CreateParameters("LinLog", null); Assert.IsInstanceOf <LinLogLayoutParameters>(createdParameters); Assert.AreNotSame(linLogParameters, createdParameters); createdParameters = factory.CreateParameters("LinLog", testParameters); Assert.IsInstanceOf <LinLogLayoutParameters>(createdParameters); Assert.AreNotSame(treeParameters, createdParameters); createdParameters = factory.CreateParameters("LinLog", linLogParameters); Assert.IsInstanceOf <LinLogLayoutParameters>(createdParameters); Assert.AreNotSame(linLogParameters, createdParameters); var sugiyamaParameters = new SugiyamaLayoutParameters(); createdParameters = factory.CreateParameters("Sugiyama", null); Assert.IsInstanceOf <SugiyamaLayoutParameters>(createdParameters); Assert.AreNotSame(sugiyamaParameters, createdParameters); createdParameters = factory.CreateParameters("Sugiyama", testParameters); Assert.IsInstanceOf <SugiyamaLayoutParameters>(createdParameters); Assert.AreNotSame(treeParameters, createdParameters); createdParameters = factory.CreateParameters("Sugiyama", sugiyamaParameters); Assert.IsInstanceOf <SugiyamaLayoutParameters>(createdParameters); Assert.AreNotSame(sugiyamaParameters, createdParameters); var compoundFDPParameters = new CompoundFDPLayoutParameters(); createdParameters = factory.CreateParameters("CompoundFDP", null); Assert.IsInstanceOf <CompoundFDPLayoutParameters>(createdParameters); Assert.AreNotSame(compoundFDPParameters, createdParameters); createdParameters = factory.CreateParameters("CompoundFDP", testParameters); Assert.IsInstanceOf <CompoundFDPLayoutParameters>(createdParameters); Assert.AreNotSame(treeParameters, createdParameters); createdParameters = factory.CreateParameters("CompoundFDP", compoundFDPParameters); Assert.IsInstanceOf <CompoundFDPLayoutParameters>(createdParameters); Assert.AreNotSame(compoundFDPParameters, createdParameters); var randomParameters = new RandomLayoutParameters(); createdParameters = factory.CreateParameters("Random", null); Assert.IsInstanceOf <RandomLayoutParameters>(createdParameters); Assert.AreNotSame(randomParameters, createdParameters); createdParameters = factory.CreateParameters("Random", testParameters); Assert.IsInstanceOf <RandomLayoutParameters>(createdParameters); Assert.AreNotSame(treeParameters, createdParameters); createdParameters = factory.CreateParameters("Random", randomParameters); Assert.IsInstanceOf <RandomLayoutParameters>(createdParameters); Assert.AreNotSame(randomParameters, createdParameters); Assert.IsFalse(factory.IsValidAlgorithm(null)); Assert.IsFalse(factory.IsValidAlgorithm(string.Empty)); Assert.IsTrue(factory.IsValidAlgorithm("Circular")); Assert.IsFalse(factory.IsValidAlgorithm("circular")); Assert.IsTrue(factory.IsValidAlgorithm("Tree")); Assert.IsTrue(factory.IsValidAlgorithm("FR")); Assert.IsTrue(factory.IsValidAlgorithm("BoundedFR")); Assert.IsTrue(factory.IsValidAlgorithm("KK")); Assert.IsTrue(factory.IsValidAlgorithm("ISOM")); Assert.IsTrue(factory.IsValidAlgorithm("LinLog")); Assert.IsTrue(factory.IsValidAlgorithm("Sugiyama")); Assert.IsTrue(factory.IsValidAlgorithm("CompoundFDP")); Assert.IsTrue(factory.IsValidAlgorithm("Random")); var algorithm1 = new TestLayoutAlgorithm(); Assert.IsEmpty(factory.GetAlgorithmType(algorithm1)); var algorithm2 = new CircularLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > >(graph, positions, sizes, circularParameters); Assert.AreEqual("Circular", factory.GetAlgorithmType(algorithm2)); var algorithm3 = new SimpleTreeLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > >(graph, positions, sizes, treeParameters); Assert.AreEqual("Tree", factory.GetAlgorithmType(algorithm3)); var algorithm4 = new FRLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > >(graph, positions, frParameters); Assert.AreEqual("FR", factory.GetAlgorithmType(algorithm4)); var algorithm5 = new FRLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > >(graph, positions, boundedFrParameters); Assert.AreEqual("BoundedFR", factory.GetAlgorithmType(algorithm5)); var algorithm6 = new KKLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > >(graph, positions, kkParameters); Assert.AreEqual("KK", factory.GetAlgorithmType(algorithm6)); var algorithm7 = new ISOMLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > >(graph, positions, isomParameters); Assert.AreEqual("ISOM", factory.GetAlgorithmType(algorithm7)); var algorithm8 = new LinLogLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > >(graph); Assert.AreEqual("LinLog", factory.GetAlgorithmType(algorithm8)); var algorithm9 = new SugiyamaLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > >(graph, positions, sizes, sugiyamaParameters); Assert.AreEqual("Sugiyama", factory.GetAlgorithmType(algorithm9)); var algorithm10 = new CompoundFDPLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > >(graph, sizes, borders, layoutTypes); Assert.AreEqual("CompoundFDP", factory.GetAlgorithmType(algorithm10)); var algorithm11 = new RandomLayoutAlgorithm <TestVertex, Edge <TestVertex>, BidirectionalGraph <TestVertex, Edge <TestVertex> > >(graph, sizes, null, randomParameters); Assert.AreEqual("Random", factory.GetAlgorithmType(algorithm11)); Assert.IsFalse(factory.NeedEdgeRouting(string.Empty)); Assert.IsTrue(factory.NeedEdgeRouting("Circular")); Assert.IsTrue(factory.NeedEdgeRouting("Tree")); Assert.IsTrue(factory.NeedEdgeRouting("FR")); Assert.IsTrue(factory.NeedEdgeRouting("BoundedFR")); Assert.IsTrue(factory.NeedEdgeRouting("KK")); Assert.IsTrue(factory.NeedEdgeRouting("ISOM")); Assert.IsTrue(factory.NeedEdgeRouting("LinLog")); Assert.IsFalse(factory.NeedEdgeRouting("Sugiyama")); Assert.IsTrue(factory.NeedEdgeRouting("CompoundFDP")); Assert.IsTrue(factory.NeedEdgeRouting("Random")); Assert.IsFalse(factory.NeedOverlapRemoval(string.Empty)); Assert.IsFalse(factory.NeedOverlapRemoval("Circular")); Assert.IsFalse(factory.NeedOverlapRemoval("Tree")); Assert.IsTrue(factory.NeedOverlapRemoval("FR")); Assert.IsTrue(factory.NeedOverlapRemoval("BoundedFR")); Assert.IsTrue(factory.NeedOverlapRemoval("KK")); Assert.IsTrue(factory.NeedOverlapRemoval("ISOM")); Assert.IsTrue(factory.NeedOverlapRemoval("LinLog")); Assert.IsFalse(factory.NeedOverlapRemoval("Sugiyama")); Assert.IsFalse(factory.NeedOverlapRemoval("CompoundFDP")); Assert.IsTrue(factory.NeedOverlapRemoval("Random")); }
private double EvaluateFitnessForGraph(CompoundFDPLayoutParameters chromosome, CompoundGraph <object, IEdge <object> > compoundGraph) { var sizes = new Dictionary <object, Size>(); var borders = new Dictionary <object, Thickness>(); var layoutType = new Dictionary <object, CompoundVertexInnerLayoutType>(); var s = new Size(20, 20); foreach (var v in compoundGraph.SimpleVertices) { sizes[v] = s; } var b = new Thickness(5, 10, 5, 5); foreach (var v in compoundGraph.CompoundVertices) { sizes[v] = new Size(); borders[v] = b; layoutType[v] = CompoundVertexInnerLayoutType.Automatic; } //run the compound FDP algorithm var algorithm = new CompoundFDPLayoutAlgorithm <object, IEdge <object>, CompoundGraph <object, IEdge <object> > >( compoundGraph, sizes, borders, layoutType, null, chromosome); algorithm.Compute(); double fitness = 0.0; //refresh the sizes of the compound vertices foreach (var v in compoundGraph.CompoundVertices) { var border = borders[v]; var innerCanvasSize = algorithm.InnerCanvasSizes[v]; var size = new Size( border.Left + innerCanvasSize.Width + border.Right, border.Top + innerCanvasSize.Height + border.Bottom ); sizes[v] = size; } //NODE OVERLAP double overlaps = EvaluateNodeOverlaps(compoundGraph, algorithm, sizes); /*if (overlaps > 0.0) * return double.NaN;*/ fitness += overlaps * NODE_OVERLAP_MULTIPLIER; //CANVAS SIZE Size canvasSize = EvaluateCanvasSize(compoundGraph, algorithm, sizes); fitness += canvasSize.Width * canvasSize.Height * CANVAS_SIZE_MULTIPLIER; //CANVAS RATIO double canvasRatio = canvasSize.Width / canvasSize.Height; canvasRatio = canvasRatio < 1 ? 1 / canvasRatio : canvasRatio; fitness += canvasRatio * CANVAS_RATIO_MULTIPLIER; //NODE DISTANCES double minimalMinDistance, averageMinDistance, maximalMinDistance; double idealDistance = chromosome.IdealEdgeLength; EvaluateNodeDistances(compoundGraph, algorithm, sizes, out minimalMinDistance, out averageMinDistance, out maximalMinDistance); fitness += (averageMinDistance - idealDistance) * NODE_DISTANCE_MULTIPLIER; fitness += (minimalMinDistance - idealDistance) * NODE_DISTANCE_MULTIPLIER; fitness += (maximalMinDistance - idealDistance) * NODE_DISTANCE_MULTIPLIER; //EDGE LENGTH double edgeLength = EvaluateEdgeLength(compoundGraph, algorithm, sizes, chromosome.IdealEdgeLength, chromosome.NestingFactor); fitness += edgeLength * EDGE_LENGTH_MULTIPLIER; //EDGE CROSSING double edgeCrossing = EvaluateEdgeCrossing(compoundGraph, algorithm, sizes); fitness += edgeCrossing * EDGE_CROSSING_MULTIPLIER; //PHASE_LENGTH double phaseLength = (chromosome.Phase1Iterations + chromosome.Phase2Iterations + chromosome.Phase3Iterations) * PHASE_LENGTH_MULTIPLIER; fitness += phaseLength; return(fitness); }
private void ShowGraph(int graphIndex) { CompoundGraph<object, IEdge<object>> g = graphs[graphIndex]; _rectDict.Clear(); _lineDict.Clear(); lc.Children.Clear(); var origo = new Ellipse(); origo.Width = 100; origo.Height = 100; origo.Fill = Brushes.Black; origo.OpacityMask = new RadialGradientBrush(Colors.Black, Colors.Transparent); Canvas.SetLeft(origo, -5); Canvas.SetTop(origo, -5); lc.Children.Add(origo); var sizes = new Dictionary<object, Size>(); var borders = new Dictionary<object, Thickness>(); var layoutType = new Dictionary<object, CompoundVertexInnerLayoutType>(); var s = new Size(20, 20); foreach (var v in g.SimpleVertices) { sizes[v] = s; } var b = new Thickness(5, 10, 5, 5); foreach (var v in g.CompoundVertices) { sizes[v] = new Size(); borders[v] = b; layoutType[v] = CompoundVertexInnerLayoutType.Automatic; } var worker = new BackgroundWorker(); worker.WorkerReportsProgress = true; worker.DoWork += (sender, e) => { var layoutAlgorithm = new CompoundFDPLayoutAlgorithm <object, IEdge<object>, ICompoundGraph<object, IEdge<object>>>( g, sizes, borders, layoutType, null, parameters); layoutAlgorithm.IterationEnded += (o, evt) => { var args = evt as TestingCompoundLayoutIterationEventArgs<object, IEdge<object>, TestingCompoundVertexInfo, object>; var positions = args.VertexPositions; var innerSizes = (args as ICompoundLayoutIterationEventArgs<object>).InnerCanvasSizes; var vertexInfos = args.VertexInfos; Dispatcher.Invoke(new Action(delegate { var pDict = new Dictionary<object, Point>(); var compoundVerticesToCheck = new Queue<object>(); var compoundVertices = new List<object>(); var root = g.CompoundVertices.Where( cv => g.GetParent(cv) == null); foreach (var r in root) compoundVerticesToCheck.Enqueue(r); while (compoundVerticesToCheck.Count > 0) { var next = compoundVerticesToCheck.Dequeue(); if (!g.IsCompoundVertex(next)) continue; compoundVertices.Add(next); foreach ( var childrenVertex in g.GetChildrenVertices(next)) { compoundVerticesToCheck.Enqueue( childrenVertex); } } //draw the compound vertices foreach (var v in compoundVertices) { var size = innerSizes[v]; size.Width += b.Left + b.Right; size.Height += b.Top + b.Bottom; var pos = positions[v]; pDict[v] = pos; AddRect(v, pos, size); } //draw the simple vertices foreach (var v in g.SimpleVertices) { var pos = positions[v]; pDict[v] = pos; AddRect(v, pos, s); } //draw the simple edges foreach (var edge in g.Edges) { var pos1 = pDict[edge.Source]; var pos2 = pDict[edge.Target]; AddLine(edge, pos1, pos2, true); } //draw the containment edges /*foreach (var v in g.CompoundVertices) { var pos1 = pDict[v]; foreach (var c in g.GetChildrenVertices(v)) { var pos2 = pDict[c]; AddLine(c, pos1, pos2, false); } }*/ //draw the lines of the forces foreach (var forceLine in _forceLines) lc.Children.Remove(forceLine); var springColor = Brushes.Orange; var repulsionColor = Brushes.Red; var gravityColor = Brushes.Green; var applicationColor = Brushes.Yellow; foreach (var kvp in vertexInfos) { var line = CreateLine(pDict[kvp.Key], kvp.Value.SpringForce, springColor); lc.Children.Add(line); _forceLines.Add(line); line = CreateLine(pDict[kvp.Key], kvp.Value.RepulsionForce, repulsionColor); lc.Children.Add(line); _forceLines.Add(line); line = CreateLine(pDict[kvp.Key], kvp.Value.GravityForce, gravityColor); lc.Children.Add(line); _forceLines.Add(line); line = CreateLine(pDict[kvp.Key], kvp.Value.ApplicationForce, applicationColor); lc.Children.Add(line); _forceLines.Add(line); } //set the position of the gravity center Animate(origo, Canvas.LeftProperty, args.GravitationCenter.X - origo.Width / 2.0, animationDuration); Animate(origo, Canvas.TopProperty, args.GravitationCenter.Y - origo.Height / 2.0, animationDuration); txtMessage.Text = args.Message; })); do { Thread.Sleep((int) animationDuration.TimeSpan.TotalMilliseconds); } while (_paused); }; layoutAlgorithm.Compute(); }; worker.RunWorkerAsync(); }
/// <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); }
private void ShowGraph(int graphIndex) { CompoundGraph <object, IEdge <object> > graph = _graphs[graphIndex]; _rectangles.Clear(); _lines.Clear(); Layout.Children.Clear(); var origo = new Ellipse { Width = 100, Height = 100, Fill = System.Windows.Media.Brushes.Black, OpacityMask = new RadialGradientBrush(Colors.Black, Colors.Transparent) }; Canvas.SetLeft(origo, -5); Canvas.SetTop(origo, -5); Layout.Children.Add(origo); var sizes = new Dictionary <object, Size>(); var borders = new Dictionary <object, Thickness>(); var layoutType = new Dictionary <object, CompoundVertexInnerLayoutType>(); var size = new Size(20, 20); foreach (object vertex in graph.SimpleVertices) { sizes[vertex] = size; } var thickness = new Thickness(5, 10, 5, 5); foreach (object vertex in graph.CompoundVertices) { sizes[vertex] = default; borders[vertex] = thickness; layoutType[vertex] = CompoundVertexInnerLayoutType.Automatic; } var worker = new BackgroundWorker { WorkerReportsProgress = true }; worker.DoWork += (sender, args) => { var layoutAlgorithm = new CompoundFDPLayoutAlgorithm <object, IEdge <object>, ICompoundGraph <object, IEdge <object> > >( graph, sizes, borders, layoutType, _parameters); layoutAlgorithm.IterationEnded += (s, iterationArgs) => { var testIterationArgs = iterationArgs as TestingCompoundLayoutIterationEventArgs <object, IEdge <object>, TestingCompoundVertexInfo, object>; IDictionary <object, Point> positions = testIterationArgs?.VerticesPositions; if (positions is null) { return; } IDictionary <object, Size> innerSizes = ((ICompoundLayoutIterationEventArgs <object>)testIterationArgs).InnerCanvasSizes; IDictionary <object, TestingCompoundVertexInfo> verticesInfos = testIterationArgs.VerticesInfos; Dispatcher.Invoke(() => { var points = new Dictionary <object, Point>(); var compoundVerticesToCheck = new Queue <object>(); var compoundVertices = new List <object>(); var roots = graph.CompoundVertices.Where(vertex => graph.GetParent(vertex) is null); foreach (object root in roots) { compoundVerticesToCheck.Enqueue(root); } while (compoundVerticesToCheck.Count > 0) { object next = compoundVerticesToCheck.Dequeue(); if (!graph.IsCompoundVertex(next)) { continue; } compoundVertices.Add(next); foreach (object childrenVertex in graph.GetChildrenVertices(next)) { compoundVerticesToCheck.Enqueue(childrenVertex); } } // Draw the compound vertices foreach (object vertex in compoundVertices) { Size innerSize = innerSizes[vertex]; innerSize.Width += thickness.Left + thickness.Right; innerSize.Height += thickness.Top + thickness.Bottom; Point pos = positions[vertex]; points[vertex] = pos; AddRectangle(vertex, pos, innerSize); } // Draw the simple vertices foreach (object vertex in graph.SimpleVertices) { Point pos = positions[vertex]; points[vertex] = pos; AddRectangle(vertex, pos, size); } // Draw the simple edges foreach (IEdge <object> edge in graph.Edges) { Point pos1 = points[edge.Source]; Point pos2 = points[edge.Target]; AddLine(edge, pos1, pos2, true); } // Draw the containment edges foreach (object vertex in graph.CompoundVertices) { Point pos1 = points[vertex]; foreach (object child in graph.GetChildrenVertices(vertex)) { Point pos2 = points[child]; AddLine(child, pos1, pos2, false); } } // Draw the lines of the forces foreach (Line forceLine in _forceLines) { Layout.Children.Remove(forceLine); } SolidColorBrush springColor = System.Windows.Media.Brushes.Orange; SolidColorBrush repulsionColor = System.Windows.Media.Brushes.Red; SolidColorBrush gravityColor = System.Windows.Media.Brushes.Green; SolidColorBrush applicationColor = System.Windows.Media.Brushes.Yellow; foreach (KeyValuePair <object, TestingCompoundVertexInfo> pair in verticesInfos) { Line line = CreateLine(points[pair.Key], pair.Value.SpringForce, springColor); Layout.Children.Add(line); _forceLines.Add(line); line = CreateLine(points[pair.Key], pair.Value.RepulsionForce, repulsionColor); Layout.Children.Add(line); _forceLines.Add(line); line = CreateLine(points[pair.Key], pair.Value.GravityForce, gravityColor); Layout.Children.Add(line); _forceLines.Add(line); line = CreateLine(points[pair.Key], pair.Value.ApplicationForce, applicationColor); Layout.Children.Add(line); _forceLines.Add(line); } // Set the position of the gravity center Animate( origo, Canvas.LeftProperty, testIterationArgs.GravitationCenter.X - origo.Width / 2.0, _animationDuration); Animate( origo, Canvas.TopProperty, testIterationArgs.GravitationCenter.Y - origo.Height / 2.0, _animationDuration); TxtMessage.Text = testIterationArgs.Message; }); do { Thread.Sleep((int)_animationDuration.TimeSpan.TotalMilliseconds); } while (_paused); }; layoutAlgorithm.Compute(); }; worker.RunWorkerAsync(); }
private static double EvaluateFitnessForGraph( [NotNull] CompoundFDPLayoutParameters chromosome, [NotNull] CompoundGraph <object, IEdge <object> > compoundGraph) { var verticesSizes = new Dictionary <object, Size>(); var verticesBorders = new Dictionary <object, Thickness>(); var layoutTypes = new Dictionary <object, CompoundVertexInnerLayoutType>(); var size = new Size(20, 20); foreach (object v in compoundGraph.SimpleVertices) { verticesSizes[v] = size; } var border = new Thickness(5, 10, 5, 5); foreach (object v in compoundGraph.CompoundVertices) { verticesSizes[v] = new Size(); verticesBorders[v] = border; layoutTypes[v] = CompoundVertexInnerLayoutType.Automatic; } // Run the compound FDP algorithm var algorithm = new CompoundFDPLayoutAlgorithm <object, IEdge <object>, CompoundGraph <object, IEdge <object> > >( compoundGraph, verticesSizes, verticesBorders, layoutTypes, chromosome); algorithm.Compute(); double fitness = 0.0; // Refresh the sizes of the compound vertices foreach (object v in compoundGraph.CompoundVertices) { Thickness b = verticesBorders[v]; Size innerCanvasSize = algorithm.InnerCanvasSizes[v]; var s = new Size( b.Left + innerCanvasSize.Width + b.Right, b.Top + innerCanvasSize.Height + b.Bottom); verticesSizes[v] = s; } // NODE OVERLAP double overlaps = EvaluateNodeOverlaps(compoundGraph, algorithm, verticesSizes); fitness += overlaps * NodeOverlapMultiplier; // CANVAS SIZE Size canvasSize = EvaluateCanvasSize(compoundGraph, algorithm, verticesSizes); fitness += canvasSize.Width * canvasSize.Height * CanvasSizeMultiplier; // CANVAS RATIO double canvasRatio = canvasSize.Width / canvasSize.Height; canvasRatio = canvasRatio < 1 ? 1 / canvasRatio : canvasRatio; fitness += canvasRatio * CanvasRatioMultiplier; // NODE DISTANCES double idealDistance = chromosome.IdealEdgeLength; EvaluateNodeDistances( compoundGraph, algorithm, verticesSizes, out double minimalMinDistance, out double averageMinDistance, out double maximalMinDistance); fitness += (averageMinDistance - idealDistance) * NodeDistanceMultiplier; fitness += (minimalMinDistance - idealDistance) * NodeDistanceMultiplier; fitness += (maximalMinDistance - idealDistance) * NodeDistanceMultiplier; // EDGE LENGTH double edgeLength = EvaluateEdgeLength( compoundGraph, algorithm, verticesSizes, chromosome.IdealEdgeLength, chromosome.NestingFactor); fitness += edgeLength * EdgeLengthMultiplier; // EDGE CROSSING double edgeCrossing = EvaluateEdgeCrossing(compoundGraph, algorithm, verticesSizes); fitness += edgeCrossing * EdgeCrossingMultiplier; // PHASE_LENGTH double phaseLength = chromosome.Phase1Iterations + chromosome.Phase2Iterations + chromosome.Phase3Iterations; phaseLength *= PhaseLengthMultiplier; fitness += phaseLength; return(fitness); }