microsoft / automatic-graph-layout

A set of tools for graph layout and viewing
Other
1.36k stars 304 forks source link

Populating a graph and retrieving node positions not working #362

Open critical-pass opened 10 months ago

critical-pass commented 10 months ago

I am trying to use the MSAGL library to generate node positions. I have gone through the samples and have not found a simple example that helps.

I have my own custom Graph object with a list of custom edges and custom nodes. I am iterating through them, adding them to the GeometryGraph, creating a layered layout, running the graph, iterating back through the nodes, and retrieving the node positions. The resulting nodes positions are incorrect, they are just about all overlapping. I tried scaling the positions by 100x but they still overlap. What am I doing wrong? (Here's my code)

1) I create nodes and edges. I make a dictionary for the nodes so I can reuse them in my edges.

Dictionary<string, Microsoft.Msagl.Core.Layout.Node> nMap = new Dictionary<string, Microsoft.Msagl.Core.Layout.Node>();
int radius = 12;
foreach (var myNode in myGraph.nodes)
{
    var curve = CurveFactory.CreateCircle(radius, new Point());

    // var node = new Microsoft.Msagl.Core.Layout.Node(curve, id);
    var node = new Microsoft.Msagl.Core.Layout.Node(curve, myNode.id.ToString());

    graph.Nodes.Add(node);
    nMap.Add(myNode.id.ToString(), mNode);
}

foreach (var activity in myGraph.activities)
{
    var source = nMap[activity.chartInfo.source_id.ToString()];
    var target = nMap[activity.chartInfo.target_id.ToString()];
    graph.GeometryGraph.Edges.Add(new Microsoft.Msagl.Core.Layout.Edge(source, target));
}

2) Then I create my layout settings. I've tried changing properties on the settings to see if they produce different positions

var settings = new SugiyamaLayoutSettings
{
    Transformation = PlaneTransformation.Rotation(Math.PI / 2),
    EdgeRoutingSettings = { EdgeRoutingMode = Microsoft.Msagl.Core.Routing.EdgeRoutingMode.Spline }
};

// Tested these out but they didn't work
settings.MinimalHeight = 700;
settings.MinimalWidth = 1300;
settings.NodeSeparation = 200;

var llayout = new LayeredLayout(graph.GeometryGraph, settings);
llayout.Run();

3) Then I get my custom nodes (from a dictionary lookup) and set the positions from the GeometryGraph nodes:

foreach(var node in graph.GeometryGraph.Nodes)
{
    var myNode = myGraphNodeMap[node.UserData.ToString()];
    myNode .x = (int)node.Center.X * 100;
    myNode .y = (int)node.Center.Y* 100;
}

Can someone point me in the right direction? What am I doing wrong?

As an aside, how would you create edges that curve around a node?

levnach commented 10 months ago

What is "id" here? var node = new Microsoft.Msagl.Core.Layout.Node(curve, id); The edge routing in SplineMode is based on https://link.springer.com/content/pdf/10.1007/978-3-642-11805-0_15.pdf, building a sparse visibility graph and routing on it.

critical-pass commented 10 months ago

Ah it was a typo, it should be:

var node = new Microsoft.Msagl.Core.Layout.Node(curve, myNode.id.ToString());

I'll modify it so it says the right thing.

levnach commented 10 months ago

Sorry, it is difficult to see what is happening without additional information. A full example would help. Maybe you can print out the msagl node positions as well.