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 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");
        }
Beispiel #3
0
        protected override PlacementInfo PositionComponents(Dictionary <FIRRTLNode, Point> nodeSizes, Module mod)
        {
            PlacementInfo placments = new PlacementInfo();

            const int dpi = 96;
            const int ppi = 72;

            RootGraph graph = RootGraph.CreateNew("some name??", GraphType.Directed);

            graph.SafeSetAttribute("rankdir", "LR", "TB");
            graph.SafeSetAttribute("ranksep", "7", "0.5");
            graph.SafeSetAttribute("nodesep", "1.0", "0.25");

            //Add nodes to graph
            Dictionary <FIRRTLNode, Node> firNodeToNode = new Dictionary <FIRRTLNode, Node>();
            Dictionary <Input, string>    inputToPort   = new Dictionary <Input, string>();
            Dictionary <Output, string>   outputToPort  = new Dictionary <Output, string>();
            Dictionary <Input, Node>      inputToNode   = new Dictionary <Input, Node>();
            Dictionary <Output, Node>     outputToNode  = new Dictionary <Output, Node>();
            int nodeCounter = 0;
            int portName    = 0;

            foreach (var firNode in nodeSizes)
            {
                if (firNode.Key == mod)
                {
                    continue;
                }

                string nodeName = $"n{nodeCounter++}";
                Node   node     = graph.GetOrAddNode(nodeName);
                node.SafeSetAttribute("shape", "record", "ellipse");
                node.SafeSetAttribute("width", ((double)firNode.Value.X / dpi).ToString(), "0.75");
                node.SafeSetAttribute("height", ((double)firNode.Value.Y / dpi).ToString(), "0.5");

                Input[]  nodeInputs  = firNode.Key.GetInputs();
                Output[] nodeOutputs = firNode.Key.GetOutputs();

                MakeIntoRecord(node, nodeInputs, nodeOutputs, inputToPort, outputToPort, ref portName);

                firNodeToNode.Add(firNode.Key, node);

                foreach (var input in nodeInputs)
                {
                    inputToNode.Add(input, node);
                }
                foreach (var output in nodeOutputs)
                {
                    outputToNode.Add(output, node);
                }
            }

            Node modInputNode = graph.GetOrAddNode("modInput");

            MakeIntoRecord(modInputNode, mod.GetInputs(), Array.Empty <Output>(), inputToPort, outputToPort, ref portName);
            modInputNode.SafeSetAttribute("rank", "sink", "sink");

            Node modOutputNode = graph.GetOrAddNode("modOutput");

            MakeIntoRecord(modInputNode, Array.Empty <Input>(), mod.GetOutputs(), inputToPort, outputToPort, ref portName);
            modOutputNode.SafeSetAttribute("rank", "source", "source");

            //Make edges
            int edgeCounter = 0;

            foreach (Output output in outputToNode.Keys)
            {
                if (!output.IsConnectedToAnything())
                {
                    continue;
                }
                var from = outputToNode[output];
                foreach (var input in output.GetConnectedInputs())
                {
                    if (input.Node != null && input.Node is INoPlaceAndRoute)
                    {
                        continue;
                    }

                    if (!inputToNode.ContainsKey(input))
                    {
                        continue;
                    }
                    var to   = inputToNode[input];
                    var edge = graph.GetOrAddEdge(from, to, (edgeCounter++).ToString());
                    edge.SafeSetAttribute("tailport", outputToPort[output], " ");
                    edge.SafeSetAttribute("headport", inputToPort[input], " ");
                }
            }

            graph.ComputeLayout();

            Dictionary <FIRRTLNode, Rectangle> firNodeRects = new Dictionary <FIRRTLNode, Rectangle>();

            foreach (var firToVizNode in firNodeToNode)
            {
                var centerF = firToVizNode.Value.Position();
                var center  = new Point((int)(centerF.X * dpi), (int)(centerF.Y * dpi)) / ppi;

                var nodeSize = nodeSizes[firToVizNode.Key];
                var topLeft  = center - (nodeSize / 2);

                firNodeRects.Add(firToVizNode.Key, new Rectangle(topLeft, nodeSize));
            }
            graph.FreeLayout();

            Point min = new Point(int.MaxValue, int.MaxValue);

            foreach (var rect in firNodeRects.Values)
            {
                min = Point.Min(min, rect.Pos);
            }

            Point offsetBy = min.Abs();

            foreach (var firRect in firNodeRects)
            {
                placments.AddNodePlacement(firRect.Key, new Rectangle(offsetBy + firRect.Value.Pos, firRect.Value.Size));
            }

            Point borderPadding = new Point(100, 200);

            placments.AutoSpacePlacementRanks(mod);
            placments.AddBorderPadding(borderPadding);
            return(placments);
        }