LayeredDigraphLayout Links and Layers

How are the link paths calculated for LayeredDigraphLayouts calculated as it relates to links to the next vs further away layers?

I’m trying to clean up some linking / styling for the links between layers, and it seems like some properties apply only to links between adjacent layers vs some apply to links between disconnected layers? Or that the size/position of the to link changes the from links end segment?

My goal is to straighten up and line up more of these links, so that there’s less zigzagging:

Ideally I’d like nice arrays of lines. I’ve been playing around with various properties on the links (routing, curve, to/from segment length) and layout (layer/column/link spacing, aggressiveOption, etc) and I can’t quite seem to get it to play nice.

One thing that I’m confused by is that expanding and collapsing a to node seems to change the length of the from end segment?

Note the fromEndSegment from the left group no longer lines up when the toGroup is expanded:

Is this something where I’m probably going to have to create my own link class?

Yes, links that connect nodes that are not in adjacent layers get dummy vertexes, and those vertexes are laid out somewhat like regular vertexes for real nodes, but much thinner.

The main issue is in exactly how the nodes line up with each other. What is the value of LayeredDigraphLayout.columnSpacing? It would be good to make the node width a multiple of the columnSpacing.

Are you using AvoidsNodes routing? If so, the layout routing results might be better with just Orthogonal.

If you don’t mind a comment, I find the links too easily confused with the group borders. Changing the stroke color and/or strokeWidth of one or the other might help. And to make the links easier to follow, you could try setting Link.corner to a value such as 5 or so.

I’ll change the borders to try and make them look nicer, thanks. (I was planning on the groups being wider and dashed, but I hadn’t gotten to it yet, haha).

The link template:

function getLinkTemplate() {
    return GO(go.Link, {
            routing: go.Link.AvoidsNodes,
            curve: go.Link.JumpGap,
            corner: 5,
            fromSpot: go.Spot.Right,
            toSpot: go.Spot.Left
        GO(go.Shape, {
            name: "OBJSHAPE",
            strokeWidth: 1
        GO(go.Shape, {
            name: "ARWSHAPE",
            toArrow: "Standard"

The Layout settings:

function getLayout() {
    return GO(go.LayeredDigraphLayout, {
        isOngoing: true,
        layerSpacing: 100,
        columnSpacing: 100,
        linkSpacing: 10,
        layeringOption: go.LayeredDigraphLayout.LayerLongestPathSource,
        aggressiveOption: go.LayeredDigraphLayout.AggressiveNone

The nodes are currently an arbitrary size, based on a textBlock in the center with a minWidth, then some extra spacing for the various buttons and status icons that decorate it.

I just tested moving the size to the outer auto “port” panel and making them multiples (360 size, 60 spacing), but that doesn’t seem to have helped much.

I also tried orthogonal, but I have issues where the links overlap the groups with it:

The links between adjacent groups works very well. Is there a way to emulate their behavior for cross-layer links?

I would have thought that using Orthogonal routing would have helped. I don’t see how it would have routed the link you have drawn in red in your last screenshot, running through that middle group. Each group has its own Group.layout, doesn’t it?

LayeredDigraphLayout intentionally tries to separate out links that have segments that coincide that do not have connected ports in common. But it shouldn’t do that for the links coming out of the node on the left.

However with AvoidsNodes routing the route might well naturally do that (running closer to the node on the left) and LayeredDiagraphLayout doesn’t try to do any of its own routing of links that have AvoidsNodes routing, which would explain your first screenshot.

I’m using the return of that function for each of the subgraphs. GO is an alias to make, which will return separate instances, right?

I’m not sure if it helps, but it seems like even within one group, I can get links that draw over it’s own nodes with Orthogonal:

So you are setting Group.layout to the result of calling getLayout()? That should be OK.

LayeredDigraphLayout won’t do such a routing on its own (crossing over nodes), so I don’t understand why it’s happening for you.

I can email you the source if you’d like. It’s all self-contained, so you should be able to just open the html and see.

I’m sure I’m doing something janky somewhere. =P

OK. You know our email address, GoJS at our domain,