static void AddEdgesBetweenColumns(string[] col0, string[] col1, GeometryGraph graph) { foreach (var id in col0) { Edge edge = new Edge(graph.FindNodeByUserData(id), graph.FindNodeByUserData(col1[r.Next(col1.Length)])); edge.EdgeGeometry.TargetArrowhead = null; graph.Edges.Add(edge); edge = new Edge(graph.FindNodeByUserData(id), graph.FindNodeByUserData(col1[r.Next(col1.Length)])); graph.Edges.Add(edge); } }
private static void CreateDiagramLinks(List <BinaryLinkShape> linkShapes, GeometryGraph graph) { foreach (BinaryLinkShape linkShape in linkShapes) { graph.Edges.Add(new Edge(graph.FindNodeByUserData(linkShape.Nodes[0]), graph.FindNodeByUserData(linkShape.Nodes[1])) { UserData = linkShape }); } }
private static void AddEdge(GeometryGraph g, string u, string v) { var e = new Edge(g.FindNodeByUserData(u), g.FindNodeByUserData(v)); e.EdgeGeometry.SourceArrowhead = new Arrowhead { Length = 5, Width = 5 }; e.EdgeGeometry.TargetArrowhead = new Arrowhead { Length = 5, Width = 5 }; g.Edges.Add(e); }
//helper function for ToMSALGraph private static void RecursiveCompleteMSALGraphEdges(GeometryGraph target, Node current) { target.Edges.Add( new Edge( // Set source and target by finding MSAGL node based on SfDiagram node. target.FindNodeByUserData(current.getParent()), target.FindNodeByUserData(current)) { Weight = 1, }); foreach (Node child in current.getChildren()) { RecursiveCompleteMSALGraphEdges(target, child); } }
internal static GeometryGraph CreateAndLayoutGraph() { double w = 40; double h = 10; GeometryGraph graph = new GeometryGraph(); // columns var col0 = new[] { "a", "b", "c" }; var col1 = new[] { "d", "e", "f", "g" }; var col2 = new[] { "k", "l", "m", "n" }; var col3 = new[] { "w", "y", "z" }; var settings = new SugiyamaLayoutSettings(); foreach (var id in col0) { DrawingUtilsForSamples.AddNode(id, graph, w, h); } foreach (var id in col1) { DrawingUtilsForSamples.AddNode(id, graph, w, h); } foreach (var id in col2) { DrawingUtilsForSamples.AddNode(id, graph, w, h); } foreach (var id in col3) { DrawingUtilsForSamples.AddNode(id, graph, w, h); } //pinning columns settings.PinNodesToSameLayer(col0.Select(s => graph.FindNodeByUserData(s)).ToArray()); settings.PinNodesToSameLayer(col1.Select(s => graph.FindNodeByUserData(s)).ToArray()); settings.PinNodesToSameLayer(col2.Select(s => graph.FindNodeByUserData(s)).ToArray()); settings.PinNodesToSameLayer(col3.Select(s => graph.FindNodeByUserData(s)).ToArray()); AddEdgesBetweenColumns(col0, col1, graph); AddEdgesBetweenColumns(col1, col2, graph); AddEdgesBetweenColumns(col2, col3, graph); // rotate layer to columns settings.Transformation = PlaneTransformation.Rotation(Math.PI / 2); settings.NodeSeparation = 5; settings.LayerSeparation = 100; var ll = new LayeredLayout(graph, settings); ll.Run(); return(graph); }
static Node SetNode( GeometryGraph g, string id, double xRad, double yRad) { var geomNode = g.FindNodeByUserData(id); if (geomNode == null) { g.Nodes.Add(geomNode = new Node() { UserData = id }); } var size = MeasureTextSize(id); geomNode.BoundaryCurve = CurveFactory.CreateRectangleWithRoundedCorners( size.Width, size.Height, xRad, yRad, new Point(0, 0) ); return(geomNode); }
private static Cluster AddRootCluster(GeometryGraph g, params string[] vs) { var c = new Cluster(from v in vs select g.FindNodeByUserData(v)); g.RootCluster = c; return(c); }
private string GetUniqueId(IComparable p) { string id; do { id = p.ToString() + idCounter++; }while (graph.FindNodeByUserData(id) != null); return(id); }
public static Node AddNode(GeometryGraph geometryGraph, IDiagramItem item) { Node msaglNode = geometryGraph.FindNodeByUserData(item); if (msaglNode == null) { msaglNode = new Node(CreateCurve(item), item); geometryGraph.Nodes.Add(msaglNode); } return(msaglNode); }
/// <summary> /// Finds the GeometryNode for the drawing node with the given id. /// </summary> /// <returns></returns> public Microsoft.Msagl.Core.Layout.Node FindGeometryNode(string nodeId) { if (GeometryGraph != null) { Node node = nodeMap[nodeId] as Node; if (node != null) { return(GeometryGraph.FindNodeByUserData(node)); } } return(null); }
private static void AddDesignConstraints(List <BinaryLinkShape> linkShapes, ModelRoot modelRoot, GeometryGraph graph) { // Sugiyama allows for layout constraints, so we can make sure that base classes are above derived classes, // and put classes derived from the same base in the same vertical layer. Unfortunately, other layout strategies // don't have that ability. if (modelRoot.LayoutAlgorithmSettings is SugiyamaLayoutSettings sugiyamaSettings) { // ensure generalizations are vertically over each other foreach (GeneralizationConnector linkShape in linkShapes.OfType <GeneralizationConnector>()) { if (modelRoot.LayoutAlgorithm == LayoutAlgorithm.Sugiyama) { int upperNodeIndex = linkShape.Nodes[1].ModelElement.GetBaseElement() == linkShape.Nodes[0].ModelElement ? 0 : 1; int lowerNodeIndex = upperNodeIndex == 0 ? 1 : 0; sugiyamaSettings.AddUpDownConstraint(graph.FindNodeByUserData(linkShape.Nodes[upperNodeIndex]), graph.FindNodeByUserData(linkShape.Nodes[lowerNodeIndex])); } } // add constraints ensuring descendents of a base class are on the same level Dictionary <string, List <NodeShape> > derivedClasses = linkShapes.OfType <GeneralizationConnector>() .SelectMany(ls => ls.Nodes) .Where(n => n.ModelElement is ModelClass mc && mc.BaseClass != null) .GroupBy(n => ((ModelClass)n.ModelElement).BaseClass) .ToDictionary(n => n.Key, n => n.ToList()); foreach (KeyValuePair <string, List <NodeShape> > derivedClassData in derivedClasses) { Node[] siblingNodes = derivedClassData.Value.Select(graph.FindNodeByUserData).ToArray(); sugiyamaSettings.AddSameLayerNeighbors(siblingNodes); } } }
private static Cluster AddCluster(double padding, GeometryGraph g, Cluster parent, params string[] vs) { var c = new Cluster(from v in vs select g.FindNodeByUserData(v)) { UserData = string.Concat(vs), RectangularBoundary = new RectangularClusterBoundary { LeftMargin = padding, RightMargin = padding, BottomMargin = padding, TopMargin = padding }, BoundaryCurve = CurveFactory.CreateRectangle(30, 30, new Point(15, 15)) }; parent.AddChild(c); return(c); }
/// <summary> /// Creates a small, non-trivial clustered and disconnected graph for tests /// ( A B-)-C /// D-(-(-E F)-G) /// H-I /// J /// (K L-)-(-M N) /// </summary> /// <returns>returns a disconnected clustered graph</returns> public static GeometryGraph CreateClusteredGraph(double padding) { var graph = new GeometryGraph(); for (int i = 0; i < 14; ++i) { graph.Nodes.Add(new Node(CurveFactory.CreateRectangle(10, 10, new Point()), GetCharacter(i))); } AddEdge(graph, "B", "C"); AddEdge(graph, "D", "E"); AddEdge(graph, "H", "I"); var root = AddRootCluster(graph, "C", "D", "H", "I", "J"); AddCluster(padding, graph, root, "A", "B"); var parent = AddCluster(padding, graph, root, "G"); var child = AddCluster(padding, graph, parent, "E", "F"); graph.Edges.Add(new Edge(graph.FindNodeByUserData("G"), child)); graph.Edges.Add(new Edge(AddCluster(padding, graph, root, "K", "L"), AddCluster(padding, graph, root, "M", "N"))); return(graph); }
static internal GeometryGraph CreateAndLayoutGraph() { GeometryGraph graph = new GeometryGraph(); double width = 40; double height = 10; foreach (string id in "0 1 2 3 4 5 6 A B C D E F G a b c d e".Split(' ')) { DrawingUtilsForSamples.AddNode(id, graph, width, height); } graph.Edges.Add(new Edge(graph.FindNodeByUserData("A"), graph.FindNodeByUserData("B"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("A"), graph.FindNodeByUserData("C"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("A"), graph.FindNodeByUserData("D"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("D"), graph.FindNodeByUserData("E"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("B"), graph.FindNodeByUserData("E"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("D"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("0"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("1"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("2"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("3"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("4"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("5"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("6"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("a"), graph.FindNodeByUserData("b"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("b"), graph.FindNodeByUserData("c"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("c"), graph.FindNodeByUserData("d"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("d"), graph.FindNodeByUserData("e"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("A"), graph.FindNodeByUserData("a"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("B"), graph.FindNodeByUserData("a"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("C"), graph.FindNodeByUserData("a"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("D"), graph.FindNodeByUserData("a"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("E"), graph.FindNodeByUserData("a"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("F"), graph.FindNodeByUserData("a"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("G"), graph.FindNodeByUserData("a"))); var settings = new SugiyamaLayoutSettings { Transformation = PlaneTransformation.Rotation(Math.PI / 2), EdgeRoutingSettings = { EdgeRoutingMode = EdgeRoutingMode.Spline } }; var layout = new LayeredLayout(graph, settings); layout.Run(); return(graph); }
static internal GeometryGraph CreateAndLayoutGraph() { GeometryGraph graph = new GeometryGraph(); double width = 40; double height = 10; foreach (string id in "0 1 2 3 4 5 6 A B C D E F G a b c d e".Split(' ')) { AddNode(id, graph, width, height); } graph.Edges.Add(new Edge(graph.FindNodeByUserData("A"), graph.FindNodeByUserData("B"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("A"), graph.FindNodeByUserData("C"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("A"), graph.FindNodeByUserData("D"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("D"), graph.FindNodeByUserData("E"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("B"), graph.FindNodeByUserData("E"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("D"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("0"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("1"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("2"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("3"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("4"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("5"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("6"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("a"), graph.FindNodeByUserData("b"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("b"), graph.FindNodeByUserData("c"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("c"), graph.FindNodeByUserData("d"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("d"), graph.FindNodeByUserData("e"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("A"), graph.FindNodeByUserData("a"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("B"), graph.FindNodeByUserData("a"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("C"), graph.FindNodeByUserData("a"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("D"), graph.FindNodeByUserData("a"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("E"), graph.FindNodeByUserData("a"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("F"), graph.FindNodeByUserData("a"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("G"), graph.FindNodeByUserData("a"))); var settings = new SugiyamaLayoutSettings(); settings.Transformation = PlaneTransformation.Rotation(Math.PI / 2); settings.EdgeRoutingSettings.EdgeRoutingMode = EdgeRoutingMode.Spline; var layout = new LayeredLayout(graph, settings); layout.Run(); return(graph); // double w = 40; // double h = 10; // GeometryGraph graph = new GeometryGraph(); //columns // var col0 = new[] { "a", "b", "c" }; // var col1 = new[] { "d", "e", "f", "g" }; // var col2 = new[] { "k", "l", "m", "n" }; // var col3 = new[] { "w", "y", "z" }; // // var settings = new SugiyamaLayoutSettings(); // // foreach (var id in col0) // AddNode(id, graph, w, h); // foreach (var id in col1) // AddNode(id, graph, w, h); // foreach (var id in col2) // AddNode(id, graph, w, h); // foreach (var id in col3) // AddNode(id, graph, w, h); // //pinning columns // settings.PinNodesToSameLayer(col0.Select(s=>graph.FindNodeByUserData(s)).ToArray()); // settings.PinNodesToSameLayer(col1.Select(s => graph.FindNodeByUserData(s)).ToArray()); // settings.PinNodesToSameLayer(col2.Select(s => graph.FindNodeByUserData(s)).ToArray()); // settings.PinNodesToSameLayer(col3.Select(s => graph.FindNodeByUserData(s)).ToArray()); // // AddEdgesBetweenColumns(col0, col1, graph); // AddEdgesBetweenColumns(col1, col2, graph); // AddEdgesBetweenColumns(col2, col3, graph); //rotate layer to columns // graph.Transformation = PlaneTransformation.Rotation(Math.PI / 2); // settings.NodeSeparation = 5; // settings.LayerSeparation = 100; // var ll = new LayeredLayout(graph, settings); // ll.Run(); // return graph; }
public void GetClusteredConnectedComponentsTest() { List <GeometryGraph> components = graph.GetClusteredConnectedComponents().ToList(); List <Cluster> expectedTopLevelClusters = graph.RootCluster.Clusters.ToList(); Assert.AreEqual(5, components.Count, "Expected 5 connected components"); Node nodeA = graph.FindNodeByUserData("A"); Node nodeB = graph.FindNodeByUserData("B"); Node nodeC = graph.FindNodeByUserData("C"); // go through each of the components and make sure that it matches the original // since the graph is traversed in order of Nodes we know what order the components will be appear in Actual GeometryGraph c = components[0]; Assert.AreEqual(3, c.Nodes.Count, "Component has incorrect node count"); Assert.IsTrue(c.FindNodeByUserData(nodeA) != null, "Component should contain node A"); Assert.IsTrue(c.FindNodeByUserData(nodeB) != null, "Component should contain node B"); Assert.IsTrue(c.FindNodeByUserData(nodeC) != null, "Component should contain node C"); Assert.AreSame(c.FindNodeByUserData(nodeC).InEdges.First().UserData, nodeC.InEdges.First(), "Edge doesn't match original"); Assert.AreEqual(1, c.Edges.Count, "Component should contain 1 edge"); var cluster = c.RootCluster.Clusters.First(); Assert.AreEqual(2, cluster.Nodes.Count(), "Component should contain 2 nodes"); Assert.AreSame(expectedTopLevelClusters[0], cluster.UserData, "Component invalid"); c = components[1]; Assert.AreEqual(4, c.Nodes.Count, "Component invalid"); Assert.AreEqual(2, c.Edges.Count, "Component invalid"); cluster = c.RootCluster.Clusters.First(); Assert.AreSame(expectedTopLevelClusters[1], cluster.UserData, "Component invalid"); Assert.AreEqual(1, cluster.Nodes.Count(), "Component invalid"); Assert.AreEqual("G", ((Node)cluster.Nodes.First().UserData).UserData, "Component invalid"); // double user data lookup since the first user data is the components source node var nested = cluster.Clusters.First(); Assert.AreEqual("E", ((Node)nested.Nodes.First().UserData).UserData, "Component invalid"); Assert.AreEqual("F", ((Node)nested.Nodes.Last().UserData).UserData, "Component invalid"); Assert.AreSame(expectedTopLevelClusters[1].Clusters.First(), nested.UserData, "Component invalid"); Assert.AreEqual(2, nested.Nodes.Count(), "Component invalid"); c = components[2]; Assert.AreEqual(2, c.Nodes.Count, "Component invalid"); Assert.AreEqual(1, c.Edges.Count, "Component invalid"); Assert.IsFalse(c.RootCluster.Clusters.Any(), "Component invalid"); c = components[3]; Assert.AreEqual(1, c.Nodes.Count, "Component invalid"); Assert.AreEqual(0, c.Edges.Count, "Component invalid"); Assert.IsFalse(c.RootCluster.Clusters.Any(), "Component invalid"); c = components[4]; cluster = c.RootCluster.Clusters.First(); Assert.AreEqual("K", ((Node)cluster.Nodes.First().UserData).UserData, "Component invalid"); Assert.AreEqual("L", ((Node)cluster.Nodes.Last().UserData).UserData, "Component invalid"); cluster = c.RootCluster.Clusters.Last(); Assert.AreEqual("M", ((Node)cluster.Nodes.First().UserData).UserData, "Component invalid"); Assert.AreEqual("N", ((Node)cluster.Nodes.Last().UserData).UserData, "Component invalid"); Assert.AreEqual(c.Edges.Count, 1, "Component invalid"); }
internal void CreateGraph() { graph = new GeometryGraph(); double width = 100; double height = 30; foreach (string id in "0 1 2 3 4 5 6 A B C D E F G a b c d e".Split(' ')) { AddNode(id, graph, width, height); } graph.Edges.Add(new Edge(graph.FindNodeByUserData("A"), graph.FindNodeByUserData("B"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("A"), graph.FindNodeByUserData("C"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("A"), graph.FindNodeByUserData("D"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("D"), graph.FindNodeByUserData("E"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("B"), graph.FindNodeByUserData("E"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("D"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("0"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("1"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("2"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("3"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("4"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("5"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("6"), graph.FindNodeByUserData("F"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("a"), graph.FindNodeByUserData("b"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("b"), graph.FindNodeByUserData("c"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("c"), graph.FindNodeByUserData("d"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("d"), graph.FindNodeByUserData("e"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("A"), graph.FindNodeByUserData("a"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("B"), graph.FindNodeByUserData("a"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("C"), graph.FindNodeByUserData("a"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("D"), graph.FindNodeByUserData("a"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("E"), graph.FindNodeByUserData("a"))); graph.Edges.Add(new Edge(graph.FindNodeByUserData("F"), graph.FindNodeByUserData("a"))); Edge edge = new Edge(graph.FindNodeByUserData("G"), graph.FindNodeByUserData("a")); graph.Edges.Add(edge); }