Giter Club home page Giter Club logo

Comments (18)

uruuru avatar uruuru commented on August 15, 2024

Please try to set the layout option hierarchyHandling to INCLUDE_CHILDREN.

It is necessary to lay out hierarchical edges. In klayjs this was the default behavior; in elkjs the default value is SEPARATE_CHILDREN (to be consistent with the java version of elk).

from elkjs.

jbeard4 avatar jbeard4 commented on August 15, 2024

Thank you, I will try this.

from elkjs.

jbeard4 avatar jbeard4 commented on August 15, 2024

I tried setting hierarchyHandling to INCLUDE_CHILDREN using the defaultLayoutOptions option of the ELK constructor. This resolved the issue of parents targeting children, but created an issue of children targeting parents. Please consider the following reduced example.

Expected behavior (generated with klay):

screen shot 2018-08-11 at 8 41 33 pm

With hierarchyHandling unset (default behavior), I get the following graph, which matches the expected output:

screen shot 2018-08-11 at 8 43 41 pm

With hierarchyHandling set to INCLUDE_CHILDREN, I get the following graph:

screen shot 2018-08-11 at 8 42 32 pm

The edge from A1 to A is misaligned.

Here is the kgraph before layout:

{
    "id": "$generated-scxml-0",
    "labels": [
        {
            "text": ""
        }
    ],
    "edges": [
        {
            "id": "a1:transition:0",
            "source": "a1",
            "target": "A",
            "labels": [
                {
                    "text": "e",
                    "width": 1.765625,
                    "height": 4.53125
                }
            ],
            "targetPort": "A_exit:1",
            "$type": "hyperlink"
        },
        {
            "id": "$generated_A_initial_0:transition:0",
            "source": "$generated_A_initial_0",
            "target": "a1",
            "labels": []
        },
        {
            "id": "$generated_$generated-scxml-0_initial_0:transition:0",
            "source": "$generated_$generated-scxml-0_initial_0",
            "target": "A",
            "labels": []
        }
    ],
    "properties": {
        "borderSpacing": 6
    },
    "$type": "scxml",
    "children": [
        {
            "id": "A",
            "labels": [
                {
                    "text": "A"
                }
            ],
            "edges": [
                {
                    "id": "A_exit:1_A_enter:0",
                    "source": "A",
                    "target": "A",
                    "sourcePort": "A_exit:1",
                    "targetPort": "A_enter:0",
                    "labels": [],
                    "$hyperlink": "a1:transition:0"
                }
            ],
            "properties": {
                "borderSpacing": 6
            },
            "$type": "state",
            "children": [
                {
                    "id": "a1",
                    "labels": [
                        {
                            "text": "a1"
                        }
                    ],
                    "edges": [],
                    "properties": {
                        "borderSpacing": 6
                    },
                    "$type": "state",
                    "x": 0,
                    "y": 0,
                    "width": 8.765625,
                    "height": 9.53125
                },
                {
                    "id": "a2",
                    "labels": [
                        {
                            "text": "a2"
                        }
                    ],
                    "edges": [],
                    "properties": {
                        "borderSpacing": 6
                    },
                    "$type": "state",
                    "x": 0,
                    "y": 0,
                    "width": 8.765625,
                    "height": 9.53125
                },
                {
                    "id": "$generated_A_initial_0",
                    "labels": [
                        {
                            "text": "◉ $generated_A_initial_0"
                        }
                    ],
                    "edges": [],
                    "properties": {
                        "borderSpacing": 6
                    },
                    "$type": "initial",
                    "x": 0,
                    "y": 0,
                    "width": 4,
                    "height": 4
                }
            ],
            "ports": [
                {
                    "id": "A_enter:0"
                },
                {
                    "id": "A_exit:1"
                }
            ],
            "x": 0,
            "y": 0,
            "width": 7.875,
            "height": 9.53125
        },
        {
            "id": "$generated_$generated-scxml-0_initial_0",
            "labels": [
                {
                    "text": "◉ $generated_$generated-scxml-0_initial_0"
                }
            ],
            "edges": [],
            "properties": {
                "borderSpacing": 6
            },
            "$type": "initial",
            "x": 0,
            "y": 0,
            "width": 4,
            "height": 4
        }
    ],
    "width": 5,
    "height": 5
}

Here is the kgraph after layout with hierarchyHandling set to INCLUDE_CHILDREN:

{
    "id": "$generated-scxml-0",
    "labels": [
        {
            "text": "",
            "x": 0,
            "y": 0,
            "width": 0,
            "height": 0
        }
    ],
    "edges": [
        {
            "id": "a1:transition:0",
            "source": "a1",
            "target": "A",
            "labels": [
                {
                    "text": "e",
                    "width": 1.765625,
                    "height": 4.53125,
                    "x": 105.53125,
                    "y": 58.53125
                }
            ],
            "targetPort": "A_exit:1",
            "$type": "hyperlink",
            "sections": [
                {
                    "id": "a1:transition:0_s0",
                    "startPoint": {
                        "x": 85.53125,
                        "y": 55.53125
                    },
                    "endPoint": {
                        "x": 119.296875,
                        "y": 55.53125
                    }
                }
            ]
        },
        {
            "id": "$generated_A_initial_0:transition:0",
            "source": "$generated_A_initial_0",
            "target": "a1",
            "labels": [],
            "sections": [
                {
                    "id": "$generated_A_initial_0:transition:0_s0",
                    "startPoint": {
                        "x": 20.765625,
                        "y": 43.53125
                    },
                    "endPoint": {
                        "x": 40.765625,
                        "y": 43.53125
                    }
                }
            ]
        },
        {
            "id": "$generated_$generated-scxml-0_initial_0:transition:0",
            "source": "$generated_$generated-scxml-0_initial_0",
            "target": "A",
            "labels": [],
            "sections": [
                {
                    "id": "$generated_$generated-scxml-0_initial_0:transition:0_s0",
                    "startPoint": {
                        "x": 16,
                        "y": 24
                    },
                    "endPoint": {
                        "x": 36,
                        "y": 24
                    }
                }
            ]
        }
    ],
    "properties": {
        "borderSpacing": 6
    },
    "$type": "scxml",
    "children": [
        {
            "id": "A",
            "labels": [
                {
                    "text": "A",
                    "x": 0,
                    "y": 0,
                    "width": 0,
                    "height": 0
                }
            ],
            "edges": [
                {
                    "id": "A_exit:1_A_enter:0",
                    "source": "A",
                    "target": "A",
                    "sourcePort": "A_exit:1",
                    "targetPort": "A_enter:0",
                    "labels": [],
                    "$hyperlink": "a1:transition:0",
                    "sections": [
                        {
                            "id": "A_exit:1_A_enter:0_s0",
                            "startPoint": {
                                "x": 119.296875,
                                "y": 55.53125
                            },
                            "endPoint": {
                                "x": 36,
                                "y": 34
                            },
                            "bendPoints": [
                                {
                                    "x": 129.296875,
                                    "y": 55.53125
                                },
                                {
                                    "x": 129.296875,
                                    "y": 86.0625
                                },
                                {
                                    "x": 26,
                                    "y": 86.0625
                                },
                                {
                                    "x": 26,
                                    "y": 34
                                }
                            ]
                        }
                    ]
                }
            ],
            "properties": {
                "borderSpacing": 6
            },
            "$type": "state",
            "children": [
                {
                    "id": "a1",
                    "labels": [
                        {
                            "text": "a1",
                            "x": 0,
                            "y": 0,
                            "width": 0,
                            "height": 0
                        }
                    ],
                    "edges": [],
                    "properties": {
                        "borderSpacing": 6
                    },
                    "$type": "state",
                    "x": 40.765625,
                    "y": 38.765625,
                    "width": 8.765625,
                    "height": 9.53125,
                    "$H": 284
                },
                {
                    "id": "a2",
                    "labels": [
                        {
                            "text": "a2",
                            "x": 0,
                            "y": 0,
                            "width": 0,
                            "height": 0
                        }
                    ],
                    "edges": [],
                    "properties": {
                        "borderSpacing": 6
                    },
                    "$type": "state",
                    "x": 12,
                    "y": 12,
                    "width": 8.765625,
                    "height": 9.53125,
                    "$H": 287
                },
                {
                    "id": "$generated_A_initial_0",
                    "labels": [
                        {
                            "text": "◉ $generated_A_initial_0",
                            "x": 0,
                            "y": 0,
                            "width": 0,
                            "height": 0
                        }
                    ],
                    "edges": [],
                    "properties": {
                        "borderSpacing": 6
                    },
                    "$type": "initial",
                    "x": 16.765625,
                    "y": 41.53125,
                    "width": 4,
                    "height": 4,
                    "$H": 290
                }
            ],
            "ports": [
                {
                    "id": "A_enter:0",
                    "x": 0,
                    "y": 22,
                    "width": 0,
                    "height": 0
                },
                {
                    "id": "A_exit:1",
                    "x": 83.296875,
                    "y": 43.53125,
                    "width": 0,
                    "height": 0
                }
            ],
            "x": 36,
            "y": 12,
            "width": 83.296875,
            "height": 64.0625,
            "$H": 278
        },
        {
            "id": "$generated_$generated-scxml-0_initial_0",
            "labels": [
                {
                    "text": "◉ $generated_$generated-scxml-0_initial_0",
                    "x": 0,
                    "y": 0,
                    "width": 0,
                    "height": 0
                }
            ],
            "edges": [],
            "properties": {
                "borderSpacing": 6
            },
            "$type": "initial",
            "x": 12,
            "y": 22,
            "width": 4,
            "height": 4,
            "$H": 293
        }
    ],
    "width": 141.296875,
    "height": 98.0625,
    "$H": 12,
    "x": 0,
    "y": 0
}

Does hierarchyHandling need to be set at an individual node level, rather than globally? If so, what are the conditions for which hierarchyHandling it must be set?

Thank you very much for your help with this.

from elkjs.

uruuru avatar uruuru commented on August 15, 2024

If you set hierarchyHandling for the top-level node, the behavior is propagated to all children automatically. Setting it for the top-level node should thus yield the same behavior as specifying it as part of the defaultLayoutOptions.

The results you get do not immediately make sense to me. I won't be able to look at it more closely before next weekend though. Maybe @le-cds finds time to check it in elk itself in the meantime.

from elkjs.

jbeard4 avatar jbeard4 commented on August 15, 2024

Sounds good. Thank you @uruuru

from elkjs.

jbeard4 avatar jbeard4 commented on August 15, 2024

@le-cds Please let me know if I can provide additional information to help reproduce this

from elkjs.

le-cds avatar le-cds commented on August 15, 2024

Sorry, I totally neglected this ticket. I'll be sure to take a look at it over the next few days.

from elkjs.

jbeard4 avatar jbeard4 commented on August 15, 2024

No problem. Thank you for your help with this.

from elkjs.

le-cds avatar le-cds commented on August 15, 2024

Right, I've spent a few minutes looking into this and have a few comments.

Hierarchy handling should only be necessary for long hierarchical edges. What you seem to have here, however, are short hierarchical edges: edges that connect a node with one of its direct children. ELK Layered should support those right out of the box. There are a few catches, however.

First, short hierarchical edges are a bit particular when it comes to ports. They usually need to be connected to an explicit port of their hierarchical node. When I didn't do so while reproducing your example, this is when I got your initial result.

Second, you need to be careful as to where you define your edges. The exact rules are at the bottom of this page (where it says Edge Containment). In short, if you have an edge that connects two children of A, that edge needs to be defined in A, not in the surrounding graph. Similarly, if you have an edge that connects A to one of its children, that too needs to be defined in A. That may explain the strange offsets you're experiencing.

As I already mentioned in #48, this may be different for graphs defined using JSON, but @uruuru will have to shed some light on that question.

However, even with all of these problems solved, there seems to be a layout bug hidden in what remains. This is what I got when I tried to reproduce your graph:

bug

I created eclipse/elk#369 to track that.

from elkjs.

jbeard4 avatar jbeard4 commented on August 15, 2024

Thank you for looking into this.

from elkjs.

uruuru avatar uruuru commented on August 15, 2024

The idea is that the json format behaves the same wrt edge containments.

from elkjs.

uruuru avatar uruuru commented on August 15, 2024

@le-cds have you had a look at this lately? Maybe any of your latest changes fixes this?

from elkjs.

le-cds avatar le-cds commented on August 15, 2024

According to my last comment here, this was related to eclipse/elk#369, which has since been fixed. Is there anything else I need to look at?

from elkjs.

uruuru avatar uruuru commented on August 15, 2024

I reduced the original example a bit and (hopefully) moved the edges to correct containment: see here.

The result is still odd in that the hierarchical edge A:transition:0 breaks the layout. Removing the edge gives a proper layout.

Make sure to select 0.6.1 when trying it.

from elkjs.

jbeard4 avatar jbeard4 commented on August 15, 2024

Thank you for continuing to investigate this.

from elkjs.

le-cds avatar le-cds commented on August 15, 2024

I reduced the original example a bit and (hopefully) moved the edges to correct containment

As I mentioned in my previous comment, proper edge containment is just one half of the solution; using ports is the other. Having A:transition:0 connect to A through an explicit port should solve the issue.

from elkjs.

uruuru avatar uruuru commented on August 15, 2024

Shouldn't the ports (dummies) be added automatically?

You wrote:

They usually need to be connected to an explicit port of their hierarchical node.

Is that something we documented?

from elkjs.

le-cds avatar le-cds commented on August 15, 2024

Shouldn't the ports (dummies) be added automatically?

With INCLUDE_CHILDREN, they in fact are. Without that option, they are not, but should be. There's a ticket about that, namely eclipse/elk#60.

I took your corrected JSON file again and tried to reproduce the issue with the following ELKT code (I'm using ELKT because I find it easier to read):

algorithm: layered
hierarchyHandling: INCLUDE_CHILDREN

node A {
	node a1
	node a2
	edge a2 -> a1
	edge A -> a1
}
node B
edge B -> A

ELK Layered produces this result on my machine:

result

I don't see where the problem should come from. 😕

from elkjs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.