Exemple #1
1
        private void SetGraph()
        {
            var graph = new Graph();
            graph.AddEdge("a", "b");
            graph.AddEdge("e", "b");
            graph.AddEdge("d", "b");
            graph.AddEdge("b", "c");

            graph.AddEdge("a22", "b22");
            graph.AddEdge("e22", "b22");
            graph.AddEdge("d22", "b22");
            graph.AddEdge("b22", "c22");

            graph.AddEdge("a0", "b0");
            graph.AddEdge("b0", "c0");

            graph.AddEdge("a33", "b33");
            graph.AddEdge("e33", "b33");
            graph.AddEdge("d33", "b33");
            graph.AddEdge("b33", "c33");

            graph.AddEdge("a11", "b11");
            graph.AddEdge("b11", "c11").LabelText = "Test labels!";

            graph.CreateGeometryGraph();
            foreach (Node node in graph.Nodes)
                node.GeometryNode.BoundaryCurve = CreateLabelAndBoundary(node);

            foreach (var edge in graph.Edges) {
                if (edge.Label != null) {
                    var geomEdge = edge.GeometryEdge;
                    double width;
                    double height;
                    StringMeasure.MeasureWithFont(edge.LabelText,
                                                  new Font(edge.Label.FontName, (float)edge.Label.FontSize), out width, out height);
                    edge.Label.GeometryLabel=geomEdge.Label = new Label(width, height, geomEdge);
                }

            }

            var geomGraph=graph.GeometryGraph;

            var geomGraphComponents = GraphConnectedComponents.CreateComponents(geomGraph.Nodes, geomGraph.Edges);
            var settings = new SugiyamaLayoutSettings();
            foreach (var subgraph in geomGraphComponents) {

                var layout=new LayeredLayout(subgraph, settings);
                subgraph.Margins = settings.NodeSeparation/2;
                layout.Run();

            }

               Microsoft.Msagl.Layout.MDS.MdsGraphLayout.PackGraphs(geomGraphComponents, settings);

            geomGraph.UpdateBoundingBox();

            gViewer1.NeedToCalculateLayout = false;
            gViewer1.Graph = graph;
        }
        public void MinimumSizeIsRespected()
        {
            // Setup
            string filePath = Path.Combine(this.TestContext.TestDir, "Out\\Dots", "chat.dot");
            GeometryGraph graph = this.LoadGraph(filePath);

            const double DesiredHeight = 100000;
            const double DesiredWidth = 100000;

            SugiyamaLayoutSettings settings = new SugiyamaLayoutSettings();
            settings.MinimalHeight = DesiredHeight;
            settings.MinimalWidth = DesiredWidth;
            
            // Execute
            LayeredLayout layeredLayout = new LayeredLayout(graph, settings);
            layeredLayout.Run();

            // Verify the graph is the correct size
            Assert.IsTrue(DesiredHeight < graph.Height, "Graph height should be the minimal height.");
            Assert.IsTrue(DesiredWidth < graph.Width, "Graph width should be the minimal width.");

            // Verify the nodes were spread apart to fill the space
            Rectangle nodeBounds = new Rectangle(graph.Nodes.Select(n => n.BoundingBox));
            Assert.IsTrue(DesiredWidth < nodeBounds.Height, "The graph nodes weren't scaled vertically to fill the space.");
            Assert.IsTrue(DesiredWidth < nodeBounds.Width, "The graph nodes weren't scaled horizontally to fill the space.");
        }
        public void NodeShapeChange()
        {
            // Setup
            string filePath = Path.Combine(this.TestContext.TestDir, "Out\\Dots", "chat.dot");
            GeometryGraph graph = this.LoadGraph(filePath);
            var settings = new SugiyamaLayoutSettings();

            // Initial layout
            LayeredLayout layeredLayout = new LayeredLayout(graph, settings);
            layeredLayout.Run();
            SortedList<double, SortedList<double, Node>> originalLayers = SugiyamaValidation.GetLayers(graph, true);

            // Incremental layout
            List<Node> nodes = graph.Nodes.ToList();
            for (int i = 0; i < nodes.Count; i++)
            {
                // Resize a node
                Node node = nodes[i];
                node.BoundaryCurve = node.BoundaryCurve.ScaleFromOrigin(2.0, 2.0);

                // Run incremental layout
                LayeredLayout.IncrementalLayout(graph, node);
                
                // Verify - the layering and ordering of nodes should not have changed.
                SortedList<double, SortedList<double, Node>> newLayers = SugiyamaValidation.GetLayers(graph, true);
                VerifyLayersAreEqual(originalLayers, newLayers);
            }
        }
        public void TallRatioSimpleStretch()
        {
            // Setup
            string filePath = Path.Combine(this.TestContext.TestDir, "Out\\Dots", "chat.dot");
            GeometryGraph graph = this.LoadGraph(filePath);
            SugiyamaLayoutSettings settings = new SugiyamaLayoutSettings();
            settings.AspectRatio = 0.25;
        
            // Execute
            LayeredLayout layeredLayout = new LayeredLayout(graph, settings);
            layeredLayout.Run();

            // Verify
            VerifyAspectRatio(graph, settings.AspectRatio);
        }
        internal static 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;
        }
        public void LabelsNearEdges()
        {
            // Setup
            string filePath = Path.Combine(this.TestContext.TestDir, "Out\\Dots", "chat.dot");

            GeometryGraph graph = this.LoadGraph(filePath);
            AddLabelSizes(graph);
            Assert.IsTrue(graph.CollectAllLabels().Count > 0, "The loaded graph has no labels.");

            // Execute
            LayeredLayout layeredLayout = new LayeredLayout(graph, new SugiyamaLayoutSettings());
            layeredLayout.Run();

            // Verify
            foreach (Edge edge in graph.Edges)
            {
                VerifyLabelIsNearEdges(edge);

                // We do not verify that labels don't overlap other edges, 
                // since that is not gauranteed by sugiyama layout.
            }
        }
        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 void TestGraphWithConstraints() {
            var graph = new GeometryGraph();

            var closed = new Node(CreateEllipse(), "closed");
            var line = new Node(CreateEllipse(), "line");
            var bezier = new Node(CreateEllipse(), "bezier");
            var arc = new Node(CreateEllipse(), "arc");
            var rectangle = new Node(CreateEllipse(), "rectangle");
            var ellipse = new Node(CreateEllipse(), "ellipse");
            var polygon = new Node(CreateEllipse(), "polygon");
            var shapes = new Node(CreateEllipse(), "shapes");
            var open = new Node(CreateEllipse(), "open");
            graph.Nodes.Add(closed);
            graph.Nodes.Add(line);
            graph.Nodes.Add(bezier);
            graph.Nodes.Add(arc);
            graph.Nodes.Add(rectangle);
            graph.Nodes.Add(ellipse);
            graph.Nodes.Add(polygon);
            graph.Nodes.Add(shapes);
            graph.Nodes.Add(open);

            var so = new Edge(shapes, open);
            var sc = new Edge(shapes, closed);
            var ol = new Edge(open, line);
            var ob = new Edge(open, bezier);
            var oa = new Edge(open, arc);
            var cr = new Edge(closed, rectangle);
            var ce = new Edge(closed, ellipse);
            var cp = new Edge(closed, polygon);
            graph.Edges.Add(so);
            graph.Edges.Add(sc);
            graph.Edges.Add(ol);
            graph.Edges.Add(ob);
            graph.Edges.Add(oa);
            graph.Edges.Add(cr);
            graph.Edges.Add(ce);
            graph.Edges.Add(cp);

            var settings = new SugiyamaLayoutSettings();
            settings.AddUpDownVerticalConstraint(closed, ellipse);
            settings.AddUpDownVerticalConstraint(open, bezier);
            settings.AddUpDownConstraint(closed, open);
            settings.AddSameLayerNeighbors(polygon, open);
            settings.AddLeftRightConstraint(closed, open);
            settings.AddLeftRightConstraint(open, closed);

            ////To verify 444585, just turn on this following commented line
            settings.AddLeftRightConstraint(ellipse, rectangle);
            settings.AddLeftRightConstraint(ellipse, bezier);

            var layeredLayout = new LayeredLayout(graph, settings);
            layeredLayout.Run();
#if DEBUG
            DisplayGeometryGraph.ShowGraph(graph);
#endif
        }
                public static void TreeWithConstraints() {
            var graph = new GeometryGraph();

            var closed = new Node(CreateEllipse(), "clos");
            var line = new Node(CreateEllipse(), "line");
            var bezier = new Node(CreateEllipse(), "bezi");
            var arc = new Node(CreateEllipse(), "arc");
            var rectangle = new Node(CreateEllipse(), "rect");
            var ellipse = new Node(CreateEllipse(), "elli");
            var polygon = new Node(CreateEllipse(), "poly");
            var shapes = new Node(CreateEllipse(), "shap");
            var open = new Node(CreateEllipse(), "open");
            graph.Nodes.Add(closed);
            graph.Nodes.Add(line);
            graph.Nodes.Add(bezier);
            graph.Nodes.Add(arc);
            graph.Nodes.Add(rectangle);
            graph.Nodes.Add(ellipse);
            graph.Nodes.Add(polygon);
            graph.Nodes.Add(shapes);
            graph.Nodes.Add(open);

            var so = new Edge(shapes, open);
            var sc = new Edge(shapes, closed);
            var ol = new Edge(open, line);
            var ob = new Edge(open, bezier);
            var oa = new Edge(open, arc);
            var cr = new Edge(closed, rectangle);
            var ce = new Edge(closed, ellipse);
            var cp = new Edge(closed, polygon);
            graph.Edges.Add(so);
            graph.Edges.Add(sc);
            graph.Edges.Add(ol);
            graph.Edges.Add(ob);
            graph.Edges.Add(oa);
            graph.Edges.Add(cr);
            graph.Edges.Add(ce);
            graph.Edges.Add(cp);

            var settings = new SugiyamaLayoutSettings();
            settings.AddUpDownVerticalConstraint(closed, ellipse);
            settings.AddUpDownVerticalConstraint(open, bezier);
            settings.AddUpDownConstraint(closed, open);
            settings.AddSameLayerNeighbors(polygon, open);
            settings.AddLeftRightConstraint(closed, open);

            settings.AddUpDownConstraint(closed, open);
            //settings.AddSameLayerNeighbors(polygon, open);
            settings.AddLeftRightConstraint(closed, open);

            //To verify 444585, just turn on this following commented line
            settings.AddLeftRightConstraint(ellipse, rectangle);
            settings.AddLeftRightConstraint(ellipse, bezier);

            var layeredLayout = new LayeredLayout(graph, settings);
            layeredLayout.Run();
#if DEBUG
            LayoutAlgorithmSettings.ShowGraph(graph);
#endif

            Debug.Assert(Math.Abs(closed.Center.X - ellipse.Center.X) < 0.01);
            Debug.Assert(Math.Abs(open.Center.X - bezier.Center.X) < 0.01);

            foreach (Node n0 in graph.Nodes) {
                foreach (Node n1 in graph.Nodes) {
                    if (n0 == n1) {
                        continue;
                    }
                    Debug.Assert(!n0.BoundingBox.Intersects(n1.BoundingBox));
                }
            }

            ValidateUpDownVerticalConstraint(closed, ellipse);
            ValidateUpDownVerticalConstraint(open, bezier);
            ValidateUpDownConstraint(closed, open);
            ValidateNeighborConstraint(graph, polygon, open);
            ValidateLeftRightConstraint(closed, open);

            //To verify 444585, also turn on this following commented line
            ValidateLeftRightConstraint(ellipse, rectangle);
            ValidateLeftRightConstraint(ellipse, bezier);
        }
        static void LayerSeparationWithTransform() {
            GeometryGraph graph = GeometryGraphReader.CreateFromFile("c:/tmp/wrongLayout.msagl.geom");
            var settings = new SugiyamaLayoutSettings();
            settings.Transformation = PlaneTransformation.Rotation(-Math.PI/2);
            var layeredLayout = new LayeredLayout(graph, settings);
            layeredLayout.Run();
            //   LayoutHelpers.CalculateLayout(graph, settings);
            GeometryGraphWriter.Write(graph, "c:\\tmp\\correctLayout");
#if DEBUG
            LayoutAlgorithmSettings.ShowGraph(graph);
#endif
        }
        static void TestConstraints() {
            var gg = new GeometryGraph();

            var node1 = new Node {GeometryParent = gg};
            node1.BoundaryCurve =CurveFactory.CreateEllipse(20.0,10.0,new Point(0.0, 0.0));
            gg.Nodes.Add(node1);

            var node2 = new Node {GeometryParent = gg};
            node2.BoundaryCurve =
                CurveFactory.CreateEllipse(20.0,10.0,new Point(0.0, 0.0));
            gg.Nodes.Add(node2);

            var edge = new Edge(node1,node2) {GeometryParent = gg};
            gg.Edges.Add(edge);
            edge.Label = new Label {GeometryParent = edge,
                //need to set the label dimensions, otherwise the assertion is thrown
                Width = 10, Height = 10
            };
            //node1.AddOutEdge(edge); //the edges have been already added to the nodes in gg.Edges.Add(edge)
            //node2.AddInEdge(edge);

            var settings = new SugiyamaLayoutSettings();
            settings.AddSameLayerNeighbors(node1, node2);
            var layoutAlgorithm = new
                LayeredLayout(gg, settings);
            layoutAlgorithm.Run();
#if TEST_MSAGL
            LayoutAlgorithmSettings.ShowGraph(gg);
#endif
            Environment.Exit(0);
        }
        public void ConstraintWithTransformation()
        {
            Random random = new Random(999);

            GeometryGraph graph = GraphGenerator.GenerateOneSimpleGraph();            
            GraphGenerator.SetRandomNodeShapes(graph, random);
            SugiyamaLayoutSettings settings = new SugiyamaLayoutSettings();

            //layer direction to be left to right
            settings.Transformation = PlaneTransformation.Rotation(Math.PI / 2);

            List<Node> nodes = graph.Nodes.ToList();

            settings.AddUpDownConstraint(nodes[0], nodes[1]);
            settings.AddLeftRightConstraint(nodes[3], nodes[4]);
            settings.AddUpDownVerticalConstraint(nodes[0], nodes[3]);
            settings.AddSameLayerNeighbors(nodes[2], nodes[4]);

            LayeredLayout layeredLayout = new LayeredLayout(graph, settings);
            layeredLayout.Run();

            ShowGraphInDebugViewer(graph);

            SugiyamaValidation.ValidateUpDownConstraint(nodes[0], nodes[1]);
            SugiyamaValidation.ValidateLeftRightConstraint(nodes[3], nodes[4]);
            SugiyamaValidation.ValidateUpDownVerticalConstraint(nodes[0], nodes[3]);
            SugiyamaValidation.ValidateNeighborConstraint(graph, nodes[2], nodes[4], settings);
        }
        private static void LayoutAndValidate(GeometryGraph graph, SugiyamaLayoutSettings settings, double nodeSeparation, double layerSeparation, LayerDirection direction)
        {
            settings.NodeSeparation = nodeSeparation;
            
            switch (direction)
            {
                case LayerDirection.None:
                case LayerDirection.TopToBottom:                    
                    break;
                case LayerDirection.BottomToTop:
                    settings.Transformation = PlaneTransformation.Rotation(Math.PI);
                    break;
                case LayerDirection.LeftToRight:
                    settings.Transformation = PlaneTransformation.Rotation(Math.PI / 2);
                    break;
                case LayerDirection.RightToLeft:
                    settings.Transformation = PlaneTransformation.Rotation(-Math.PI / 2);
                    break;
            }

            settings.LayerSeparation = layerSeparation;
            LayeredLayout layeredLayout = new LayeredLayout(graph, settings);
            layeredLayout.Run();


            ShowGraphInDebugViewer(graph);

//            SugiyamaValidation.ValidateGraph(graph, settings);
        }
        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;
        }
        private void DoLayoutSugiyama(DrawingGraph dg)
        {
            var gg = dg.GeometryGraph;
            var layoutAlgorithm = new LayeredLayout(gg, dg.LayoutAlgorithmSettings as SugiyamaLayoutSettings);
            layoutAlgorithm.Run(CancelToken = new Core.CancelToken());

            var settings = (dg.LayoutAlgorithmSettings as SugiyamaLayoutSettings);
            if (!CancelToken.Canceled)
                DoEdgeRouting(dg.GeometryGraph, settings.EdgeRoutingSettings, settings.NodeSeparation);
        }
        static void BundleWithWidths() {
            bool msaglFile;
            int line;
            int column;
            var graph = Form2.CreateDrawingGraphFromFile("c:\\dev\\graphlayout\\graphs\\tail.dot", out line, out column, out msaglFile);
            var graph1 = Form2.CreateDrawingGraphFromFile("c:\\dev\\graphlayout\\graphs\\tail.dot", out line, out column, out msaglFile);

            double w = 0.3;
            foreach (var edge in graph.Edges) {
                edge.Attr.LineWidth = w;
                if (w == 0.3)
                    w = 0.4;
                else if (w == 0.4)
                    w = .5;
                else w = 0.3;
            }

            var gv = new GViewer();
            gv.Graph = graph1;
            graph.CreateGeometryGraph();
            var gg = graph.GeometryGraph;
            var gg1 = graph1.GeometryGraph;

            for (int i = 0; i < gg.Nodes.Count; i++)
                gg.Nodes[i].BoundaryCurve = gg1.Nodes[i].BoundaryCurve;

            var ss = new SugiyamaLayoutSettings();
            var ll = new LayeredLayout(graph.GeometryGraph, ss);
            ll.Run();

            var bundler = new SplineRouter(graph.GeometryGraph, ss.NodeSeparation * 2, ss.NodeSeparation / 3, Math.PI / 6, ss.EdgeRoutingSettings.BundlingSettings);

            bundler.Run();
            
            var f = new Form();
            f.SuspendLayout();
            f.Controls.Add(gv);
            gv.Dock = DockStyle.Fill;
            gv.NeedToCalculateLayout = false;
            gv.Graph = graph;
            f.ResumeLayout();

            f.ShowDialog();


        }
        void LayeredLayout(SugiyamaLayoutSettings layeredSettings, GeometryGraph component) {
            var layeredLayout = new LayeredLayout(component, layeredSettings);
            layeredLayout.SetCancelToken(this.CancelToken);
            double aspectRatio = layeredLayout.EstimateAspectRatio();
            double edgeDensity = (double) component.Edges.Count/component.Nodes.Count;

            // if the estimated aspect ratio is not in the range below then we fall back to force directed layout
            // with constraints which is both faster and usually returns a better aspect ratio for largish graphs
            var fallbackLayoutSettings = layeredSettings.FallbackLayoutSettings;
            if (fallbackLayoutSettings != null &&
                (component.Nodes.Count > 50 && edgeDensity > 2 // too dense
                 || component.Nodes.Count > 40 && edgeDensity > 3.0 // too dense
                 || component.Nodes.Count > 30 && edgeDensity > 4.0 // too dense
                 || component.Nodes.Count > 30 && aspectRatio > layeredSettings.MaxAspectRatioEccentricity // too wide
                 || component.Nodes.Count > 30 && aspectRatio < 1d/layeredSettings.MaxAspectRatioEccentricity
                    // too high
                    )) {
                // for large graphs there's really no point trying to produce nice edge routes
                // the sugiyama edge routing can be quite circuitous on large graphs anyway
                var prevEdgeRouting = fallbackLayoutSettings.EdgeRoutingSettings.EdgeRoutingMode;
                if (component.Nodes.Count > 100 && edgeDensity > 2.0)
                    fallbackLayoutSettings.EdgeRoutingSettings.EdgeRoutingMode = EdgeRoutingMode.StraightLine;

                LayoutComponent(fallbackLayoutSettings, component);
                fallbackLayoutSettings.EdgeRoutingSettings.EdgeRoutingMode = prevEdgeRouting;
            }
            else {
                var prevEdgeRouting = layeredSettings.EdgeRoutingSettings.EdgeRoutingMode;
                // for large graphs there's really no point trying to produce nice edge routes
                // the sugiyama edge routing can be quite circuitous on large graphs anyway
                if (component.Nodes.Count > 100 && edgeDensity > 2.0) {
                    layeredSettings.EdgeRoutingSettings.EdgeRoutingMode = EdgeRoutingMode.StraightLine;
                }
                layeredLayout.Run(this.CancelToken);
                layeredSettings.EdgeRoutingSettings.EdgeRoutingMode = prevEdgeRouting;
                InitialLayoutHelpers.FixBoundingBox(component, layeredSettings);
            }
            //LayoutAlgorithmSettings.ShowGraph(component);
        }
        public void StaircaseLayoutWithConstraints()
        {
            var graph = new GeometryGraph();

            var a = new Node(CreateRectangle());
            var b = new Node(CreateRectangle());
            var c = new Node(CreateRectangle());
            var d = new Node(CreateRectangle());
            // need the following dummy nodes for constraints
            var v1 = new Node(CreateDot());
            var v2 = new Node(CreateDot());
            var v3 = new Node(CreateDot());
            
            graph.Nodes.Add(a);
            graph.Nodes.Add(b);
            graph.Nodes.Add(c);
            graph.Nodes.Add(d);
            graph.Nodes.Add(v1);
            graph.Nodes.Add(v2);
            graph.Nodes.Add(v3);

            graph.Edges.Add(new Edge(a, b));
            graph.Edges.Add(new Edge(a, b));
            graph.Edges.Add(new Edge(b, a));
            graph.Edges.Add(new Edge(b, c));
            graph.Edges.Add(new Edge(c, d));
            graph.Edges.Add(new Edge(d, c));
            graph.Edges.Add(new Edge(c, d));
            graph.Edges.Add(new Edge(d, c));

            // if dummy nodes are not connected to graph then we get a DebugAssert fail
            graph.Edges.Add(new Edge(a, v1));
            graph.Edges.Add(new Edge(b, v2));
            graph.Edges.Add(new Edge(c, v3));

            var settings = new SugiyamaLayoutSettings();

            // it's fairly easy to find debug assert failures by trying different combinations of the following 
            settings.AddUpDownVerticalConstraint(a, v1);
            settings.AddUpDownVerticalConstraint(b, v2);
            settings.AddUpDownVerticalConstraint(c, v3);
            //settings.AddUpDownVerticalConstraint(v2, d);
            //settings.AddUpDownConstraint(a, v1);
            //settings.AddUpDownConstraint(a, b);
            //settings.AddUpDownConstraint(b, c);
            //settings.AddUpDownConstraint(c, d);
            settings.AddSameLayerNeighbors(v1, b);
            settings.AddSameLayerNeighbors(v2, c);
            settings.AddSameLayerNeighbors(d, v3);
            //settings.AddLeftRightConstraint(v1, b);
            //settings.AddLeftRightConstraint(v2, c); - doesn't work

            LayeredLayout layeredLayout = new LayeredLayout(graph, settings);
            layeredLayout.Run();

            graph.Nodes.Remove(v1);
            graph.Nodes.Remove(v2);
            graph.Nodes.Remove(v3);

            ShowGraphInDebugViewer(graph);
        }