LayeredDigraphLayout + Bands + Grouped Nodes

Hi,

I’m a newbie working with GoJS on a prototype that uses a LayeredDigraphLayout with bands and I have some nodes that are grouped and some nodes that are not. I’m have trouble getting things to layout in a way where the node links don’t overlap and are as straight as possible.

The following forum post seems related to my issue which gave me the idea of setting Group.layout = null on my group template.

http://www.nwoods.com/forum/forum_posts.asp?TID=5717&KW=LayeredDigraphLayout+groups&PID=24331&title=positioning-of-nodes-within-groups#24331

That seemed to fix my overlapping lines issue and also resulted in straighter lines. But my group always shows up in the 1st band and not in the 2nd band (see screenshots below).

Node & Link Data

nodeData = [
{ key: 1, type: “task”, id: “task1”, name: “Landing Page”, channel: “web”, count: 3 },
{ key: 2, type: “split”, id: “2”, name: “Response Split”, count: 3, isGroup: true },
{ key: 3, type: “cell”, id: “3”, name: “Accepted”, count: 2, group: 2 },
{ key: 4, type: “cell”, id: “4”, name: “Did Not Accept”, count: 1, group: 2 },
{ key: 5, type: “cell”, id: “5”, name: “Remainder”, count: 0, group: 2 },
{ key: 6, type: “cell”, id: “6”, name: “Missing”, group: 2 },
{ key: 7, type: “task”, id: “task3”, name: “Followup Email”, channel: “email” },
{ key: 8, type: “task”, id: “task2”, name: “Welcome Email”, channel: “email”, count: 2 },
{ key: 9, type: “wait”, id: “9”, name: “Wait 5 Days”, count: 1 },
{ key: 10, type: “stop”, id: “10”, name: “Stop” },
];
linkData = [
{ from: 1, to: 2 },
{ from: 5, to: 12 },
{ from: 3, to: 8 },
{ from: 4, to: 9 },
{ from: 8, to: 10 },
{ from: 9, to: 7 },
{ from: 7, to: 10 },
{ from: 6, to: 7 },
{ from: 5, to: 10 },
];

Group.layout = $(go.GridLayout, { wrappingColumn: 1 })
Puts the “Response Split” group in the correct band but doesn’t re-order the grouped nodes to avoid overlapping lines nor does it position the group optimally to result in straighter lines.

Group.layout=null
Fixes my overlapping links and also positions the “Response Split” group, the grouped nodes and downstream nodes so that lines are straight. But it always puts the group in the 1st band.

How can I get the best of both of the above screenshots? I need my group in the 2nd band like the 1st screenshot but the layout of the group and downstream nodes like the 2nd screenshot.

Kendal

As that other post suggested, did you also set Group.isLayoutPositioned = false? That and setting Group.layout = null will make it appear to the Layout as if the Group did not exist. Then if you are using a Placeholder, the Group will just be positioned to surround the Nodes, which presumably had been placed moderately well, in whatever layers that the LayeredDigraphLayout assigned to them.

Thanks for the quick reply!

Setting Group.isLayoutPositioned = false made things worse. I no longer see my grouped node or the nodes within the group (see screenshot below). I have the following placeholder set.

$(go.Placeholder, { padding: new go.Margin(40, 5, 5, 5) })

I then removed Group.isLayoutPositioned = false and connected my 1st node directly to the grouped nodes instead of the group. Here’s my link data change (see comments).

linkData = [
// { from: 1, to: 2 },
{ from: 1, to: 3 }, // connect directly to grouped node instead of group
{ from: 1, to: 4 }, // connect directly to grouped node instead of group
{ from: 1, to: 5 }, // connect directly to grouped node instead of group
{ from: 1, to: 6 }, // connect directly to grouped node instead of group
{ from: 5, to: 12 },
{ from: 3, to: 8 },
{ from: 4, to: 9 },
{ from: 8, to: 10 },
{ from: 9, to: 7 },
{ from: 7, to: 10 },
{ from: 6, to: 7 },
{ from: 5, to: 10 },
];

That made things better.

My preference is to connect the 1st node to the group only and not the group members. Is that possible with a layout similar to the above? Or do I have to connect directly to the group members?

Also in the above screenshot, my grouped node icon and text is showing up in my band header for band #2. I assume because the layout is laying things out as if my group doesn’t exist and then surrounding my nodes. And my group top padding is 40. Is there a way to factor in my group placeholder padding when laying out the grouped nodes within the band so that the entire grouped node fits within the band content?

Sorry about that – I did not notice that the link connected directly with the Group instead of to a Node inside the Group. I’m guessing that the layout was accounting for the size of the Group but afterwards the Group automatically moved itself to be where its member Nodes got positioned separately by the layout, leaving behind an empty space.

Most of the Layout classes make use of a LayoutNetwork subclass. That is useful because it gives the programmer flexibility for what graph should actually be laid out – it need not be isomorphic to the actual Nodes and Links in the Diagram. So you could override LayeredDigraphLayout.makeNetwork to call the base method, create LayeredDigraphEdges as if those 4 Links actually existed in the Diagram, and remove the LayeredDigraphEdge corresponding to the single actual Link that you do want to connect to the Group.

I know that the Genogram sample’s custom layout demonstrates an override of makeNetwork, but its usage and purpose is different. Other overrides of makeNetwork are for simpler initialization purposes.

As far as the header for the Group overlapping the headers of the layer bands, I think you can adjust the Rects that are given in the “layerRects” argument to commitLayers, along with a corresponding shift in the “offset” argument, to accommodate the desired additional vertical space.

I now have everything laying out like I want.

My link data model now looks like this.

linkData = [
{ from: 1, to: 2 },
{ from: 1, to: 3, transparent: true },
{ from: 1, to: 4, transparent: true },
{ from: 1, to: 5, transparent: true },
{ from: 1, to: 6, transparent: true },

];

I use data binding to make the links “transparent” if transparent = true. So all the links exist in the diagram but you only see the link from the 1st node to the group. Let me know if you have issues with this approach.

I tweaked several different configurations to make sure my group doesn’t overflow into the band header or overlap other nodes in the same band.

Thanks for the pointers!
Kendal

The only problem with your approach is that it makes the LayeredDigraphLayout, which is already very slow to begin with (especially because this is executing JavaScript), slightly slower.

But if you don’t mind creating those extra links in your model, that’s a good enough solution.

Actually, I wonder if you could go back to setting Group.isLayoutPositioned = false again.

Setting Group.isLayoutPositioned = false still causes the issue in my 9:44am post yesterday (screenshot exactly the same). The group and the group members no longer show up.

I have a follow-on question related to this post. In my improved diagram layout in my above post (Posted: August-27-2014 at 10:40am), is there any way to control the order or influence the order of the group members with LayeredDigraphLayout?

I keep getting requests from project management to order the group members in a specific way. For example, in the screenshot above, they always want “Accepted” node to be the 1st group member in the group and “Remainder” to be the last group member in the group. All the others group members can be in in between the 1st and last in any order.

Is that possible with LayeredDigraphLayout?

In general, LayeredDigraphLayout is geared towards trying to re-order nodes within a layer in order to reduce the number of link crossings there are.

I wonder if there’s a way for you to use TreeLayout, since that does let you order the children of each parent node. However it isn’t clear to me if you can. And even if you can it isn’t clear to me which way you want the tree to “grow” – towards the right or towards the left – to get the best results.