Manual layout/extending layout

Hi,

I’ve got following Situation. I am using a LayeredDigraphLayout for a tree like structure for visualizing a workflow top-down, which works quite well out-of-the-box.
Now, I have to Show additional nodes which do not directly have anything do with the workflow on the right side of the diagram. These nodes represent reports/documents which may be referenced by certain nodes of the workflow (see screenshot)

My first thought was to use Groups and specify a different layout for the Group, but since the reports may be referenced by different workflow nodes which may be spread all across the diagram, I think this does not work.
My second thought and first implemantation does a Manual layout, i.e. the Report nodes have an empty layout-id and I calculate the Position manually. But now I run into collisions, i.e. two Report nodes overlap.
So now my question: what would you propose to handle such a requirement? Would it be better to somehow extend the LayeredDigraphLayout? Where would I start? Is there some documentation or api doc where I could start? Especially helpful could be sth. about finding collisions…

Thanks in advance,
Marc

I think you should subclass LayeredDigraphLayout. I’ll give you an example later.

To detect overlaps, try calling GoXam for WPF 2.2.4

For this example I’ll assume the nodes that you wanted to position along the right side have Category == “Extra”, i.e. they are using a different template, and such nodes have go:Node.LayoutId = "None". And that you’ll want to position those at the same “layer” (i.e. Y value) as whatever they were connected with in the main layout:

  public class CustomLayout : LayeredDigraphLayout {
    protected override void LayoutNodes() {
      base.LayoutNodes();
      var b = this.Diagram.Panel.ComputeBounds(this.Network.GetNodesAndLinks());
      foreach (var v in this.Network.Vertexes) {
        var n = v.Node;
        if (n == null) continue;
        foreach (var n2 in n.NodesConnected.Where(x => x.Category == "Extra")) {
          n2.Position = new Point(b.Right + 50, v.Position.Y);
        }
      }
    }
  }

This doesn’t address multiple “Extra” nodes at the same layer – you’ll need to keep track of the nodes per layer so that you can assign unique X values to avoid overlaps.

Hi Walter,

thanks for your Information!

I now tried to add the collision detection behaviour with the method you mentioned earlier in this Topic. But it doesn’t work as I expected. Here’s the code and a sample Output of my LayoutNodes() method:

x.Position = new Point(bounds.Right + OffsetX, vertex.Position.Y + OffsetY);

// detect collisions
var collisions = this.Diagram.Panel.FindPartsIn<Node>(x.Bounds, SearchFlags.Nodes, SearchInclusion.Intersects,
	SearchLayers.Nodes);
while (collisions.Any())
{
	x.Position = new Point(x.Position.X, x.Position.Y + 20);
	Console.WriteLine("new bounds: {0}", x.Bounds);
	collisions = this.Diagram.Panel.FindPartsIn<Node>(x.Bounds, SearchFlags.Nodes, SearchInclusion.Intersects,
	SearchLayers.Nodes);
}

Console.WriteLine("position for node {0}: {1}/{2}", ((GraphLinksModelNodeData<string>)x.Data).Key, x.Position.X, x.Position.Y);

Output:

position for node 026BLORDERFEEDBACKSTO:STO.026:2.I: 506/-2
position for node 026INPRODUCTIONAVIS:STO.026:AU.025: 506/-2
position for node 026BLCUDAPFEEDBACKSTO:STO.026:C.14: 506/916,85

Now, if I run the layouting multiple times, I get a toggling behaviour. I suspect that the Problem lies in the FindPartsIn method, namely that this method does not yet know about the changed positions. I have sth. on my mind that I somewhere read sth. about commiting positions and I guess that this didn’t happen until the layouting is finished. At least it would expect the toggling behaviour. The first case is, that the positions get calculated and no collisions are found, thus low y values. Then the second layouting sees that the nodes were placed there and calculates positions with higher y values. Then the third layout sees the positions of the second layouting and thinks that there is free space at low y positions and places the nodes there, …
And in each layout run, no collisions are detected between nodes that are currently rearranged. Thus the Output of the two nodes which have the same Position, which should not occur.

So, now at last my question: what am I doing wrong here and what do I have to do to do it right? Any help is appreciated.

Kind regards,
Marc

You do not need to call FindPartsIn, since you should know which “extra” nodes should belong to which layer. (Well, if that isn’t known, you will need to figure it out in your override method.)

So you can order the nodes how you want and then position them as you like.