public void TestReadDotFile() { RootGraph root = RootGraph.FromDotString(@" digraph test { A; B; B -> B; A -> B[name = edgename]; A -> B[name = edgename]; A -> B[name = edgename]; } "); var edges = root.Edges().ToList(); var names = edges.Select(e => e.GetName()); // This results in ,,, strangely enough // There seems to be no way to influence the edge name from dot Console.WriteLine(string.Join(", ", names)); // However, it is strange that all edges seem to have te same name, namely "" // According to the documentation, the name is used to distinguish between multiedges var A = root.GetNode("A"); var B = root.GetNode("B"); Assert.AreEqual(3, A.EdgesOut().Count()); // The documentation seem to be correct for edges that are added through the C interface root.GetOrAddEdge(A, B, ""); root.GetOrAddEdge(A, B, ""); root.GetOrAddEdge(A, B, ""); Assert.AreEqual(4, A.EdgesOut().Count()); }
public void TestEdgesInSubgraphs() { RootGraph graph = Utils.CreateUniqueTestGraph(); Node node = graph.GetOrAddNode("node"); Edge edge = graph.GetOrAddEdge(node, node, "edge 1"); SubGraph subgraph = graph.GetOrAddSubgraph("sub graph"); Node subnode = subgraph.GetOrAddNode("subnode"); Edge subedge_between_node = subgraph.GetOrAddEdge(node, node, "edge 2"); Edge subedge_between_subnode = subgraph.GetOrAddEdge(subnode, subnode, "edge 3"); Edge edge_between_subnode = graph.GetOrAddEdge(subnode, subnode, "edge 4"); Assert.True(graph.Contains(edge)); Assert.True(graph.Contains(subedge_between_node)); Assert.True(graph.Contains(subedge_between_subnode)); Assert.True(graph.Contains(edge_between_subnode)); Assert.False(subgraph.Contains(edge)); Assert.True(subgraph.Contains(subedge_between_node)); Assert.True(subgraph.Contains(subedge_between_subnode)); Assert.False(subgraph.Contains(edge_between_subnode)); // Conclusion: // Subgraphs can contain edges, independently of their endpoints. // This affects enumeration as follows: Assert.AreEqual(2, node.EdgesOut(graph).Count()); Assert.AreEqual(1, node.EdgesOut(subgraph).Count()); Assert.AreEqual(2, subnode.EdgesOut(graph).Count()); Assert.AreEqual(1, subnode.EdgesOut(subgraph).Count()); }
public void TestDeletions() { RootGraph root = Utils.CreateUniqueTestGraph(); Node tail = root.GetOrAddNode("1"); Node head = root.GetOrAddNode("2"); Node other = root.GetOrAddNode("3"); Edge edge = root.GetOrAddEdge(tail, head, "edge"); Edge tailout = root.GetOrAddEdge(tail, other, "tailout"); Edge headout = root.GetOrAddEdge(head, other, "headout"); Edge tailin = root.GetOrAddEdge(other, tail, "tailin"); Edge headin = root.GetOrAddEdge(other, head, "headin"); Assert.IsTrue(root.Equals(root.MyRootGraph)); Assert.IsTrue(root.Equals(tail.MyRootGraph)); Assert.IsTrue(root.Equals(edge.MyRootGraph)); Assert.AreEqual(3, tail.TotalDegree()); Assert.AreEqual(3, head.TotalDegree()); Assert.AreEqual(3, root.Nodes().Count()); root.Delete(edge); Assert.AreEqual(2, tail.TotalDegree()); Assert.AreEqual(2, head.TotalDegree()); Assert.AreEqual(3, root.Nodes().Count()); root.Delete(tail); Assert.AreEqual(2, root.Nodes().Count()); Assert.AreEqual(2, other.TotalDegree()); }
public void StringEscaping() { RootGraph root = RootGraph.CreateNew("Graph with escaped strings", GraphType.Directed); Node.IntroduceAttribute(root, "label", "\\N"); Node nodeA = root.GetOrAddNode("A"); // Several characters and character sequences can have special meanings in labels, like \N. // When you want to have a literal string in a label, we provide a convenience function for you to do just that. nodeA.SetAttribute("label", CGraphThing.EscapeLabel("Some string literal \\N \\n |}>")); root.ComputeLayout(); // When defining portnames, some characters, like ':' and '|', are not allowed and they can't be escaped either. // This can be troubling if you have an externally defined ID for such a port. // We provide a function that maps strings to valid portnames. var somePortId = "port id with :| special characters"; var validPortName = Edge.ConvertUidToPortName(somePortId); Node nodeB = root.GetOrAddNode("B"); nodeB.SafeSetAttribute("shape", "record", ""); nodeB.SafeSetAttribute("label", $"<{validPortName}>1|2", "\\N"); // The function makes sure different strings don't accidentally map onto the same portname Assert.That(Edge.ConvertUidToPortName(":"), Is.Not.EqualTo(Edge.ConvertUidToPortName("|"))); }
public void GraphConstruction() { // You can programmatically construct graphs as follows RootGraph root = RootGraph.CreateNew("Some Unique Identifier", GraphType.Directed); // The node names are unique identifiers within a graph in Graphviz Node nodeA = root.GetOrAddNode("A"); Node nodeB = root.GetOrAddNode("B"); Node nodeC = root.GetOrAddNode("C"); Node nodeD = root.GetOrAddNode("D"); // The edge name is only unique between two nodes Edge edgeAB = root.GetOrAddEdge(nodeA, nodeB, "Some edge name"); Edge edgeBC = root.GetOrAddEdge(nodeB, nodeC, "Some edge name"); Edge anotherEdgeBC = root.GetOrAddEdge(nodeB, nodeC, "Another edge name"); // We can attach attributes to nodes, edges and graphs to store information and instruct // graphviz by specifying layout parameters. At the moment we only support string // attributes. Cgraph assumes that all objects of a given kind (graphs/subgraphs, nodes, // or edges) have the same attributes. The attributes first have to be introduced for a // certain kind, before we can use it. Node.IntroduceAttribute(root, "my attribute", "defaultvalue"); nodeA.SetAttribute("my attribute", "othervalue"); // To introduce and set an attribute at the same time, there are convenience wrappers edgeAB.SafeSetAttribute("color", "red", "black"); edgeBC.SafeSetAttribute("arrowsize", "2.0", "1.0"); // We can simply export this graph to a text file in dot format root.ToDotFile(TestContext.CurrentContext.TestDirectory + "/out.dot"); }
public void TestTopologicalEqualsCloneWithSubgraphs(int nodes, int degree) { var root = CreateRandomConnectedGraph(nodes * SizeMultiplier, degree); var nodeSelection = new HashSet <Node>(root.Nodes().Take(nodes / 2)); var sub = root.AddSubgraphFromNodes("sub", nodeSelection); var subNodeCount = sub.Nodes().Count(); var nodeSelection2 = new HashSet <Node>(sub.Nodes().Take(subNodeCount / 2)); var sub2 = root.AddSubgraphFromNodes("sub2", nodeSelection2); var edgeCount = sub2.Edges().Count(); var edgeSelection = new HashSet <Edge>(sub.Edges().Take(edgeCount / 2)); var sub3 = root.AddSubgraphFromEdgeSet("sub3", edgeSelection); RootGraph subclone = sub.Clone("subclone"); Assert.IsTrue(GraphComparer.CheckTopologicallyEquals(sub, subclone, Log)); Assert.IsFalse(GraphComparer.CheckTopologicallyEquals(sub, root, Log)); Assert.IsFalse(GraphComparer.CheckTopologicallyEquals(sub, sub2, Log)); Assert.IsFalse(GraphComparer.CheckTopologicallyEquals(sub, sub3, Log)); RootGraph sub2clone = sub2.Clone("sub2clone"); Assert.IsTrue(GraphComparer.CheckTopologicallyEquals(sub2, sub2clone, Log)); Assert.IsFalse(GraphComparer.CheckTopologicallyEquals(sub2, root, Log)); Assert.IsFalse(GraphComparer.CheckTopologicallyEquals(sub2, sub, Log)); Assert.IsFalse(GraphComparer.CheckTopologicallyEquals(sub2, sub3, Log)); RootGraph sub3clone = sub3.Clone("sub3clone"); Assert.IsTrue(GraphComparer.CheckTopologicallyEquals(sub3, sub3clone, Log)); Assert.IsFalse(GraphComparer.CheckTopologicallyEquals(sub3, root, Log)); Assert.IsFalse(GraphComparer.CheckTopologicallyEquals(sub3, sub, Log)); Assert.IsFalse(GraphComparer.CheckTopologicallyEquals(sub3, sub2, Log)); }
public static RootGraph CreateRandomConnectedGraph(int size, double out_degree) { RootGraph root = CreateUniqueTestGraph(); // First generate a star of requested size Node centernode = root.GetOrAddNode(0.ToString()); for (int i = 1; i < size; i++) { var node = root.GetOrAddNode(i.ToString()); _ = root.GetOrAddEdge(centernode, node, $"{0} to {i}"); } // For each node pick requested number of random neighbors for (int i = 0; i < size; i++) { // We already have one out edge for each node for (int x = 0; x < out_degree - 2; x++) { var node = root.GetNode(i.ToString()); int j = rand.Next(size - 1); var neighbor = root.GetNode(j.ToString()); _ = root.GetOrAddEdge(node, neighbor, $"{i} to {j}"); } } return(root); }
public void TestAttributeDefaults() { { RootGraph root = Utils.CreateUniqueTestGraph(); Node.IntroduceAttribute(root, "label", ""); Node nodeA = root.GetOrAddNode("A"); Node nodeB = root.GetOrAddNode("B"); nodeA.SetAttribute("label", "1"); Assert.AreEqual("1", nodeA.GetAttribute("label")); Assert.AreEqual("", nodeB.GetAttribute("label")); root.ToDotFile(TestContext.CurrentContext.TestDirectory + "/out.gv"); } { var root = RootGraph.FromDotFile(TestContext.CurrentContext.TestDirectory + "/out.gv"); Node nodeA = root.GetNode("A"); Node nodeB = root.GetNode("B"); Assert.AreEqual("1", nodeA.GetAttribute("label")); Assert.AreEqual("", nodeB.GetAttribute("label")); root.ComputeLayout(); Assert.AreEqual("1", nodeA.GetAttribute("label")); Assert.AreEqual("", nodeB.GetAttribute("label")); root.ToSvgFile(TestContext.CurrentContext.TestDirectory + "/out.svg"); } // The empty label default is not exported, but that appears to be no problem here. The // default seems to become the empty string. However, dot.exe gives a different result. // When applying dot.exe on out.gv the default label is set to \N, which gives different // results entirely. // Related issue: https://gitlab.com/graphviz/graphviz/-/issues/1887 }
public void TestReadDotFile() { RootGraph root = RootGraph.FromDotString(@" digraph test { A; B; B -> B; A -> B[key = edgename]; A -> B; A -> B; } "); var edges = root.Edges().ToList(); var names = edges.Select(e => e.GetName()); // The attribute 'key' maps to the edgename Assert.IsTrue(names.Any(n => n == "edgename")); Assert.IsTrue(names.All(n => n == "edgename" || string.IsNullOrEmpty(n))); // However, it is strange that the other two edges both seem to have the same name, namely "" // According to the documentation, the name is used to distinguish between multi-edges var A = root.GetNode("A"); var B = root.GetNode("B"); Assert.AreEqual(3, A.EdgesOut().Count()); // The documentation seem to be correct for edges that are added through the C interface _ = root.GetOrAddEdge(A, B, ""); Assert.AreEqual(4, A.EdgesOut().Count()); _ = root.GetOrAddEdge(A, B, ""); Assert.AreEqual(4, A.EdgesOut().Count()); }
public void Layouting() { // If we have a given dot file, we can also simply read it back in RootGraph root = RootGraph.FromDotFile(TestContext.CurrentContext.TestDirectory + "/out.dot"); // Let's have graphviz compute a dot layout for us root.ComputeLayout(); // We can export this to svg root.ToSvgFile(TestContext.CurrentContext.TestDirectory + "/dot_out.svg"); // Or programatically read out the layout attributes Node nodeA = root.GetNode("A"); PointF position = nodeA.Position(); Assert.AreEqual("{X=43, Y=192.1739}", position.ToString()); // Like a bounding box of an object RectangleF nodeboundingbox = nodeA.BoundingBox(); Assert.AreEqual("{X=16,Y=171.3391,Width=54,Height=41.66957}", nodeboundingbox.ToString()); // Or splines between nodes Node nodeB = root.GetNode("B"); Edge edge = root.GetEdge(nodeA, nodeB, "Some edge name"); PointF[] spline = edge.FirstSpline(); string splineString = string.Join(", ", spline.Select(p => p.ToString())); string expectedSplineString = "{X=0, Y=0}, {X=43, Y=171.29}, {X=43, Y=163.45}," + " {X=43, Y=154.26}, {X=43, Y=145.63}"; Assert.AreEqual(expectedSplineString, splineString); GraphvizLabel nodeLabel = nodeA.GetLabel(); Assert.AreEqual("{X=36.25977,Y=181.4415,Width=13.48047,Height=21.46484}", nodeLabel.BoundingBox().ToString()); Assert.AreEqual("Times-Roman", nodeLabel.FontName().ToString()); SubGraph cluster = root.GetSubgraph("cluster_1"); RectangleF clusterbox = cluster.BoundingBox(); RectangleF rootgraphbox = root.BoundingBox(); Assert.AreEqual("{X=8,Y=8,Width=70,Height=135.34}", clusterbox.ToString()); Assert.AreEqual("{X=0,Y=0,Width=142,Height=213.01}", rootgraphbox.ToString()); // Once all layout information is obtained from the graph, the resources should be // reclaimed. To do this, the application should call the cleanup routine associated // with the layout algorithm used to draw the graph. This is done by a call to // FreeLayout(). A given graph can be laid out multiple times. The application, however, // must clean up the earlier layout's information with a call to FreeLayout before // invoking a new layout function. root.FreeLayout(); // We can use layout engines other than dot by explicitly passing the engine we want root.ComputeLayout(LayoutEngines.Neato); root.ToSvgFile(TestContext.CurrentContext.TestDirectory + "/neato_out.svg"); }
public void TestNodeAndGraphWithSameName() { RootGraph root = Utils.CreateUniqueTestGraph(); SubGraph sub = root.GetOrAddSubgraph("name"); Node node = sub.GetOrAddNode("name"); Assert.True(root.Contains(sub)); Assert.True(sub.Contains(node)); }
public void TestEdgeContraction() { //NativeMethods.AllocConsole(); RootGraph root = Utils.CreateUniqueTestGraph(); Node tail = root.GetOrAddNode("x"); Node head = root.GetOrAddNode("xx"); Node other = root.GetOrAddNode("xxx"); Edge contracted = root.GetOrAddEdge(tail, head, "tocontract"); Edge parallel = root.GetOrAddEdge(tail, head, "parallel"); Edge counterparallel = root.GetOrAddEdge(head, tail, "counterparallel"); Edge tailout = root.GetOrAddEdge(tail, other, "tailout"); Edge headout = root.GetOrAddEdge(head, other, "headout"); Edge tailin = root.GetOrAddEdge(other, tail, "tailin"); Edge headin = root.GetOrAddEdge(other, head, "headin"); foreach (Node n in root.Nodes()) { n.SafeSetAttribute("label", n.GetName(), "no"); n.SafeSetAttribute("fontname", "Arial", "Arial"); foreach (Edge e in n.EdgesOut()) { e.SafeSetAttribute("label", e.GetName(), "no"); e.SafeSetAttribute("fontname", "Arial", "Arial"); } } Assert.AreEqual(5, tail.TotalDegree()); Assert.AreEqual(5, head.TotalDegree()); Assert.AreEqual(3, root.Nodes().Count()); Node contraction = root.Contract(contracted, "contraction result"); foreach (Node n in root.Nodes()) { n.SafeSetAttribute("label", n.GetName(), "no"); n.SafeSetAttribute("fontname", "Arial", "Arial"); foreach (Edge e in n.EdgesOut()) { e.SafeSetAttribute("label", e.GetName(), "no"); e.SafeSetAttribute("fontname", "Arial", "Arial"); } } //Console.Read(); Assert.AreEqual(2, root.Nodes().Count()); Assert.AreEqual(2, contraction.InDegree()); Assert.AreEqual(2, contraction.OutDegree()); Assert.AreEqual(2, other.InDegree()); Assert.AreEqual(2, other.OutDegree()); }
public void Layouting() { // If we have a given dot file (in this case the one we generated above), we can also read it back in RootGraph root = RootGraph.FromDotFile(TestContext.CurrentContext.TestDirectory + "/out.dot"); // Let's have graphviz compute a dot layout for us root.ComputeLayout(); // We can export this to svg root.ToSvgFile(TestContext.CurrentContext.TestDirectory + "/dot_out.svg"); // Or programatically read out the layout attributes Node nodeA = root.GetNode("A"); PointF position = nodeA.Position(); Utils.AssertPattern(@"{X=[\d.]+, Y=[\d.]+}", position.ToString()); // Like a bounding box of an object RectangleF nodeboundingbox = nodeA.BoundingBox(); Utils.AssertPattern(@"{X=[\d.]+,Y=[\d.]+,Width=[\d.]+,Height=[\d.]+}", nodeboundingbox.ToString()); // Or splines between nodes Node nodeB = root.GetNode("B"); Edge edge = root.GetEdge(nodeA, nodeB, "Some edge name"); PointF[] spline = edge.FirstSpline(); string splineString = string.Join(", ", spline.Select(p => p.ToString())); string expectedSplinePattern = @"{X=[\d.]+, Y=[\d.]+}, {X=[\d.]+, Y=[\d.]+}, {X=[\d.]+, Y=[\d.]+}," + @" {X=[\d.]+, Y=[\d.]+}, {X=[\d.]+, Y=[\d.]+}"; Utils.AssertPattern(expectedSplinePattern, splineString); GraphvizLabel nodeLabel = nodeA.GetLabel(); Utils.AssertPattern(@"{X=[\d.]+,Y=[\d.]+,Width=[\d.]+,Height=[\d.]+}", nodeLabel.BoundingBox().ToString()); Utils.AssertPattern(@"Times-Roman", nodeLabel.FontName().ToString()); // Once all layout information is obtained from the graph, the resources should be // reclaimed. To do this, the application should call the cleanup routine associated // with the layout algorithm used to draw the graph. This is done by a call to // FreeLayout(). A given graph can be laid out multiple times. The application, however, // must clean up the earlier layout's information with a call to FreeLayout before // invoking a new layout function. root.FreeLayout(); // We can use layout engines other than dot by explicitly passing the engine we want root.ComputeLayout(LayoutEngines.Neato); root.ToSvgFile(TestContext.CurrentContext.TestDirectory + "/neato_out.svg"); }
public void TestLabelEscaping(bool escape) { string label1 = "|"; string label2 = @"\N\n\L"; string label3 = "3"; if (escape) { label1 = CGraphThing.EscapeLabel(label1); label2 = CGraphThing.EscapeLabel(label2); } { RootGraph root = CreateUniqueTestGraph(); Node node1 = root.GetOrAddNode("1"); node1.SafeSetAttribute("shape", "record", ""); node1.SafeSetAttribute("label", label1, ""); Node node2 = root.GetOrAddNode("2"); node2.SafeSetAttribute("label", label2, ""); Node node3 = root.GetOrAddNode("3"); node3.SafeSetAttribute("label", label3, ""); root.ToDotFile(GetTestFilePath("out.gv")); } { var root = RootGraph.FromDotFile(GetTestFilePath("out.gv")); Node node1 = root.GetNode("1"); Assert.That(node1.GetAttribute("label"), Is.EqualTo(label1)); Node node2 = root.GetNode("2"); Assert.That(node2.GetAttribute("label"), Is.EqualTo(label2)); Node node3 = root.GetNode("3"); Assert.That(node3.GetAttribute("label"), Is.EqualTo(label3)); root.ComputeLayout(); root.ToSvgFile(GetTestFilePath("out.svg")); root.ToDotFile(GetTestFilePath("out.dot")); var rects = node1.GetRecordRectangles(); if (escape) { Assert.That(rects.Count, Is.EqualTo(1)); Assert.That(node2.BoundingBox().Height, Is.EqualTo(node3.BoundingBox().Height)); } else { Assert.That(rects.Count, Is.EqualTo(2)); Assert.That(node2.BoundingBox().Height, Is.Not.EqualTo(node3.BoundingBox().Height)); } } }
public void Records() { RootGraph root = RootGraph.CreateNew("Graph with records", GraphType.Directed); Node nodeA = root.GetOrAddNode("A"); nodeA.SafeSetAttribute("shape", "record", ""); nodeA.SafeSetAttribute("label", "1|2|3|{4|5}|6|{7|8|9}", "\\N"); root.ComputeLayout(); // The order of the list matches the order in which the labels occur in the label string above. var rects = nodeA.GetRecordRectangles().ToList(); Assert.That(rects.Count, Is.EqualTo(9)); }
public void TestEmptyRecordShapes() { RootGraph root = CreateUniqueTestGraph(); Node nodeA = root.GetOrAddNode("A"); nodeA.SafeSetAttribute("shape", "record", ""); nodeA.SafeSetAttribute("label", "||||", ""); root.ComputeLayout(); var rects = nodeA.GetRecordRectangles().ToList(); Assert.That(rects.Count, Is.EqualTo(5)); root.ToSvgFile(GetTestFilePath("out.svg")); }
public void TestRecordShapeOrder() { RootGraph root = CreateUniqueTestGraph(); Node nodeA = root.GetOrAddNode("A"); nodeA.SafeSetAttribute("shape", "record", ""); nodeA.SafeSetAttribute("label", "1|2|3|{4|5}|6|{7|8|9}", "\\N"); root.ComputeLayout(); var rects = nodeA.GetRecordRectangles().ToList(); // Because Graphviz uses a lower-left originated coordinate system, we need to flip the y coordinates Utils.AssertOrder(rects, r => (r.Left, -r.Top)); Assert.That(rects.Count, Is.EqualTo(9)); }
public void TestPortNameConversion(bool escape) { string port1 = ">|<"; string port2 = "B"; if (escape) { port1 = Edge.ConvertUidToPortName(port1); port2 = Edge.ConvertUidToPortName(port2); } string label = $"{{<{port1}>1|<{port2}>2}}"; { RootGraph root = CreateUniqueTestGraph(); Node node = root.GetOrAddNode("N"); node.SafeSetAttribute("shape", "record", ""); node.SafeSetAttribute("label", label, ""); Edge edge = root.GetOrAddEdge(node, node, ""); edge.SafeSetAttribute("tailport", port1 + ":n", ""); edge.SafeSetAttribute("headport", port2 + ":s", ""); root.ToDotFile(GetTestFilePath("out.gv")); } { var root = RootGraph.FromDotFile(GetTestFilePath("out.gv")); Node node = root.GetNode("N"); Assert.That(node.GetAttribute("label"), Is.EqualTo(label)); Edge edge = root.Edges().First(); Assert.That(edge.GetAttribute("tailport"), Is.EqualTo(port1 + ":n")); Assert.That(edge.GetAttribute("headport"), Is.EqualTo(port2 + ":s")); root.ComputeLayout(); root.ToSvgFile(GetTestFilePath("out.svg")); root.ToDotFile(GetTestFilePath("out.dot")); var rects = node.GetRecordRectangles(); if (escape) { Assert.That(rects.Count, Is.EqualTo(2)); } else { Assert.That(rects.Count, Is.EqualTo(3)); } } }
public void TestSelfLoopEnumeration() { RootGraph graph = Utils.CreateUniqueTestGraph(); Node node = graph.GetOrAddNode("node 1"); Node node2 = graph.GetOrAddNode("node 2"); Edge edgein = graph.GetOrAddEdge(node2, node, "in"); Edge edgeout = graph.GetOrAddEdge(node, node2, "out"); Edge edgeself = graph.GetOrAddEdge(node, node, "self"); Assert.AreEqual(2, node.InDegree()); Assert.AreEqual(2, node.OutDegree()); Assert.AreEqual(4, node.TotalDegree()); Assert.AreEqual(2, node.EdgesIn().Count()); Assert.AreEqual(2, node.EdgesOut().Count()); Assert.AreEqual(3, node.Edges().Count()); }
public void TestCopyAttributes() { RootGraph root = Utils.CreateUniqueTestGraph(); Node n1 = root.GetOrAddNode("1"); Node.IntroduceAttribute(root, "test", "foo"); Assert.AreEqual("foo", n1.GetAttribute("test")); n1.SetAttribute("test", "bar"); Assert.AreEqual("bar", n1.GetAttribute("test")); RootGraph root2 = Utils.CreateUniqueTestGraph(); Node n2 = root2.GetOrAddNode("2"); Assert.AreEqual(null, n2.GetAttribute("test")); Assert.AreEqual(0, n1.CopyAttributesTo(n2)); Assert.AreEqual("bar", n2.GetAttribute("test")); }
public void TestCreateNestedStructures() { // Documentation: // Subgraphs are an important construct in Cgraph.They are intended for organizing subsets of // graph objects and can be used interchangeably with top - level graphs in almost all Cgraph // functions. A subgraph may contain any nodes or edges of its parent. (When an edge is // inserted in a subgraph, its nodes are also implicitly inserted if necessary.Similarly, // insertion of a node or edge automatically implies insertion in all containing subgraphs up // to the root.) Subgraphs of a graph form a hierarchy(a tree).Cgraph has functions to // create, search, and iterate over subgraphs. // Conclusion: the hierarchical tree structure is maintained in a sane way across all // operations we can do w.r.t. subgraphs. // If a node is created in a subgraph, it should also be contained in all supergraphs RootGraph graph = Utils.CreateUniqueTestGraph(); SubGraph supergraph = graph.GetOrAddSubgraph("level 1"); string subgraphname = "level 2"; SubGraph subgraph = supergraph.GetOrAddSubgraph(subgraphname); string nodename = "test node"; Node node = subgraph.GetOrAddNode(nodename); // Node must be contained in super graph Assert.True(node.MyRootGraph.Equals(graph)); Assert.True(supergraph.Contains(node)); Assert.True(supergraph.Nodes().Contains(node)); Assert.NotNull(supergraph.GetNode(nodename)); // Node must be contained in root graph Assert.True(graph.Contains(node)); Assert.True(graph.Nodes().Contains(node)); Assert.NotNull(graph.GetNode(nodename)); // Subgraph must be contained in super graph Assert.True(supergraph.Contains(subgraph)); Assert.True(supergraph.Descendants().Contains(subgraph)); Assert.NotNull(supergraph.GetSubgraph(subgraphname)); // Subgraph must be contained in root graph Assert.True(graph.Contains(subgraph)); Assert.True(graph.Descendants().Contains(subgraph)); // Subgraph cannot be obtained in the following way: //graph.GetSubgraph(subgraphname) Assert.Null(graph.GetSubgraph(subgraphname)); // Use a utility function instead: Assert.NotNull(graph.GetDescendantByName(subgraphname)); }
public void TestCopyToNewRoot() { RootGraph root = Utils.CreateUniqueTestGraph(); Node n1 = root.GetOrAddNode("1"); Node.IntroduceAttribute(root, "test", "foo"); Assert.AreEqual("foo", n1.GetAttribute("test")); n1.SetAttribute("test", "bar"); Assert.AreEqual("bar", n1.GetAttribute("test")); RootGraph root2 = Utils.CreateUniqueTestGraph(); Node.IntroduceAttribute(root2, "test", "foo"); Node n2 = n1.CopyToOtherRoot(root2); Assert.AreEqual("1", n2.GetName()); Assert.AreEqual("bar", n2.GetAttribute("test")); }
private void InitMetaData() { var rootText = Resources.Load <TextAsset>("meta/root" + SceneManager.GetActiveScene().name); var docStream = new StringReader(rootText.text); RootGraph root = RootGraph.Construct(docStream); foreach (var clip in root.Clips) { //load clip var clipText = Resources.Load <TextAsset>("meta/" + clip.Path); var clipDocStream = new StringReader(clipText.text); ClipTree clipGraph = ClipTree.Construct(clipDocStream); var ser = new YamlDotNet.Serialization.Serializer(); clipGraphs.Add(clip.Name, clipGraph); var midiFile = Resources.Load <TextAsset>("clips/" + clipGraph.Midi); Debug.Log(clipGraph.Midi); AudioSource audioSource = AddAudioSourceToScene(clipGraph.Audio); //parse midi Midi midi = new MidiParser().Parse(midiFile.bytes); //debug Debug.Log(midi.Tracks[2].Bpm); foreach (var msg in midi.Tracks[2].Messages) { Debug.Log(msg); } Debug.Log(ser.Serialize(clipGraph)); clips.Add(clip.Name, new Assets.Core.Clip(audioSource, midi)); } foreach (var graph in root.Scriptgraphs) { var graphText = Resources.Load <TextAsset>("meta/" + graph.Path); Debug.Log(graphText); var graphDocStream = new StringReader(graphText.text); ScriptTree scriptGraph = ScriptTree.Construct(graphDocStream); var ser = new YamlDotNet.Serialization.Serializer(); scriptGraphs.Add(graph.Name, scriptGraph); Debug.Log("Constructed a script graph : " + graph.Name); Debug.Log(ser.Serialize(scriptGraph)); } }
public void TestHtmlLabelsDefault() { RootGraph root = CreateUniqueTestGraph(); const string labelKey = "label"; Node.IntroduceAttributeHtml(root, labelKey, "<html default>"); Node n1 = root.GetOrAddNode("1"); Node n2 = root.GetOrAddNode("2"); Node n3 = root.GetOrAddNode("3"); n1.SetAttribute(labelKey, "plain 1"); n2.SetAttributeHtml(labelKey, "<html 2>"); var result = root.ToDotString(); Assert.That(result, Does.Contain("\"plain 1\"")); AssertContainsHtml(result, "<html 2>"); AssertContainsHtml(result, "<html default>"); }
public void TestEdgeEquals() { RootGraph graph = Utils.CreateUniqueTestGraph(); Node node = graph.GetOrAddNode("node 1"); Node node2 = graph.GetOrAddNode("node 2"); Node node3 = graph.GetOrAddNode("node 3"); Edge edge = graph.GetOrAddEdge(node, node, "edge 1"); Edge edge2 = graph.GetOrAddEdge(node, node, "edge 2"); Edge edge3 = graph.GetOrAddEdge(node, node2, "edge 3"); Edge edge4 = graph.GetOrAddEdge(node2, node3, "edge 4"); Assert.AreEqual(edge, edge); Assert.AreNotEqual(edge, edge2); Assert.AreNotEqual(edge, edge3); Assert.AreNotEqual(edge, edge4); Assert.AreEqual(edge.GetHashCode(), edge.GetHashCode()); Assert.AreNotEqual(edge.GetHashCode(), edge2.GetHashCode()); Assert.AreNotEqual(edge.GetHashCode(), edge3.GetHashCode()); Assert.AreNotEqual(edge.GetHashCode(), edge4.GetHashCode()); }
public void TestAttributeIntroduction() { RootGraph root = Utils.CreateUniqueTestGraph(); Graph.IntroduceAttribute(root, "test", "default"); root.SetAttribute("test", "1"); Assert.AreEqual("1", root.GetAttribute("test")); Graph.IntroduceAttribute(root, "test", "default"); // Now the value has been reset! Assert.AreEqual("default", root.GetAttribute("test")); // This is not the case for nodes Node node = root.GetOrAddNode("nodename"); Node.IntroduceAttribute(root, "test", "default"); node.SetAttribute("test", "1"); Assert.AreEqual("1", node.GetAttribute("test")); Node.IntroduceAttribute(root, "test", "default"); Assert.AreEqual("1", node.GetAttribute("test")); }
// Use only in editor mode public static void SaveScripts(string name, ScriptTree tree) { var rootText = Resources.Load <TextAsset>("meta/root"); var docStream = new StringReader(rootText.text); RootGraph root = RootGraph.Construct(docStream); var scriptGraph = root.Scriptgraphs.Find(sg => sg.Name == name); string fullPath = path + scriptGraph.Path + ".yaml"; var sr = new YamlDotNet.Serialization.SerializerBuilder() .WithNamingConvention(new YamlDotNet.Serialization.NamingConventions.CamelCaseNamingConvention()) .Build(); using (FileStream fs = new FileStream(fullPath, FileMode.Create)) { using (StreamWriter writer = new StreamWriter(fs)) { writer.Write(sr.Serialize(tree)); } } UnityEditor.AssetDatabase.Refresh(); }
public void TestReadDotFile() { RootGraph root = RootGraph.FromDotString(@" digraph test { A; B; B -> B; A -> B[name = edgename]; A -> B[name = edgename]; A -> B[name = edgename]; } "); var A = root.GetNode("A"); Assert.AreEqual(3, A.EdgesOut().Count()); var B = root.GetNode("B"); _ = root.GetOrAddEdge(A, B, ""); Assert.AreEqual(4, A.EdgesOut().Count()); }
public void TestNonStrictGraph() { RootGraph graph = Utils.CreateUniqueTestGraph(); Assert.False(graph.IsStrict()); Assert.False(graph.IsUndirected()); Assert.True(graph.IsDirected()); Node node = graph.GetOrAddNode("node 1"); Node node2 = graph.GetOrAddNode("node 2"); Edge edge = graph.GetOrAddEdge(node, node, "edge 1"); Edge edge2 = graph.GetOrAddEdge(node, node, "edge 2"); Assert.AreNotEqual(edge.GetName(), edge2.GetName()); Edge edge3 = graph.GetOrAddEdge(node, node2, "edge 3"); Edge edge4 = graph.GetOrAddEdge(node, node2, "edge 4"); Assert.AreNotEqual(edge3.GetName(), edge4.GetName()); }
public void Clusters() { RootGraph root = RootGraph.CreateNew("Graph with clusters", GraphType.Directed); Node nodeA = root.GetOrAddNode("A"); Node nodeB = root.GetOrAddNode("B"); Node nodeC = root.GetOrAddNode("C"); Node nodeD = root.GetOrAddNode("D"); // When a subgraph name is prefixed with cluster, // the dot layout engine will render it as a box around the containing nodes. SubGraph cluster1 = root.GetOrAddSubgraph("cluster_1"); cluster1.AddExisting(nodeB); cluster1.AddExisting(nodeC); SubGraph cluster2 = root.GetOrAddSubgraph("cluster_2"); cluster2.AddExisting(nodeD); // COMPOUND EDGES // Graphviz does not really support edges from and to clusters. However, by adding an // invisible dummynode and setting the ltail or lhead attributes of an edge this // behavior can be faked. Graphviz will then draw an edge to the dummy node but clip it // at the border of the cluster. We provide convenience methods for this. // To enable this feature, Graphviz requires us to set the "compound" attribute to "true". Graph.IntroduceAttribute(root, "compound", "true"); // Allow lhead/ltail // The boolean indicates whether the dummy node should take up any space. When you pass // false and you have a lot of edges, the edges may start to overlap a lot. _ = root.GetOrAddEdge(nodeA, cluster1, false, "edge to a cluster"); _ = root.GetOrAddEdge(cluster1, nodeD, false, "edge from a cluster"); _ = root.GetOrAddEdge(cluster1, cluster1, false, "edge between clusters"); root.ComputeLayout(); SubGraph cluster = root.GetSubgraph("cluster_1"); RectangleF clusterbox = cluster.BoundingBox(); RectangleF rootgraphbox = root.BoundingBox(); Utils.AssertPattern(@"{X=[\d.]+,Y=[\d.]+,Width=[\d.]+,Height=[\d.]+}", clusterbox.ToString()); Utils.AssertPattern(@"{X=[\d.]+,Y=[\d.]+,Width=[\d.]+,Height=[\d.]+}", rootgraphbox.ToString()); }
public Form2() { InitializeComponent(); /* string DotFilePath = String.Format(@"C:\Users\Zenith\AppData\Roaming\HNClusterUI\HNClusterUI\1.0.0.0\DOTFILE - Copy - Copy.dot"); //graph.ToDotFile(DotFilePath); DOT dotfile2 = new DOT(); string DotFile1 = File.ReadAllText(DotFilePath); string svg2 = dotfile2.ToSvg(DotFile1); return;*/ this.MouseWheel += new System.Windows.Forms.MouseEventHandler(Form2_MouseWheel); this.KeyDown += Form2_KeyDown_KeyUp; this.KeyUp += Form2_KeyDown_KeyUp; this.KeyPreview = true; webBrowser1.WebBrowserShortcutsEnabled = false; webBrowser1.IsWebBrowserContextMenuEnabled = false; webBrowser1.PreviewKeyDown += webBrowser1_PreviewKeyDown; Control c = webBrowser1; c.KeyDown += Form2_KeyDown_KeyUp; c.KeyUp += Form2_KeyDown_KeyUp; //c.Enabled = false; /* foreach (Control control in this.Controls) { control.KeyDown += new KeyEventHandler(Form2_KeyDown_KeyUp); control.KeyUp += new KeyEventHandler(Form2_KeyDown_KeyUp); //control.KeyPress += new KeyEventHandler(Form2_KeyDown_KeyUp); }*/ graph = new Xglore.Plugin.Graphviz.RootGraph("Clusters", false, false); string MainNode = " _3D.P–r,i:nt–ing'L13_01111111101-- 010Noro–Frenkel_law_of_corresponding___stat&es+ "; AddNode(MainNode); AddNode("0"); AddNode("00"); AddNode("000"); AddNode("001"); AddNode("01"); AddNode("010"); AddNode("011"); AddNode("1"); AddNode("10"); AddNode("100"); AddNode("101"); AddNode("11"); AddNode("110"); AddNode("111"); AddEdge(MainNode, "0"); AddEdge(MainNode, "1"); AddEdge("0", "00"); AddEdge("00", "000"); AddEdge("00", "001"); AddEdge("0", "01"); AddEdge("01", "010"); AddEdge("01", "011"); AddEdge("1", "10"); AddEdge("10", "100"); AddEdge("10", "101"); AddEdge("1", "11"); AddEdge("11", "110"); AddEdge("11", "111"); for (int i = 0; i < 10; ++i) { AddNode(i.ToString()); } for (int x = 0; x < 10; ++x) { for (int y = x; y < 10; ++y) { if (x != y) AddEdge(x.ToString(), y.ToString()); } } string dotPath = String.Format("{0}\\DOTFILE.dot", Application.UserAppDataPath); graph.ToDotFile(dotPath); DOT dotfile = new DOT(); string strBlah3 = System.IO.File.ReadAllText(dotPath); string svg = dotfile.ToSvg(strBlah3); System.IO.File.WriteAllText(String.Format("{0}\\SVG.svg", Application.UserAppDataPath), svg); //webBrowser1.Url = new Uri(@"C:\Users\Zenith\Documents\GitHub\Wikipedia-Clustering\HNCluster\HNCluster\bin\Debug\" + "SVG.svg"); Uri url = new Uri(String.Format("{0}\\SVG.svg", Application.UserAppDataPath)); webBrowser1.Url = url; XDocument doc = XDocument.Parse(svg); SVGFile = (XElement)doc.LastNode; //SVGFile = XDocument.Parse(svg).Element("svg"); this.Focus(); }
public GraphDisplay() { InitializeComponent(); graph = new RootGraph("Clusters", true, true); url = new Uri(SVGFilePath); }