protected override void OnPaint(PaintEventArgs e)
 {
     e.Graphics.SmoothingMode     = SmoothingMode.AntiAlias;
     e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
     base.OnPaint(e);
     if (_geometryGraph == null)
     {
         _geometryGraph = CreateAndLayoutGraph();
     }
     DrawingUtilsForSamples.DrawFromGraph(ClientRectangle, _geometryGraph, e.Graphics);
 }
        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 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);
        }
        private void Graph_Drawn(object sender, DrawnArgs args)
        {
            var context = args.Cr;

            DrawingUtilsForSamples.DrawFromGraph(new Cairo.Rectangle(0, 0, width, height), graph, args.Cr);
        }
        internal static GeometryGraph CreateAndLayoutGraph()
        {
            PhyloTree phyloTree = new PhyloTree();
            double    width     = 40;
            double    height    = 10;

            foreach (string id in "A B C D E F G".Split(' '))
            {
                DrawingUtilsForSamples.AddNode(id, phyloTree, width, height);
            }

            PhyloEdge e;
            double    age_of_BC = 2;
            double    age_of_D  = 3.5;
            double    age_of_F  = 1.5;
            double    age_of_G  = 3.5;
            double    age_of_E  = 2;

            phyloTree.Edges.Add(e = new PhyloEdge(phyloTree.FindNodeByUserData("A"), phyloTree.FindNodeByUserData("B")));
            e.Length = age_of_BC;
            phyloTree.Edges.Add(e = new PhyloEdge(phyloTree.FindNodeByUserData("A"), phyloTree.FindNodeByUserData("C")));
            e.Length = age_of_BC;
            phyloTree.Edges.Add(e = new PhyloEdge(phyloTree.FindNodeByUserData("A"), phyloTree.FindNodeByUserData("D")));
            e.Length = age_of_D;
            phyloTree.Edges.Add(e = new PhyloEdge(phyloTree.FindNodeByUserData("C"), phyloTree.FindNodeByUserData("E")));
            e.Length = age_of_E;
            phyloTree.Edges.Add(e = new PhyloEdge(phyloTree.FindNodeByUserData("C"), phyloTree.FindNodeByUserData("F")));
            e.Length = age_of_F;
            phyloTree.Edges.Add(e = new PhyloEdge(phyloTree.FindNodeByUserData("C"), phyloTree.FindNodeByUserData("G")));
            e.Length = age_of_G;
            var sugiyamaLayoutSettings = new SugiyamaLayoutSettings();

            foreach (var edge in phyloTree.Edges)
            {
                edge.EdgeGeometry.TargetArrowhead = new Arrowhead();
            }
            Microsoft.Msagl.Miscellaneous.LayoutHelpers.CalculateLayout(phyloTree, new SugiyamaLayoutSettings(), null);

            // add a couple of  non-tree edges
            Edge e0 = new Edge(phyloTree.FindNodeByUserData("F"), phyloTree.FindNodeByUserData("D"))
            {
                EdgeGeometry = { SourceArrowhead = new Arrowhead() }
            };

            phyloTree.Edges.Add(e0);
            Edge e1 = new Edge(phyloTree.FindNodeByUserData("G"), phyloTree.FindNodeByUserData("D"))
            {
                EdgeGeometry = { SourceArrowhead = new Arrowhead() }
            };

            phyloTree.Edges.Add(e1);

            // route the non-tree edges, every other edge is routed already
            double loosePadding = sugiyamaLayoutSettings.NodeSeparation / 10;
            double tightPadding = sugiyamaLayoutSettings.NodeSeparation / 10;
            double coneAngle    = Math.PI / 6;
            var    router       = new SplineRouter(phyloTree, new[] { e0, e1 }, tightPadding, loosePadding, coneAngle, null);

            router.Run();
            return(phyloTree);
        }