How to have links avoid groups and to ignore group boundaries when ingressing/egressing groups

I have a graph structure where large groups of nodes (sometimes hundreds) can have links that go to nodes in other groups, or to nodes that are in parent groups.

I’m running into two major issues that make this pretty messy-looking and I’m not sure how to sort it out.

The first is that if a link goes into/out of or over a group, it doesn’t avoid that group or the nodes inside that group (even if it’s connected to one of the nodes inside that group):

The second is that links in and out of groups often seem to want to “bunch up” as they go out, even in scenarios where they have to go out of their way to achieve that:

I have my link template set to avoid nodes:

const basicLink = new go.Link({
  routing: go.Link.AvoidsNodes,
  corner: 5,
  curviness: 10,
  reshapable: true,
  resegmentable: true
});

and in both my diagram and the group template, it’s set to avoids nodes as well:

const myDiagram = new go.Diagram("myDiagramDiv", {
  layout: new go.TreeLayout({
    routing: go.Routing.AvoidsNodes,
    sorting: go.TreeSorting.Ascending,
    alignment: go.TreeAlignment.CenterSubtrees,
    layerSpacing: 35,
    angle: 0,
  }),
[...]
const basicCompoundElementLayout = new go.TreeLayout({
  routing: go.Routing.AvoidsNodes,
  sorting: go.TreeSorting.Ascending,
  alignment: go.TreeAlignment.CenterSubtrees,
  layerSpacing: 35,
  linkTemplateMap: clickLinkTemplates,
  angle: 0,
});

The group template itself even has the “avoidable” property on it set, and I’ve tried playing around with the “avoidableMargin” property, but it doesn’t actually seem to have any effect:

const basicCompoundElementGroup = new go.Group('Auto', {
  layout: basicCompoundElementLayout,
  avoidableMargin: new go.Margin(2, 2, 2, 2),
  avoidable: true,
  isSubGraphExpanded: false
});

What I would like is:

  • For links that go into/out of groups to act as if the group boundary isn’t there.
  • For links that do not go into/out of groups to avoid those groups.
  • In scenarios where group A is a child of group B, node X is not a member of either, and node Y is a child of group B but not group A, for the link between nodes X and Y to act as if B’s boundary does not exist and to avoid group A’s boundary.

I’m not really sure how to accomplish this though.

Thanks in advance!

Yes, that’s a known problem for which we have not yet devised a solution. We can look into it, but it will take a while.

Understood. This does bring to mind something though: Eventually I want to have links from nodes that go to nodes in other groups to automatically create ports on the sides of those groups, and for links to connect to those ports. Presumably this might at least solve the “links in/out of groups don’t avoid nodes” issue by eliminating the need for links in/out of groups entirely.

For example: If node X is a member of group A and node Y is a member of group B, and node X has a port that connects to a port on node Y, then ports should be added to the borders of groups A and B, and the links between the ports of X and Y should connect to those ports instead, and the ports on the outside of A and B should connect. (e.g. instead of X[0] → Y[0], it would go X[0] → A[0] → B[0] → Y[0]).

I can probably do this by altering the logic for how I actually add the link data and define nodes/groups, but I’d prefer for it to happen dynamically. IIRC, I saw a post where someone did this a while back, but I don’t think they shared their solution for it. Could this be a feasible workaround/how might I do that?

Here is a sample that might be like what you are asking about:
Groups with virtual ports, created automatically when links cross the group boundary

Also, another sample that tries to solve the problem another way:
DummyLinks extending to Group borders

As usual, the complete source code is embedded in the page itself – just View Page Source in your browser.