Skip to content

Commit

Permalink
Layered: Fix too much space between leftmost node and routing area. #734
Browse files Browse the repository at this point in the history


Signed-off-by: le-cds <[email protected]>
(cherry picked from commit 8012eb5)
  • Loading branch information
le-cds committed Dec 19, 2020
1 parent c6761fe commit 7366368
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2010, 2015 Kiel University and others.
* Copyright (c) 2010, 2020 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
Expand Down Expand Up @@ -50,10 +50,6 @@
* <dt>Postcondition:</dt><dd>each node is assigned a horizontal coordinate;
* the bend points of each edge are set; the width of the whole graph is set</dd>
* </dl>
*
* @author msp
* @author cds
* @author jjc
*/
public final class OrthogonalEdgeRouter implements ILayoutPhase<LayeredPhases, LGraph> {

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

if (slotsCount > 0) {
// The space between each pair of edge segments, and between nodes and edges
double increment =
edgeNodeSpacing + (slotsCount - 1) * edgeEdgeSpacing;
// Compute routing area's width
double routingWidth = (slotsCount - 1) * edgeEdgeSpacing;

if (leftLayer != null) {
routingWidth += edgeNodeSpacing;
}

if (rightLayer != null) {
increment += edgeNodeSpacing;
routingWidth += edgeNodeSpacing;
}

// If we are between two layers, make sure their minimal spacing is preserved
if (increment < nodeNodeSpacing && !isLeftLayerExternal && !isRightLayerExternal) {
increment = nodeNodeSpacing;
if (routingWidth < nodeNodeSpacing && !isLeftLayerExternal && !isRightLayerExternal) {
routingWidth = nodeNodeSpacing;
}
xpos += increment;
xpos += routingWidth;
} else if (!isLeftLayerExternal && !isRightLayerExternal) {
// If all edges are straight, use the usual spacing
xpos += nodeNodeSpacing;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*******************************************************************************
* Copyright (c) 2020 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.alg.layered.issues;

import static org.junit.Assert.assertEquals;

import java.util.DoubleSummaryStatistics;
import java.util.List;

import org.eclipse.elk.alg.layered.intermediate.greedyswitch.TestGraphCreator;
import org.eclipse.elk.alg.layered.options.LayeredOptions;
import org.eclipse.elk.alg.test.framework.LayoutTestRunner;
import org.eclipse.elk.alg.test.framework.annotations.Algorithm;
import org.eclipse.elk.alg.test.framework.annotations.DefaultConfiguration;
import org.eclipse.elk.alg.test.framework.annotations.GraphResourceProvider;
import org.eclipse.elk.alg.test.framework.io.AbstractResourcePath;
import org.eclipse.elk.alg.test.framework.io.FileNameFilter;
import org.eclipse.elk.alg.test.framework.io.ModelResourcePath;
import org.eclipse.elk.core.util.ElkUtil;
import org.eclipse.elk.graph.ElkEdge;
import org.eclipse.elk.graph.ElkNode;
import org.eclipse.emf.common.util.EList;
import org.junit.Test;
import org.junit.runner.RunWith;

import com.google.common.collect.Lists;

@RunWith(LayoutTestRunner.class)
@Algorithm(LayeredOptions.ALGORITHM_ID)
public class Issue734Test extends TestGraphCreator {

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Sources

@GraphResourceProvider
public List<AbstractResourcePath> testGraphs() {
return Lists.newArrayList(
new ModelResourcePath("tickets/layered/734_nodeEdgeSpacingFlat.elkt"),
new ModelResourcePath("tickets/layered/734_nodeEdgeSpacingFlatMoreComplex.elkt"),
new ModelResourcePath("tickets/layered/734_nodeEdgeSpacingHierarchical.elkt"));
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Tests

@Test
public void testOrthogonalEdges(final ElkNode graph) {
// Compute the area occupied by nodes on the top level
CoordinateSpan nodeSpan = computeNodeCoordinateSpan(graph.getChildren());
CoordinateSpan edgeSpan = computeEdgeCoordinateSpan(graph.getContainedEdges());

// If the edge is routed properly, the edge span should have the same distance to the node span on both
// sides. In other words, their respective centres should be aligned
double nodeSpanCenter = (nodeSpan.min + nodeSpan.max) / 2;
double edgeSpanCenter = (edgeSpan.min + edgeSpan.max) / 2;

assertEquals(nodeSpanCenter, edgeSpanCenter, 0.5);
}

private CoordinateSpan computeNodeCoordinateSpan(EList<ElkNode> nodes) {
CoordinateSpan span = new CoordinateSpan();

span.min = nodes.stream()
.mapToDouble(node -> node.getX())
.min()
.orElse(0);
span.max = nodes.stream()
.mapToDouble(node -> node.getX() + node.getWidth())
.max()
.orElse(0);

return span;
}

private CoordinateSpan computeEdgeCoordinateSpan(EList<ElkEdge> containedEdges) {
DoubleSummaryStatistics stats = containedEdges.stream()
.flatMap(edge -> edge.getSections().stream())
.map(section -> ElkUtil.createVectorChain(section))
.flatMap(chain -> chain.stream())
.mapToDouble(vec -> vec.x)
.summaryStatistics();
return new CoordinateSpan(stats.getMin(), stats.getMax());
}

private static class CoordinateSpan {
private double min = Double.POSITIVE_INFINITY;
private double max = Double.NEGATIVE_INFINITY;

public CoordinateSpan() {
}

public CoordinateSpan(double min, double max) {
this.min = min;
this.max = max;
}
}

}

0 comments on commit 7366368

Please sign in to comment.