Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ELK layout with constraints #786

Closed
yuey1203 opened this issue Jan 13, 2022 · 5 comments
Closed

ELK layout with constraints #786

yuey1203 opened this issue Jan 13, 2022 · 5 comments
Labels
question Request for support in using ELK.

Comments

@yuey1203
Copy link

I've been using ELK to do some layouts in Sprotty and it has been working very well so far. However, I was wondering if there was any way to add constraints such as fixing node positions, port positions, and re-doing ELK layout on the unfixed nodes. Overall this seems to be pretty difficult especially for the layered version of ELK as per #315, but was wondering if there was any pointers on where to start/look if we wanted to create/add this functionality, either via ELK or other routing libraries such as Adaptagrams.
Overall, we just want to be able to add some constraints to node/port placement -- and potentially use the Adaptagrams libavoid library to route the edges.
Any help or guidance would be greatly appreciated!

@soerendomroes
Copy link
Contributor

There are two different ways to constrain node positions.
The first one does only require to layout once, however, it is needed to specify previous positions of nodes:
Here the specified position induces the layering and the positions in a layer.
You have to make sure that one can clearly identify layers by the position of the nodes. For example, if a node has the dimension 200x200 the next layer has to be at least 201 apart from the current one.

algorithm: layered
elk.direction: RIGHT
crossingMinimization.semiInteractive: true
cycleBreaking.strategy: INTERACTIVE
layering.strategy: INTERACTIVE
node n1 {
    layout [position: 0, 0]
    label "n1"
}
node n2{
    layout [position: 100, 0]
    label "n2"
}
node n3{
    layout [position: 200, 0]
    label "n3"
}
edge n1 -> n2
edge n1 -> n3

The other way requires configuring an additional layout run. The first layout run provides these kind of positions and an initial layering on which we can work to calculate positions on constraint nodes.
If you want to know how this might be done I suggest checking out Klighd to see how an additional layout run is added at the example of AbstractDiagramSynthesis in getAdditionalLayoutConfigs(final KNode viewModel, final ViewContext viewContext) which is implemented by a concrete synthesis to add an interactive layout configurator if the interactiveLayout property is set to true. This additional config is applied in the LightDiagramServices in layoutDiagram(...).

This would allow using more abstract absolute position and layer constraints such as the ones described here.

Port positions are fixed by setting portConstraints accordingly and specifying positions or at least the side of a port.

@yuey1203
Copy link
Author

Thanks for the quick response! I looked into the KLighD repo to try to understand the places that you pointed us towards. Would there be an example for ELK with KlighD somewhere? Some of it is quite confusing and an example would be a great starting point. We're trying to mostly use this on the backend for generating the placements and routes, and we were also wondering if there was potentially a Python wrapper for this logic in a similar manner to sprotty-elk?

@soerendomroes
Copy link
Contributor

Yes, the KIELER tool uses two other repositories (semantics and pragmatics) together with KLighd and ELK. For example the ElkGraphDiagramSynthesis in the pragmatic specifies the getAdditionalLayoutConfigs method to add an additional layout run.
However, I think this is again very complicated and difficult to see through.

I try to point you to the important parts of ELK instead that are used by Klighd to run more than one algorithm after the other:
Note that these parts are only available in Java (and have some Eclipse dependencies that are, however, not necessarily needed) and are not added to elk-js if you consider client-side layout.

In the elk.core.service is the DiagramLayoutEngine with a LayoutMapping layout(final IWorkbenchPart workbenchPart, final Object diagramPart,final IElkProgressMonitor progressMonitor, final Parameters params) method. params holds the potential different layout configurations or graph visitors that iterate through the graph to set different layout algorithm or whatever else might be needed for additional layout runs. From this on several layout methods are called until the final layout is executed. I suggest to replicate this or call it depending on your context.

@yuey1203
Copy link
Author

I'll take a deeper look into the DiagramLayoutEngine then to see if I can get a better understanding of the layout engine then. Will probably have further questions :)

@soerendomroes
Copy link
Contributor

With the next ELK release it should be possible to define the layer and position of a node also via the ordering in the model file. This does work very good for constraining nodes to be in a specific layer (again, in-alyer eges are still possible) but does not necessarily constrain the position since it still tries to optimize for edge crossings.

As an example

considerModelOrderStrategy: NODES_AND_EDGES
cycleBreaking.strategy: MODEL_ORDER

node n1
edge n1 -> n3
edge n1 -> n2
node n2
edge n2 -> n3
node n3

Orders the outgoing edges of n1 such that the long edge to n3 is on top of n2.
Moreover, n1 is in the first layer since it is the first node and no backward edge is created.

The following example however creates a backward edge. n1 is in the first layer, n3 in the second and n2 in the third.

considerModelOrderStrategy: NODES_AND_EDGES
cycleBreaking.strategy: MODEL_ORDER

node n1
edge n1 -> n3
edge n1 -> n2
node n3
node n2
edge n2 -> n3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Request for support in using ELK.
Projects
None yet
Development

No branches or pull requests

2 participants