Ownership structure chart


Ownership structure chart describes shareholding relationships between legal entities (multiple parent to children and multiple child to parents links). I have seen a few example that were recommending to use Layered Digraph. I would like to know if this layout is scaling well with the number of nodes and links? Because in the sample I can see quite a lot of line crossing which can make the readability more difficult. Is there a way to “optimize” the layout for readability out of the box, or is it a lot of work to create a custom layout to achieve this?
The idea would be to be able to read the links clearly as each of those is indicating an ownership percentage.

Yes, in the general case there might not be any layout that will be able to handle a large number of entities and relationships and produce a simple-looking graph. Complicated graphs can be too complicated to map well onto a small flat surface. So if you have ways of focussing on specific things, that would be most helpful to your users.

Do you have some screenshots that you could share showing the behavior that you currently have and showing what you would want ideally?

In fact, the idea would be to avoid overlapping of links as they have a shareholder percentage information. To highlight more what I am looking for, I have provided below an example of how an export could look like. We should be able to provide a fixed width and stack nodes (I have seen this behaviour in Grid layout but not Layered Digraph). Then the diagram could be split into several smaller ones, in this example this is the case for company B that would be then displayed in another page. I was thinking that Arranging layout may help us to achieve this.
The main goal would be to make all links clear and avoid overlapping when this reduces readability.

The complete source code for this app:

<!DOCTYPE html>
  <title>Minimal GoJS Sample</title>
  <!-- Copyright 1998-2022 by Northwoods Software Corporation. -->
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
  This depends on the non-tree-structured links being identified with the category: "Extra"

  <script src="https://unpkg.com/gojs"></script>
  <script src="https://gojs.net/temp/AvoidsLinksRouter.js"></script>
  <script id="code">
const $ = go.GraphObject.make;

var myRouter = new AvoidsLinksRouter();
function avoidLinks() { myRouter.avoidOrthogonalOverlaps(myDiagram.links); }

const myDiagram =
  $(go.Diagram, "myDiagramDiv",
      initialAutoScale: go.Diagram.Uniform,
      isReadOnly: true,
      layout: $(go.TreeLayout, {
        arrangement: go.TreeLayout.ArrangementHorizontal,
        arrangementSpacing: new go.Size(40, 40),
        angle: 90,
        alignment: go.TreeLayout.AlignmentStart,
        nodeSpacing: 40,
        layerSpacing: 60,
        breadthLimit: 400,
        rowIndent: 40,
        rowSpacing: 60,
        setsChildPortSpot: false
      "InitialLayoutCompleted": avoidLinks,
      "SelectionMoved": avoidLinks

myDiagram.nodeTemplate =
  $(go.Node, "Auto",
    { width: 100, height: 60, fromSpot: go.Spot.Bottom, toSpot: go.Spot.TopRightSides },
      { fill: "white" },
      new go.Binding("fill", "color")),
      new go.Binding("text"))

myDiagram.linkTemplate =
    { routing: go.Link.Orthogonal, corner: 10 },
      { segmentIndex: -2, background: "white" },
      new go.Binding("text"))

    { isLayoutPositioned: false, routing: go.Link.AvoidsNodes, corner: 10 },
      { segmentIndex: -2, background: "white" },
      new go.Binding("text"))

myDiagram.model = new go.GraphLinksModel(
  { key: 1, text: "Alpha", color: "lightblue" },
  { key: 2, text: "One", color: "orange" },
  { key: 3, text: "Two", color: "lightgreen" },
  { key: 4, text: "Three", color: "pink" },
  { key: 5, text: "Four", color: "orange" },
  { key: 6, text: "Five", color: "lightgreen" },
  { key: 7, text: "Six", color: "pink" },
  { key: 11, text: "Alpha 2", color: "lightblue" },
  { key: 12, text: "Alpha 3", color: "lightblue" },
  { key: 21, text: "Beta", color: "lightblue" },
  { key: 22, text: "One", color: "orange" },
  { key: 23, text: "Two", color: "lightgreen" },
  { from: 1, to: 2, text: "20%" },
  { from: 1, to: 3, text: "30%" },
  { from: 1, to: 4, text: "40%" },
  { from: 1, to: 5, text: "50%" },
  { from: 1, to: 6, text: "60%" },
  { from: 1, to: 7, text: "70%" },
  { from: 11, to: 4, text: "10%", category: "Extra" },
  { from: 12, to: 5, text: "10%", category: "Extra" },
  { from: 12, to: 6, text: "10%", category: "Extra" },
  { from: 21, to: 22, text: "60%" },
  { from: 21, to: 23, text: "70%" },
  { from: 21, to: 5, text: "10%", category: "Extra" },
  { from: 21, to: 6, text: "10%", category: "Extra" },

Note that this depends on being basically tree-structured and declaring which links come from outside the tree. See the link data that have the category: "Extra" property setting.

Note also that it depends on an undocumented, experimental class that reduces overlapping segments of orthogonal links.

Thank you for the feedback and for sharing this sample!
Would it require a lot of effort to have the grid layout feature of fixed maximum width in terms of nodes and stack them on another layer if there are more nodes to show ?
Is arranging layout a good layout if the whole diagram is split across different regions to make it more readable (like in my sample diagram) ?
Last question: I have seen that hyperlink are supported but it is possible to create hyperlinks to navigate from one node to another?

TreeLayout already has support for that in its “arranging…” properties. That is why all of the blue nodes and subtrees are laid out horizontally. The problem is in deciding which nodes should belong together in the same row and which ones deserve new rows. I can imagine that it can get a lot more complicated. But if that can be determined programmatically, then it can be implemented. Yes, ArrangingLayout might be useful, but it isn’t necessary.

Separate question about hyperlinks – the “HyperlinkText” extension is just for navigating to different URLs. If you just want to change focus or selection to a different node, just do it in a click event handler. Which is basically what the “HyperlinkText” extension does – a click event handler that calls window.open.

EDIT: Here’s the result of changing the TreeLayout.arrangement to be ArrangementVertical:

I guess that if I am able to determine programmatically how to layout the nodes I would then have to extend TreeLayout ?
I was thinking about using ArrangingLayout to prepare the split diagrams for export and have one diagram per page, is there a simpler alternative ?

What do you mean by “page”? If you have nodes in separate diagrams, there will be no way to draw links between nodes in different diagrams. Are you talking about putting “Beta” and its subtree in a separate diagram? Then what about links that connect “Beta” subtree nodes with “Alpha” subtree nodes?

In the diagram/model that I’ve shown above, did you want the “Alpha 2” and “Alpha 3” nodes to be in the same row as “Alpha”? Did you want “Beta” and its subtree to be in separate rows?

I have understood that GoJS does not have this pagination concept and that when a diagram is exported and cannot be printed on a single page for readability, then the global diagram is split but that could make “broken” links that would then have to be reassembled to form the original diagram.
In my case, I was thinking of have separate diagrams to have related but not directly connected nodes so that every exported page has a meaning. About your point on the links, that would be why nodes would be repeated on related pages.
That’s why I have taken the example of the B node. B has a parent A but has also children. So to keep a clean layout, it would be placed on another diagram.
So in fact, in your diagram, Beta would be a child of Alpha and would be present on a separate diagram without any links to the first one and Alpha 2, Alpha 3 would be present in the same row as Alpha

When printing, the diagram could be scaled down so that everything is shown on one page.

You could also hide most of the diagram and only layout and print a few nodes and links at a time, each on a separate page.

Note that browsers do not know the size of printed pages, so you would have to tell your code about the page size. Read more about printing at GoJS Printing -- Northwoods Software