Skip to content

Commit

Permalink
Merge pull request #1071 from skieffer/edge-coords
Browse files Browse the repository at this point in the history
Provide JSON coordinate options
  • Loading branch information
soerendomroes authored Jan 29, 2025
2 parents baadf5f + 82ea83d commit 4ca07e0
Show file tree
Hide file tree
Showing 10 changed files with 1,677 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ Since ELK graphs are based on EMF, you can simply obtain an instance of the `Elk
One method of particular value to layout algorithm developers is `firstEdgeSection(edge, reset, removeOthers)`, which returns the first edge section of the given edge, optionally resetting its layout data and removing all other edge sections. If the edge doesn't have any edge sections yet, one is created and added to it. This method is handy for applying layout results.

* **Edge Containment:** Unless one uses one of the `create` methods to create edges, finding the node an edge should be contained in may be annoying (thus, don't). The `updateContainment(ElkEdge)` method automatically computes the best containment and puts the edge there. This requires at least one of the edge's end points to be set, since that is what determines the best containment.
Note that, when graphs are imported into ELK from JSON, `updateContainment()` is automatically called on each edge. Authors of graphs in JSON format are therefore not responsible for placing edges
inside their proper container nodes.

While computing the containment is a little intricate (hence the utility method), the actual rule that determines the best containment is rather simple: it is the lowest common ancestor of all end points, where the ancestors of a node are defined as the sequence of nodes from the node itself to the graph's root node. Taking the graph at the top of this page as an example, the rule has the following implications for different types of edges:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,51 @@ The coordinates of most elements are relative to their parent element. There are

* Edge labels are relative to the coordinate system their edge is relative to.
* Source points, bend points, and target points of edges are relative to the edge's containing node. Following the usual containment conventions (as implemented in `ElkGraphUtil`) results in what is displayed in the image above.

## JSON

One way of using ELK is to define a graph using JSON, and then
transfer the computed layout back to the initial JSON graph.
See [_JSON Format_]({{< relref "documentation/tooldevelopers/graphdatastructure/jsonformat.md" >}}).
When working this way, it is possible to control what type of coordinates you get,
using the `org.eclipse.elk.json.shapeCoords` and `org.eclipse.elk.json.edgeCoords` layout options.

### Shape Coords

This setting controls the coordinate system that will be used for all nodes, ports, and labels of nodes and ports.

There are three possible values:

* `INHERIT`: Inherit the value from the parent element.
* `PARENT`: Coordinates are relative to the parent element.
* `ROOT`: Coordinates are relative to the root node, i.e. global coordinates.

The default value is `INHERIT`, except at the root node, where the default is `PARENT`.
Thus, the default behavior is as described in the image at the top of this page.
Setting `ROOT` allows you to instead use a "flat" coordinate system.

### Edge Coords

This setting controls the coordinate system that will be used for all source, bend, and target points of edges,
as well as all edge labels.

There are four possible values:

* `INHERIT`: Inherit the value from the parent element.
* `CONTAINER`: Coordinates are relative to the edge's proper container node (see below).
* `PARENT`: Coordinates are relative to the node in which the edge was defined in the given JSON.
* `ROOT`: Coordinates are relative to the root node, i.e. global coordinates.

The default value is `INHERIT`, except at the root node, where the default is (for historical reasons) `CONTAINER`.
Thus, the default behavior is as described at the top of this page.

The definition of an edge's proper container is given at the end of the page on the
[_Graph Data Structure_]({{< relref "documentation/tooldevelopers/graphdatastructure.md" >}}).
It involves lowest common ancestors, and can be tricky to compute correctly.
In particular, since you are allowed to define an edge under any node whatsoever in the input JSON, the edge's
*parent* node (the one it is defined under) may be different from its container.

If you elect to work in `CONTAINER` mode, ELK helps you by writing a `container` property into each edge after layout,
giving the `id` of the edge's container node. This can then be used to interpret the coordinates.

If you elect to work in `PARENT` or `ROOT` mode instead, then you do not need to know about edge containers at all.
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,12 @@ labels.
Nodes can have an arbitrary number of ports. Edges can connect to a node either directly or
through one of its ports. A node can also contain an arbitrary number of child nodes. A graph
is actually nothing more than a simple node whose children are the top-level nodes of the graph.
Finally, a node can contain edges. These edges do not necessarily connect to the node, but will
usually connect its children. The edge coordinates will be interpreted relative to the upper
left corner of the node which contains it.
Finally, a node can contain edges. While it is common to define those edges under a given node
that connect that node's children, in fact any edge may be defined under any node, regardless of its
end points. This allows for flexibility when defining hierarchy-crossing edges, as well as for
alternative schemes, such as defining all edges at the root level.
See [_Coordinate System_]({{< relref "documentation/tooldevelopers/graphdatastructure/coordinatesystem.md" >}})
for the rules for interpreting edge coordinates.

```json
{
Expand Down
23 changes: 23 additions & 0 deletions plugins/org.eclipse.elk.core/src/org/eclipse/elk/core/Core.melk
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,29 @@ advanced option omitNodeMicroLayout: boolean {
targets parents
}

// --- JSON
group json {

option shapeCoords: ShapeCoords {
label "Shape Coords"
description
"For layouts transferred into JSON graphs, specify the coordinate system
to be used for nodes, ports, and labels of nodes and ports."
default = ShapeCoords.INHERIT
targets parents
}

option edgeCoords: EdgeCoords {
label "Edge Coords"
description
"For layouts transferred into JSON graphs, specify the coordinate system
to be used for edge route points and edge labels."
default = EdgeCoords.INHERIT
targets parents
}

}

// --- SPACING
group spacing {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*******************************************************************************
* Copyright (c) 2024 Kiel University and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.elk.core.options;

/**
* Edge coordinate systems for JSON output. To be accessed using {@link CoreOptions#JSON_EDGE_COORDS}.
* Applies to edges, and to labels of edges.
*/
public enum EdgeCoords {

/**
* Inherit the parent node's coordinate system. The root node has no parent node; here, this setting defaults to
* {@link #CONTAINER}.
*/
INHERIT,
/** relative to the edge's proper container node. */
CONTAINER,
/** relative to the edge's JSON parent node. */
PARENT,
/** relative to the root node, a.k.a. global coordinates. */
ROOT;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*******************************************************************************
* Copyright (c) 2024 Kiel University and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.elk.core.options;

/**
* Shape coordinate systems for JSON output. To be accessed using {@link CoreOptions#JSON_SHAPE_COORDS}.
* Applies to nodes, ports, and labels of nodes and ports.
*/
public enum ShapeCoords {

/**
* Inherit the parent shape's coordinate system. The root node has no parent shape; here, this setting defaults to
* {@link #PARENT}.
*/
INHERIT,
/** relative to the shape's JSON parent shape. */
PARENT,
/** relative to the root node, a.k.a. global coordinates. */
ROOT;

}
Loading

0 comments on commit 4ca07e0

Please sign in to comment.