elk icon indicating copy to clipboard operation
elk copied to clipboard

Ports Combined With Layered Interactive

Open saulshanabrook opened this issue 1 year ago • 1 comments

Describe the bug

I notice that when I user interactive layered layout, for some reason all my outgoing ports are merged... I am not sure why. The interactive node positions seems to work properly, it's just the ports that are combined.

Here is an original layout:

Screenshot 2024-10-23 at 11 42 30 AM

Initial Layout

code

{
  "id": "--eclipse-layout-kernel-root",
  "layoutOptions": {
    "elk.algorithm": "layered",
    "elk.direction": "DOWN",
    "elk.layered.nodePlacement.strategy": "NETWORK_SIMPLEX",
    "elk.aspectRatio": 1.1271249076127126
  },
  "children": [
    {
      "id": "class-top",
      "layoutOptions": {
        "elk.algorithm": "layered",
        "elk.direction": "DOWN",
        "elk.spacing.componentComponent": "5",
        "elk.spacing.nodeNode": "5",
        "elk.padding": "[top=5,left=5,bottom=5,right=5]",
        "elk.spacing.portPort": "0",
        "portConstraints": "FREE"
      },
      "children": [
        {
          "id": "node-//",
          "width": 24,
          "height": 24,
          "ports": [
            {
              "id": "port-node-//-0",
              "layoutOptions": {
                "port.side": "SOUTH",
                "port.index": "1"
              }
            },
            {
              "id": "port-node-//-1",
              "layoutOptions": {
                "port.side": "SOUTH",
                "port.index": "0"
              }
            }
          ],
          "labels": [
            {
              "text": "/"
            }
          ],
          "layoutOptions": {
            "portConstraints": "FIXED_ORDER"
          }
        }
      ],
      "ports": [
        {
          "id": "port-class-incoming-//-0"
        },
        {
          "id": "port-class-incoming-//-1"
        },
        {
          "id": "port-class-outgoing-//-0"
        },
        {
          "id": "port-class-outgoing-//-1"
        }
      ],
      "edges": [
        {
          "id": "edge-inner-//-0",
          "edgeID": "//-0",
          "sourceNode": "node-//",
          "targetNode": "class-top",
          "sources": [
            "port-node-//-0"
          ],
          "targets": [
            "port-class-outgoing-//-0"
          ]
        },
        {
          "id": "edge-inner-//-1",
          "edgeID": "//-1",
          "sourceNode": "node-//",
          "targetNode": "class-top",
          "sources": [
            "port-node-//-1"
          ],
          "targets": [
            "port-class-outgoing-//-1"
          ]
        }
      ]
    }
  ],
  "edges": [
    {
      "id": "edge-outer-//-0",
      "edgeID": "//-0",
      "sourceNode": "node-//",
      "targetNode": "class-top",
      "sources": [
        "port-class-outgoing-//-0"
      ],
      "targets": [
        "port-class-incoming-//-0"
      ]
    },
    {
      "id": "edge-outer-//-1",
      "edgeID": "//-1",
      "sourceNode": "node-//",
      "targetNode": "class-top",
      "sources": [
        "port-class-outgoing-//-1"
      ],
      "targets": [
        "port-class-incoming-//-1"
      ]
    }
  ]
}

And here is the interactive version of it, using the positions of the first one to start:

Screenshot 2024-10-23 at 11 43 10 AM

Interactive Layout:

code

{
  "id": "--eclipse-layout-kernel-root",
  "layoutOptions": {
    "elk.algorithm": "layered",
    "elk.direction": "DOWN",
    "elk.layered.nodePlacement.strategy": "INTERACTIVE",
    "elk.aspectRatio": 1.1271249076127126,
    "elk.layered.cycleBreaking.strategy": "INTERACTIVE",
    "elk.layered.layering.strategy": "INTERACTIVE",
    "elk.layered.crossingMinimization.semiInteractive": "true"
  },
  "children": [
    {
      "id": "class-top",
      "layoutOptions": {
        "elk.algorithm": "layered",
        "elk.direction": "DOWN",
        "elk.spacing.componentComponent": "5",
        "elk.spacing.nodeNode": "5",
        "elk.padding": "[top=5,left=5,bottom=5,right=5]",
        "elk.spacing.portPort": "0",
        "portConstraints": "FREE",
        "elk.layered.cycleBreaking.strategy": "INTERACTIVE",
        "elk.layered.layering.strategy": "INTERACTIVE",
        "elk.layered.nodePlacement.strategy": "INTERACTIVE",
        "elk.layered.crossingMinimization.semiInteractive": "true"
      },
      "children": [
        {
          "id": "node-//",
          "width": 24,
          "height": 24,
          "ports": [
            {
              "id": "port-node-//-0",
              "layoutOptions": {
                "port.side": "SOUTH",
                "port.index": "1"
              },
              "x": 8,
              "y": 24
            },
            {
              "id": "port-node-//-1",
              "layoutOptions": {
                "port.side": "SOUTH",
                "port.index": "0"
              },
              "x": 16,
              "y": 24
            }
          ],
          "labels": [
            {
              "text": "/"
            }
          ],
          "layoutOptions": {
            "portConstraints": "FIXED_ORDER"
          },
          "x": 5,
          "y": 5
        }
      ],
      "ports": [
        {
          "id": "port-class-incoming-//-0",
          "x": 5,
          "y": 0
        },
        {
          "id": "port-class-incoming-//-1",
          "x": 10,
          "y": 0
        },
        {
          "id": "port-class-outgoing-//-0",
          "x": 10,
          "y": 98
        },
        {
          "id": "port-class-outgoing-//-1",
          "x": 10,
          "y": 98
        }
      ],
      "edges": [
        {
          "id": "edge-inner-//-0",
          "edgeID": "//-0",
          "sourceNode": "node-//",
          "targetNode": "class-top",
          "sources": [
            "port-node-//-0"
          ],
          "targets": [
            "port-class-outgoing-//-0"
          ]
        },
        {
          "id": "edge-inner-//-1",
          "edgeID": "//-1",
          "sourceNode": "node-//",
          "targetNode": "class-top",
          "sources": [
            "port-node-//-1"
          ],
          "targets": [
            "port-class-outgoing-//-1"
          ]
        }
      ],
      "x": 22,
      "y": 22
    }
  ],
  "edges": [
    {
      "id": "edge-outer-//-0",
      "edgeID": "//-0",
      "sourceNode": "node-//",
      "targetNode": "class-top",
      "sources": [
        "port-class-outgoing-//-0"
      ],
      "targets": [
        "port-class-incoming-//-0"
      ]
    },
    {
      "id": "edge-outer-//-1",
      "edgeID": "//-1",
      "sourceNode": "node-//",
      "targetNode": "class-top",
      "sources": [
        "port-class-outgoing-//-1"
      ],
      "targets": [
        "port-class-incoming-//-1"
      ]
    }
  ]
}

Expected behavior I would expect the ports to be distinct instead of being combined in the interactive layout.

Screenshots [included above]

ELK Version 0.9.3

Additional context

I have tried it with and without "elk.layered.crossingMinimization.semiInteractive": "true" as well as "elk.layered.crossingMinimization.strategy": "INTERACTIVE" and neither seem to help.

This bug is from https://github.com/egraphs-good/egraph-visualizer

saulshanabrook avatar Oct 23 '24 15:10 saulshanabrook

At least one part of the issue is the INTERACTIVE node placement strategy, as seen here. The slightly different second graph you posted in elkt seems to be fine.

I could not replicate that adding the interactive strategies caused the problem you described in elkt. Maybe the issues come with port sizes of zero and concrete positions for ports?

soerendomroes avatar Oct 24 '24 07:10 soerendomroes