microsoft / automatic-graph-layout

A set of tools for graph layout and viewing
Other
1.34k stars 301 forks source link

AutomaticGraphLayoutControl : Different layout each time #354

Open bforlgreen opened 11 months ago

bforlgreen commented 11 months ago

The following code creates a slightly different layout each time it is run. I would expect the same code to always have the exact same layout?

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            var graph = new Graph();

            graph.AddNode("A");
            graph.AddNode("B");
            graph.AddNode("C");
            graph.AddNode("D");
            graph.AddNode("E");
            graph.AddNode("F");
            graph.AddNode("G");
            graph.AddNode("H");
            graph.AddNode("I");
            graph.AddNode("J");
            graph.AddNode("K");
            graph.AddNode("L");
            graph.AddNode("M");

            graph.AddEdge("B", "E");
            graph.AddEdge("C", "E");

            graph.AddEdge("C", "F");
            graph.AddEdge("D", "F");

            graph.AddEdge("B", "G");
            graph.AddEdge("D", "G");

            graph.AddEdge("E", "H");
            graph.AddEdge("F", "H");

            graph.AddEdge("F", "I");
            graph.AddEdge("G", "I");

            graph.AddEdge("I", "J");
            graph.AddEdge("A", "J");

            graph.AddEdge("J", "K");
            graph.AddEdge("B", "K");

            graph.AddEdge("K", "M");
            graph.AddEdge("L", "M");

            InitializeComponent();

            layoutControl.Graph = graph;
        }
    }

image image image

bforlgreen commented 11 months ago

Oddly, I cannot reproduce the same issue when I create the graph manually using GeometryGraph (i.e only using microsoft.msagl.drawing)

So it seems that using automaticgraphlayout.wpfgraphcontrol introduces the inconsistent layout.

public partial class MainWindow : Window
{
    private GeometryGraph _geometryGraph = new GeometryGraph();

    private void AddEdge(string from, string to)
    {
        _geometryGraph.Edges.Add(new Edge(
            _geometryGraph.FindNodeByUserData(from), 
            _geometryGraph.FindNodeByUserData(to)));
    }

    private void AddNode(string name)
    {
        _geometryGraph.Nodes.Add(new Node(CurveFactory.CreateRectangle(30, 30, new()), name)
    }

    public MainWindow()
    {
        AddNode("A");
        AddNode("B");
        AddNode("C");
        AddNode("D");
        AddNode("E");
        AddNode("F");
        AddNode("G");
        AddNode("H");
        AddNode("I");
        AddNode("J");
        AddNode("K");
        AddNode("L");
        AddNode("M");

        AddEdge("B", "E");
        AddEdge("C", "E");

        AddEdge("C", "F");
        AddEdge("D", "F");

        AddEdge("B", "G");
        AddEdge("D", "G");

        AddEdge("E", "H");
        AddEdge("F", "H");

        AddEdge("F", "I");
        AddEdge("G", "I");

        AddEdge("I", "J");
        AddEdge("A", "J");

        AddEdge("J", "K");
        AddEdge("B", "K");

        AddEdge("K", "M");
        AddEdge("L", "M");

        var settings = new SugiyamaLayoutSettings();

        var layout = new LayeredLayout(_geometryGraph, settings);
        layout.Run();

        InitializeComponent();
        SetContent();
    }

    private void SetContent()
    {
        var canvas = new Canvas();

        foreach (var n in _geometryGraph.Nodes)
        {
            var border = new Border()
            {
                Width = n.Width,
                Height = n.Height,
                BorderThickness = new Thickness(1),
                BorderBrush = Brushes.Black
            };

            border.Child = new TextBlock()
            {
                Text = n.UserData.ToString(),
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            };

            Canvas.SetLeft(border, n.BoundingBox.Left);
            Canvas.SetTop(border, _geometryGraph.Top - n.BoundingBox.Top);

            canvas.Children.Add(border);
        }

        foreach (var e in _geometryGraph.Edges)
        {
            var line = new Line() { StrokeThickness = 2, Stroke = Brushes.Red };
            line.X1 = e.Curve.Start.X;
            line.Y1 = _geometryGraph.Top - e.Curve.Start.Y;

            line.X2 = e.Curve.End.X;
            line.Y2 = _geometryGraph.Top - e.Curve.End.Y;

            canvas.Children.Add(line);
        }

        Content = canvas;

        canvas.RenderTransform = new TranslateTransform(100, 0);
    }
}
bforlgreen commented 11 months ago

I'm using :

AutomaticGraphLayout.WpfGraphControl : 1.1.12 Microsoft.Msagl.Drawing 1.1.6