use of org.eclipse.elk.core.options.EdgeRouting in project elk by eclipse.
the class ElkGraphLayoutTransferrer method applyLayout.
/**
* Applies the layout information contained in the given LGraph to the ElkGraph elements it was
* created from. All source ElkGraph elements are expected to be accessible through their LGraph
* counterparts through the {@link InternalProperties#ORIGIN} property.
*
* @param lgraph the LGraph whose layout information to apply.
*/
public void applyLayout(final LGraph lgraph) {
Object graphOrigin = lgraph.getProperty(InternalProperties.ORIGIN);
if (!(graphOrigin instanceof ElkNode)) {
return;
}
// The ElkNode that represents this graph in the original ElkGraph
ElkNode parentElkNode = (ElkNode) graphOrigin;
// The LNode that represents this graph in the upper hierarchy level, if any
LNode parentLNode = (LNode) lgraph.getParentNode();
// Get the offset to be added to all coordinates
KVector offset = new KVector(lgraph.getOffset());
// Adjust offset (and with it the positions) by the requested padding
LPadding lPadding = lgraph.getPadding();
offset.x += lPadding.left;
offset.y += lPadding.top;
// Set node padding, if it was computed during layout
final EnumSet<SizeOptions> sizeOptions = parentElkNode.getProperty(LayeredOptions.NODE_SIZE_OPTIONS);
if (sizeOptions.contains(SizeOptions.COMPUTE_PADDING)) {
ElkPadding padding = parentElkNode.getProperty(LayeredOptions.PADDING);
padding.setBottom(lPadding.bottom);
padding.setTop(lPadding.top);
padding.setLeft(lPadding.left);
padding.setRight(lPadding.right);
}
// Along the way, we collect the list of edges to be processed later
List<LEdge> edgeList = Lists.newArrayList();
// Process the nodes
for (LNode lnode : lgraph.getLayerlessNodes()) {
if (representsNode(lnode)) {
applyNodeLayout(lnode, offset);
} else if (representsExternalPort(lnode) && parentLNode == null) {
// We have an external port here on the top-most hierarchy level of the current (possibly
// hierarchical) layout run; set its position
ElkPort elkport = (ElkPort) lnode.getProperty(InternalProperties.ORIGIN);
KVector portPosition = LGraphUtil.getExternalPortPosition(lgraph, lnode, elkport.getWidth(), elkport.getHeight());
elkport.setLocation(portPosition.x, portPosition.y);
}
// correctly)
for (LPort port : lnode.getPorts()) {
port.getOutgoingEdges().stream().filter(edge -> !LGraphUtil.isDescendant(edge.getTarget().getNode(), lnode)).forEach(edge -> edgeList.add(edge));
}
}
// Collect edges that go from the current graph's representing LNode down into its descendants
if (parentLNode != null) {
for (LPort port : parentLNode.getPorts()) {
port.getOutgoingEdges().stream().filter(edge -> LGraphUtil.isDescendant(edge.getTarget().getNode(), parentLNode)).forEach(edge -> edgeList.add(edge));
}
}
// Iterate through all edges
EdgeRouting routing = parentElkNode.getProperty(LayeredOptions.EDGE_ROUTING);
for (LEdge ledge : edgeList) {
applyEdgeLayout(ledge, routing, offset, lPadding);
}
// Setup the parent node
applyParentNodeLayout(lgraph);
// Process nested subgraphs
for (LNode lnode : lgraph.getLayerlessNodes()) {
LGraph nestedGraph = lnode.getNestedGraph();
if (nestedGraph != null) {
applyLayout(nestedGraph);
}
}
}
use of org.eclipse.elk.core.options.EdgeRouting in project elk by eclipse.
the class FixedLayoutProvider method layout.
@Override
public void layout(final ElkNode layoutNode, final IElkProgressMonitor progressMonitor) {
progressMonitor.begin("Fixed Layout", 1);
EdgeRouting edgeRouting = layoutNode.getProperty(CoreOptions.EDGE_ROUTING);
double maxx = 0;
double maxy = 0;
for (ElkNode node : layoutNode.getChildren()) {
// set the fixed position of the node, or leave it as it is
KVector pos = node.getProperty(FixedLayouterOptions.POSITION);
if (pos != null) {
node.setLocation(pos.x, pos.y);
// set the fixed size of the node
if (node.getProperty(FixedLayouterOptions.NODE_SIZE_CONSTRAINTS).contains(SizeConstraint.MINIMUM_SIZE)) {
KVector minSize = node.getProperty(FixedLayouterOptions.NODE_SIZE_MINIMUM);
if (minSize.x > 0 && minSize.y > 0) {
ElkUtil.resizeNode(node, minSize.x, minSize.y, true, true);
}
}
}
maxx = Math.max(maxx, node.getX() + node.getWidth());
maxy = Math.max(maxy, node.getY() + node.getHeight());
// set the fixed position of the node labels, or leave them as they are
for (ElkLabel label : node.getLabels()) {
pos = label.getProperty(FixedLayouterOptions.POSITION);
if (pos != null) {
label.setLocation(pos.x, pos.y);
}
maxx = Math.max(maxx, node.getX() + label.getX() + label.getWidth());
maxy = Math.max(maxy, node.getY() + label.getY() + label.getHeight());
}
// set the fixed position of the ports, or leave them as they are
for (ElkPort port : node.getPorts()) {
pos = port.getProperty(FixedLayouterOptions.POSITION);
if (pos != null) {
port.setLocation(pos.x, pos.y);
}
double portx = node.getX() + port.getX();
double porty = node.getY() + port.getY();
maxx = Math.max(maxx, portx + port.getWidth());
maxy = Math.max(maxy, porty + port.getHeight());
// set the fixed position of the port labels, or leave them as they are
for (ElkLabel label : port.getLabels()) {
pos = label.getProperty(FixedLayouterOptions.POSITION);
if (pos != null) {
label.setLocation(pos.x, pos.y);
}
maxx = Math.max(maxx, portx + label.getX() + label.getWidth());
maxy = Math.max(maxy, porty + label.getY() + label.getHeight());
}
}
// set fixed routing for the node's outgoing edges (both simple and hierarchical), or leave them as they are
for (ElkEdge edge : ElkGraphUtil.allOutgoingEdges(node)) {
KVector maxv = processEdge(edge, edgeRouting);
maxx = Math.max(maxx, maxv.x);
maxy = Math.max(maxy, maxv.y);
}
// note that this potentially results in hierarchical edges being handled twice
for (ElkEdge edge : ElkGraphUtil.allIncomingEdges(node)) {
if (ElkGraphUtil.getSourceNode(edge).getParent() != layoutNode) {
KVector maxv = processEdge(edge, edgeRouting);
maxx = Math.max(maxx, maxv.x);
maxy = Math.max(maxy, maxv.y);
}
}
}
// if orthogonal routing is selected, determine the junction points
if (edgeRouting == EdgeRouting.ORTHOGONAL) {
for (ElkNode node : layoutNode.getChildren()) {
for (ElkEdge edge : ElkGraphUtil.allOutgoingEdges(node)) {
generateJunctionPoints(edge);
}
}
}
// set size of the parent node unless its size should be fixed as well
if (!layoutNode.getProperty(FixedLayouterOptions.NODE_SIZE_FIXED_GRAPH_SIZE)) {
ElkPadding padding = layoutNode.getProperty(FixedLayouterOptions.PADDING);
double newWidth = maxx + padding.getLeft() + padding.getRight();
double newHeight = maxy + padding.getTop() + padding.getBottom();
ElkUtil.resizeNode(layoutNode, newWidth, newHeight, true, true);
}
progressMonitor.done();
}
use of org.eclipse.elk.core.options.EdgeRouting in project elk by eclipse.
the class LGraphToCGraphTransformer method applyLayout.
/**
* Apply the layout from the internal constraint graph back to the original lgraph.
*/
public void applyLayout() {
// apply the compacted positions to nodes
cGraph.cNodes.stream().filter(cNode -> cNode.origin instanceof LNode).forEach(cNode -> {
LNode lNode = (LNode) cNode.origin;
lNode.getPosition().x = cNode.hitbox.x + lNode.getMargin().left;
});
// adjust comment boxes
applyCommentPositions();
// apply new positions to vertical segments
cGraph.cNodes.stream().filter(cNode -> cNode.origin instanceof VerticalSegment).forEach(cNode -> {
double deltaX = cNode.hitbox.x - cNode.hitboxPreCompaction.x;
VerticalSegment vs = (VerticalSegment) cNode.origin;
vs.affectedBends.forEach(b -> b.x += deltaX);
vs.affectedBoundingBoxes.forEach(bb -> bb.x += deltaX);
vs.junctionPoints.forEach(jp -> jp.x += deltaX);
});
// be properly located in between non-straight parts
if (edgeRouting == EdgeRouting.SPLINES) {
// offset selfloops of splines
nodesMap.keySet().stream().flatMap(n -> StreamSupport.stream(n.getOutgoingEdges().spliterator(), false)).filter(e -> e.isSelfLoop()).forEach(sl -> {
LNode lNode = sl.getSource().getNode();
CNode cNode = nodesMap.get(lNode);
double deltaX = cNode.hitbox.x - cNode.hitboxPreCompaction.x;
sl.getBendPoints().offset(deltaX, 0);
});
// offset straight segments
layeredGraph.getLayers().stream().flatMap(l -> l.getNodes().stream()).flatMap(n -> StreamSupport.stream(n.getOutgoingEdges().spliterator(), false)).map(e -> e.getProperty(InternalProperties.SPLINE_ROUTE_START)).filter(chain -> chain != null && !chain.isEmpty()).forEach(spline -> adjustSplineControlPoints(spline));
}
// calculating new graph size and offset
KVector topLeft = new KVector(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
KVector bottomRight = new KVector(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
for (CNode cNode : cGraph.cNodes) {
topLeft.x = Math.min(topLeft.x, cNode.hitbox.x);
topLeft.y = Math.min(topLeft.y, cNode.hitbox.y);
bottomRight.x = Math.max(bottomRight.x, cNode.hitbox.x + cNode.hitbox.width);
bottomRight.y = Math.max(bottomRight.y, cNode.hitbox.y + cNode.hitbox.height);
}
layeredGraph.getOffset().reset().add(topLeft.clone().negate());
layeredGraph.getSize().reset().add(bottomRight.clone().sub(topLeft));
// external port dummies may have been moved ... put them back
applyExternalPortPositions(topLeft, bottomRight);
cleanup();
}
use of org.eclipse.elk.core.options.EdgeRouting in project elk by eclipse.
the class NorthSouthPortPostprocessor method process.
@Override
public void process(final LGraph layeredGraph, final IElkProgressMonitor monitor) {
monitor.begin("Odd port side processing", 1);
// Spline edge routing manages bend points in the edge router. Differentiate behaviour
// depending on edge router.
EdgeRouting routing = layeredGraph.getProperty(LayeredOptions.EDGE_ROUTING);
// Iterate through the layers
for (Layer layer : layeredGraph) {
// Iterate through the nodes (use an array to avoid concurrent modification exceptions)
LNode[] nodeArray = LGraphUtil.toNodeArray(layer.getNodes());
for (LNode node : nodeArray) {
// We only care for North/South Port dummy nodes
if (node.getType() != NodeType.NORTH_SOUTH_PORT) {
continue;
}
if (routing == EdgeRouting.SPLINES) {
// Iterate through ports
for (LPort port : node.getPorts()) {
if (!port.getIncomingEdges().isEmpty()) {
processSplineInputPort(port);
}
if (!port.getOutgoingEdges().isEmpty()) {
processSplineOutputPort(port);
}
}
} else if (node.getProperty(InternalProperties.ORIGIN) instanceof LEdge) {
// It's a self-loop
processSelfLoop(node);
} else {
// Check if all ports were created for the same origin port
boolean sameOriginPort;
if (node.getPorts().size() >= 2) {
// Iterate over the dummy's ports to find out whether the origin is always the same
sameOriginPort = true;
Iterator<LPort> portIterator = node.getPorts().iterator();
LPort currentPort = portIterator.next();
LPort previousPort = null;
while (portIterator.hasNext()) {
previousPort = currentPort;
currentPort = portIterator.next();
if (!previousPort.getProperty(InternalProperties.ORIGIN).equals(currentPort.getProperty(InternalProperties.ORIGIN))) {
// The two ports don't have the same origin
sameOriginPort = false;
break;
}
}
} else {
sameOriginPort = false;
}
// Iterate through the ports
for (LPort port : node.getPorts()) {
if (!port.getIncomingEdges().isEmpty()) {
processInputPort(port, sameOriginPort);
}
if (!port.getOutgoingEdges().isEmpty()) {
processOutputPort(port, sameOriginPort);
}
}
}
// Remove the node
node.setLayer(null);
}
}
monitor.done();
}
use of org.eclipse.elk.core.options.EdgeRouting in project elk by eclipse.
the class LGraphToCGraphTransformer method transformEdges.
private void transformEdges() {
EdgeRouting style = layeredGraph.getProperty(LayeredOptions.EDGE_ROUTING);
List<VerticalSegment> verticalSegments;
switch(style) {
case ORTHOGONAL:
verticalSegments = collectVerticalSegmentsOrthogonal();
break;
case SPLINES:
verticalSegments = collectVerticalSegmentsSplines();
break;
default:
throw new IllegalStateException("Compaction not supported for " + style + " edges.");
}
// merge them
mergeVerticalSegments(verticalSegments);
// create precomputed constraints
verticalSegmentsMap.keySet().forEach(vs -> {
CNode vsNode = verticalSegmentsMap.get(vs);
vs.constraints.forEach(other -> {
CNode otherNode = verticalSegmentsMap.get(other);
cGraph.predefinedHorizontalConstraints.add(Pair.of(vsNode, otherNode));
});
});
}
Aggregations