Understanding how node spacing is computed in LayeredDigraphLayout

Using LayeredDigraphLayout, I observe that nodes are spaced too far away, especially when there are few of them.

For example in [AAAA] ---- [BBBB] ---- [CCCC], the space between the nodes appear to be as long as the node labels, and it seems to be dependent on the size of the nodes.

I digged into the code and found out that with alignOption: go.LayeredDigraphAlign.All, there is a partially undocumented function nodeMinLayerSpace which does the relevant computation.

The code

return t.node === null && t.data === null ? 0 : this.S === 90 || this.S === 270 ? i ? t.focus.y + 10 : t.bounds.height - t.focus.y + add : i ? t.focus.x + 10 : t.bounds.width - t.focus.x + 10;

does some computation and then adds a constant 10 to the result.

I modified it a bit to only add 2 instead of 10. This makes the links shorter.
This is my current code:

class MyLayout extends go.LayeredDigraphLayout {
             
                nodeMinLayerSpace(t, i) {
                    if (t.node === null && t.data === null) {
                        return 0;
                    }
                    if (self.S === 90 || self.S === 270) {
                        // we are only interested in S = 0, call the base method
                        return super.nodeMinLayerSpace(t, i);
                    }
                    let add = 2; // instead of 10

                    let computed = (t.bounds.width - t.focus.x) + add;
                    return computed;
                    
                    
                }
            }

However I am not sure I understand what is the principle behind the code.

  • What exactly is the resulting value used for?
  • What does (t.bounds.width - t.focus.x) compute?
  • Where does 10 come from?
  • If I put 2 instead will it break somewhere for some topologies?

thanks,
A.

LayeredDigraphLayout.nodeMinLayerSpace is used by LayeredDigraphLayout.commitNodes to compute how thick each layer needs to be in document units, considering for each vertex both the space on the left/top side, and also the space on the right/bottom side. It’s used independently of the alignOption. The value of LayeredDigraphLayout.layerSpacing controls the distance between the layers. Note that it should have no effect on the spacing between nodes within the same layer.

I hope you read the comments in the go.d.ts file.

Here is its definition.

  protected nodeMinLayerSpace(v: LayeredDigraphVertex, topleft: boolean): number {
    if (v.node === null && v.data === null) return 0;
    if (this.direction === 90 || this.direction === 270) {
      if (topleft) {
        return v.focus.y + 10;
      } else {
        return v.bounds.height - v.focus.y + 10;
      }
    } else {
      if (topleft) {
        return v.focus.x + 10;
      } else {
        return v.bounds.width - v.focus.x + 10;
      }
    }
  }

10 is just an arbitrary value used to leave room for the default end segment lengths used by links that connect with the nodes, since GraphObject | GoJS API and GraphObject | GoJS API default to 10. I suppose it could be more diligent about computing a “good” extra spacing, but I don’t think being clever there really helps.

I suppose if you returned numbers that added up to smaller than the depth of the vertex’s node’s size, you might get some awkward results. But there’s a lot of flexibility there for spacing.