elkjs icon indicating copy to clipboard operation
elkjs copied to clipboard

Nested edges sometimes have unexpected containment node

Open alexei-tilikin opened this issue 2 years ago • 5 comments

Hi again,

I'm having an issue with nested edge routing in the "layered" layout. Using [email protected] Here's the input JSON:

{
  "id": "__ROOT__",
  "children": [
    {
      "id": "group_2",
      "children": [
        {
          "id": "group_1",
          "children": [
            {
              "id": "node_0",
              "width": 150,
              "height": 123
            },
            {
              "id": "node_2",
              "width": 150,
              "height": 123
            }
          ]
        },
        {
          "id": "test_in_grp2",
          "width": 150,
          "height": 123
        }
      ]
    },
    {
      "id": "node_1",
      "width": 150,
      "height": 123
    }
  ],
  "edges": [
    {
      "id": "edge:node_1:test_in_grp2",
      "sources": [
        "node_1"
      ],
      "targets": [
        "test_in_grp2"
      ]
    },
    {
      "id": "edge:test_in_grp2:node_0",
      "sources": [
        "test_in_grp2"
      ],
      "targets": [
        "node_0"
      ]
    }
  ],
  "layoutOptions": {
    "elk.algorithm": "layered",
    "hierarchyHandling": "INCLUDE_CHILDREN"
  }
}

The problematic edge is "edge:test_in_grp2:node_0". The source is nested in group_2. The target is nested in group_1, which is nested in group_2.

I've read here about the logic for coordinates calculation in ELK: https://www.eclipse.org/elk/documentation/tooldevelopers/graphdatastructure/coordinatesystem.html

According to this, the containment for edge "edge:test_in_grp2:node_0" should be the LCA of source and target, which is "group_2".

However, when I run ELK and look at the output coordinates under edge.sections, all the coordinates are relative to the outermost ROOT graph, and not to group_2.

The problem is visualised also with elkjs-svg, it also assumes edge "edge:test_in_grp2:node_0" to be defined under group_2 and puts the element under the group_2 box. The edge appears with an invalid position. Only after manually fixing this and moving the edge element to the topmost container, the edge aligns with the expected position.

Here's the output of ELK:

{
  "id": "__ROOT__",
  "children": [
    {
      "id": "group_2",
      "children": [
        {
          "id": "group_1",
          "children": [
            {
              "id": "node_0",
              "width": 150,
              "height": 123
            },
            {
              "id": "node_2",
              "width": 150,
              "height": 123
            }
          ]
        },
        {
          "id": "test_in_grp2",
          "width": 150,
          "height": 123
        }
      ]
    },
    {
      "id": "node_1",
      "width": 150,
      "height": 123
    }
  ],
  "edges": [
    {
      "id": "edge:node_1:test_in_grp2",
      "sources": [
        "node_1"
      ],
      "targets": [
        "test_in_grp2"
      ]
    },
    {
      "id": "edge:test_in_grp2:node_0",
      "sources": [
        "test_in_grp2"
      ],
      "targets": [
        "node_0"
      ]
    }
  ],
  "layoutOptions": {
    "elk.algorithm": "layered",
    "hierarchyHandling": "INCLUDE_CHILDREN"
  }
}

You can see that the edge starting point is:

"x": 349,
 "y": 240.5

While the source node (test_in_grp2) has coordinates:

"x": 12,
"y": 167

349-12 = 337 which appears to be the node width (150) + group_2 offset (187). The group_2 offset is the problem since the edge is supposed to be based on group_2 coordinates.

Oddly enough, when trying to reproduce with this demo page, the problem doesn't seem to reproduce. https://rtsys.informatik.uni-kiel.de/elklive/json.html This demo doesn't seem to apply translation on "edge:test_in_grp2:node_0" assuming it belongs to the root graph.

Can you help to understand why the container of "edge:test_in_grp2:node_0" wasn't resolved as "group_2"? Is there a way to get the resolved container for each edge as an output from elkjs?

alexei-tilikin avatar Mar 13 '22 14:03 alexei-tilikin

Here's the result of elkjs-svg running on this graph. You can see the broken edge between "test_in_grp2" and "node_0"

elkjs-svg result_broken edge

alexei-tilikin avatar Mar 13 '22 14:03 alexei-tilikin

It sounds like it will be solved by this PR, which is slated for inclusion in ELK 0.8.0 (hence also elkjs 0.8.0).

skieffer avatar Mar 13 '22 17:03 skieffer

@skieffer thank you for the quick response! What's the planned release date for 0.8.0 to be publicly available on npm?

Meanwhile, I was thinking of a possible workaround to guess the expected offset for each edge by looking at the startPoint and the source node coordinates. My rendering approach is flat (no nested transforms) so it should be enough to only figure out the offsets relative to the root graph.

Are there any "hidden" output properties on the elk JSON, what maybe should be enabled in configuration to see? For example, the port data for the edge? I'm not defining ports explicitly, though that means ports are still defined internally by the layout, right?

alexei-tilikin avatar Mar 14 '22 07:03 alexei-tilikin

The release date for 0.8.0 is currently the 11th of April, however, I might be ill in a few days which might postpone it further. After that @uruuru usually builds the elkjs release.

soerendomroes avatar Mar 14 '22 07:03 soerendomroes

Thank you! Feel well, @soerendomroes.

alexei-tilikin avatar Mar 15 '22 06:03 alexei-tilikin