Skip to content

Commit 7366368

Browse files
committed
Layered: Fix too much space between leftmost node and routing area. #734
Signed-off-by: le-cds <[email protected]> (cherry picked from commit 8012eb5)
1 parent c6761fe commit 7366368

File tree

2 files changed

+118
-12
lines changed

2 files changed

+118
-12
lines changed

plugins/org.eclipse.elk.alg.layered/src/org/eclipse/elk/alg/layered/p5edges/OrthogonalEdgeRouter.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2010, 2015 Kiel University and others.
2+
* Copyright (c) 2010, 2020 Kiel University and others.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License 2.0 which is available at
@@ -50,10 +50,6 @@
5050
* <dt>Postcondition:</dt><dd>each node is assigned a horizontal coordinate;
5151
* the bend points of each edge are set; the width of the whole graph is set</dd>
5252
* </dl>
53-
*
54-
* @author msp
55-
* @author cds
56-
* @author jjc
5753
*/
5854
public final class OrthogonalEdgeRouter implements ILayoutPhase<LayeredPhases, LGraph> {
5955

@@ -262,18 +258,22 @@ public void process(final LGraph layeredGraph, final IElkProgressMonitor monitor
262258
PolylineEdgeRouter.PRED_EXTERNAL_WEST_OR_EAST_PORT);
263259

264260
if (slotsCount > 0) {
265-
// The space between each pair of edge segments, and between nodes and edges
266-
double increment =
267-
edgeNodeSpacing + (slotsCount - 1) * edgeEdgeSpacing;
261+
// Compute routing area's width
262+
double routingWidth = (slotsCount - 1) * edgeEdgeSpacing;
263+
264+
if (leftLayer != null) {
265+
routingWidth += edgeNodeSpacing;
266+
}
267+
268268
if (rightLayer != null) {
269-
increment += edgeNodeSpacing;
269+
routingWidth += edgeNodeSpacing;
270270
}
271271

272272
// If we are between two layers, make sure their minimal spacing is preserved
273-
if (increment < nodeNodeSpacing && !isLeftLayerExternal && !isRightLayerExternal) {
274-
increment = nodeNodeSpacing;
273+
if (routingWidth < nodeNodeSpacing && !isLeftLayerExternal && !isRightLayerExternal) {
274+
routingWidth = nodeNodeSpacing;
275275
}
276-
xpos += increment;
276+
xpos += routingWidth;
277277
} else if (!isLeftLayerExternal && !isRightLayerExternal) {
278278
// If all edges are straight, use the usual spacing
279279
xpos += nodeNodeSpacing;
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2020 Kiel University and others.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*******************************************************************************/
10+
package org.eclipse.elk.alg.layered.issues;
11+
12+
import static org.junit.Assert.assertEquals;
13+
14+
import java.util.DoubleSummaryStatistics;
15+
import java.util.List;
16+
17+
import org.eclipse.elk.alg.layered.intermediate.greedyswitch.TestGraphCreator;
18+
import org.eclipse.elk.alg.layered.options.LayeredOptions;
19+
import org.eclipse.elk.alg.test.framework.LayoutTestRunner;
20+
import org.eclipse.elk.alg.test.framework.annotations.Algorithm;
21+
import org.eclipse.elk.alg.test.framework.annotations.DefaultConfiguration;
22+
import org.eclipse.elk.alg.test.framework.annotations.GraphResourceProvider;
23+
import org.eclipse.elk.alg.test.framework.io.AbstractResourcePath;
24+
import org.eclipse.elk.alg.test.framework.io.FileNameFilter;
25+
import org.eclipse.elk.alg.test.framework.io.ModelResourcePath;
26+
import org.eclipse.elk.core.util.ElkUtil;
27+
import org.eclipse.elk.graph.ElkEdge;
28+
import org.eclipse.elk.graph.ElkNode;
29+
import org.eclipse.emf.common.util.EList;
30+
import org.junit.Test;
31+
import org.junit.runner.RunWith;
32+
33+
import com.google.common.collect.Lists;
34+
35+
@RunWith(LayoutTestRunner.class)
36+
@Algorithm(LayeredOptions.ALGORITHM_ID)
37+
public class Issue734Test extends TestGraphCreator {
38+
39+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
40+
// Sources
41+
42+
@GraphResourceProvider
43+
public List<AbstractResourcePath> testGraphs() {
44+
return Lists.newArrayList(
45+
new ModelResourcePath("tickets/layered/734_nodeEdgeSpacingFlat.elkt"),
46+
new ModelResourcePath("tickets/layered/734_nodeEdgeSpacingFlatMoreComplex.elkt"),
47+
new ModelResourcePath("tickets/layered/734_nodeEdgeSpacingHierarchical.elkt"));
48+
}
49+
50+
51+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
52+
// Tests
53+
54+
@Test
55+
public void testOrthogonalEdges(final ElkNode graph) {
56+
// Compute the area occupied by nodes on the top level
57+
CoordinateSpan nodeSpan = computeNodeCoordinateSpan(graph.getChildren());
58+
CoordinateSpan edgeSpan = computeEdgeCoordinateSpan(graph.getContainedEdges());
59+
60+
// If the edge is routed properly, the edge span should have the same distance to the node span on both
61+
// sides. In other words, their respective centres should be aligned
62+
double nodeSpanCenter = (nodeSpan.min + nodeSpan.max) / 2;
63+
double edgeSpanCenter = (edgeSpan.min + edgeSpan.max) / 2;
64+
65+
assertEquals(nodeSpanCenter, edgeSpanCenter, 0.5);
66+
}
67+
68+
private CoordinateSpan computeNodeCoordinateSpan(EList<ElkNode> nodes) {
69+
CoordinateSpan span = new CoordinateSpan();
70+
71+
span.min = nodes.stream()
72+
.mapToDouble(node -> node.getX())
73+
.min()
74+
.orElse(0);
75+
span.max = nodes.stream()
76+
.mapToDouble(node -> node.getX() + node.getWidth())
77+
.max()
78+
.orElse(0);
79+
80+
return span;
81+
}
82+
83+
private CoordinateSpan computeEdgeCoordinateSpan(EList<ElkEdge> containedEdges) {
84+
DoubleSummaryStatistics stats = containedEdges.stream()
85+
.flatMap(edge -> edge.getSections().stream())
86+
.map(section -> ElkUtil.createVectorChain(section))
87+
.flatMap(chain -> chain.stream())
88+
.mapToDouble(vec -> vec.x)
89+
.summaryStatistics();
90+
return new CoordinateSpan(stats.getMin(), stats.getMax());
91+
}
92+
93+
private static class CoordinateSpan {
94+
private double min = Double.POSITIVE_INFINITY;
95+
private double max = Double.NEGATIVE_INFINITY;
96+
97+
public CoordinateSpan() {
98+
}
99+
100+
public CoordinateSpan(double min, double max) {
101+
this.min = min;
102+
this.max = max;
103+
}
104+
}
105+
106+
}

0 commit comments

Comments
 (0)