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 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()); }