use of org.eclipse.elk.alg.layered.graph.LNode in project elk by eclipse.
the class HierarchicalPortOrthogonalEdgeRouter method correctSlantedEdgeSegments.
/**
* Goes over the eastern and western hierarchical dummy nodes in the given layer and checks
* whether their incident edges have slanted segments. Note that only the first and last
* segment needs to be checked.
*
* @param layer the layer.
*/
private void correctSlantedEdgeSegments(final Layer layer) {
for (LNode node : layer) {
if (node.getType() != NodeType.EXTERNAL_PORT) {
// We're only looking for hierarchical port dummies
continue;
}
PortSide extPortSide = node.getProperty(InternalProperties.EXT_PORT_SIDE);
if (extPortSide == PortSide.EAST || extPortSide == PortSide.WEST) {
for (LEdge edge : node.getConnectedEdges()) {
KVectorChain bendPoints = edge.getBendPoints();
if (bendPoints.isEmpty()) {
// TODO: The edge has no bend points yet, but may still be slanted. Handle that!
continue;
}
// Correct a slanted segment connected to the source port if it belongs to our node
LPort sourcePort = edge.getSource();
if (sourcePort.getNode() == node) {
KVector firstBendPoint = bendPoints.getFirst();
firstBendPoint.y = sourcePort.getAbsoluteAnchor().y;
}
// Correct a slanted segment connected to the target port if it belongs to our node
LPort targetPort = edge.getTarget();
if (targetPort.getNode() == node) {
KVector lastBendPoint = bendPoints.getLast();
lastBendPoint.y = targetPort.getAbsoluteAnchor().y;
}
}
}
}
}
use of org.eclipse.elk.alg.layered.graph.LNode in project elk by eclipse.
the class HierarchicalPortOrthogonalEdgeRouter method routeEdges.
// /////////////////////////////////////////////////////////////////////////////
// STEP 3: EDGE ROUTING
/**
* Routes nothern and southern hierarchical port edges and ajusts the graph's height and
* offsets accordingly.
*
* @param monitor the progress monitor we're using.
* @param layeredGraph the layered graph.
* @param northSouthDummies the collection of restored northern and southern port dummies.
*/
private void routeEdges(final IElkProgressMonitor monitor, final LGraph layeredGraph, final Iterable<LNode> northSouthDummies) {
// Prepare south and target layers for northern and southern routing
Set<LNode> northernSourceLayer = Sets.newLinkedHashSet();
Set<LNode> northernTargetLayer = Sets.newLinkedHashSet();
Set<LNode> southernSourceLayer = Sets.newLinkedHashSet();
Set<LNode> southernTargetLayer = Sets.newLinkedHashSet();
// Find some routing parameters
double nodeSpacing = layeredGraph.getProperty(LayeredOptions.SPACING_NODE_NODE).doubleValue();
double edgeSpacing = layeredGraph.getProperty(LayeredOptions.SPACING_EDGE_EDGE).doubleValue();
// connected to
for (LNode hierarchicalPortDummy : northSouthDummies) {
PortSide portSide = hierarchicalPortDummy.getProperty(InternalProperties.EXT_PORT_SIDE);
if (portSide == PortSide.NORTH) {
northernTargetLayer.add(hierarchicalPortDummy);
for (LEdge edge : hierarchicalPortDummy.getIncomingEdges()) {
northernSourceLayer.add(edge.getSource().getNode());
}
} else if (portSide == PortSide.SOUTH) {
southernTargetLayer.add(hierarchicalPortDummy);
for (LEdge edge : hierarchicalPortDummy.getIncomingEdges()) {
southernSourceLayer.add(edge.getSource().getNode());
}
}
}
// Northern routing
if (!northernSourceLayer.isEmpty()) {
// Route the edges using a south-to-north orthogonal edge router
OrthogonalRoutingGenerator routingGenerator = new OrthogonalRoutingGenerator(RoutingDirection.SOUTH_TO_NORTH, edgeSpacing, "extnorth");
int slots = routingGenerator.routeEdges(monitor, layeredGraph, northernSourceLayer, 0, northernTargetLayer, -nodeSpacing - layeredGraph.getOffset().y);
// If anything was routed, adjust the graph's offset and height
if (slots > 0) {
northernExtPortEdgeRoutingHeight = nodeSpacing + (slots - 1) * edgeSpacing;
layeredGraph.getOffset().y += northernExtPortEdgeRoutingHeight;
layeredGraph.getSize().y += northernExtPortEdgeRoutingHeight;
}
}
// Southern routing
if (!southernSourceLayer.isEmpty()) {
// Route the edges using a north-to-south orthogonal edge router
OrthogonalRoutingGenerator routingGenerator = new OrthogonalRoutingGenerator(RoutingDirection.NORTH_TO_SOUTH, edgeSpacing, "extsouth");
int slots = routingGenerator.routeEdges(monitor, layeredGraph, southernSourceLayer, 0, southernTargetLayer, layeredGraph.getSize().y + nodeSpacing - layeredGraph.getOffset().y);
// Adjust graph height.
if (slots > 0) {
layeredGraph.getSize().y += nodeSpacing + (slots - 1) * edgeSpacing;
}
}
}
use of org.eclipse.elk.alg.layered.graph.LNode in project elk by eclipse.
the class HierarchicalPortOrthogonalEdgeRouter method setNorthSouthDummyCoordinates.
// /////////////////////////////////////////////////////////////////////////////
// STEP 2: SET NORTH / SOUTH DUMMY COORDINATES
/**
* Set coordinates for northern and southern external port dummy nodes.
*
* @param layeredGraph the layered graph.
* @param northSouthDummies dummy nodes whose position to set.
*/
private void setNorthSouthDummyCoordinates(final LGraph layeredGraph, final List<LNode> northSouthDummies) {
PortConstraints constraints = layeredGraph.getProperty(LayeredOptions.PORT_CONSTRAINTS);
KVector graphSize = layeredGraph.getSize();
LPadding graphPadding = layeredGraph.getPadding();
double graphWidth = graphSize.x + graphPadding.left + graphPadding.right;
double northY = 0 - graphPadding.top - layeredGraph.getOffset().y;
double southY = graphSize.y + graphPadding.top + graphPadding.bottom - layeredGraph.getOffset().y;
// Lists of northern and southern external port dummies
List<LNode> northernDummies = Lists.newArrayList();
List<LNode> southernDummies = Lists.newArrayList();
for (LNode dummy : northSouthDummies) {
// Set x coordinate
switch(constraints) {
case FREE:
case FIXED_SIDE:
case FIXED_ORDER:
calculateNorthSouthDummyPositions(dummy);
break;
case FIXED_RATIO:
applyNorthSouthDummyRatio(dummy, graphWidth);
dummy.borderToContentAreaCoordinates(true, false);
break;
case FIXED_POS:
applyNorthSouthDummyPosition(dummy);
dummy.borderToContentAreaCoordinates(true, false);
// Ensure that the graph is wide enough to hold the port
graphSize.x = Math.max(graphSize.x, dummy.getPosition().x + dummy.getSize().x / 2.0);
break;
}
// Set y coordinates and add the dummy to its respective list
switch(dummy.getProperty(InternalProperties.EXT_PORT_SIDE)) {
case NORTH:
dummy.getPosition().y = northY;
northernDummies.add((dummy));
break;
case SOUTH:
dummy.getPosition().y = southY;
southernDummies.add(dummy);
break;
}
}
// have been put on top of one another
switch(constraints) {
case FREE:
case FIXED_SIDE:
ensureUniquePositions(northernDummies, layeredGraph);
ensureUniquePositions(southernDummies, layeredGraph);
break;
case FIXED_ORDER:
restoreProperOrder(northernDummies, layeredGraph);
restoreProperOrder(southernDummies, layeredGraph);
break;
}
}
use of org.eclipse.elk.alg.layered.graph.LNode in project elk by eclipse.
the class HierarchicalPortOrthogonalEdgeRouter method fixCoordinates.
/**
* Fixes the coordinates of the nodes in the given layer.
*
* @param layer the layer.
* @param constraints external port constraints.
* @param graph the graph.
*/
private void fixCoordinates(final Layer layer, final PortConstraints constraints, final LGraph graph) {
// Get some geometric values from the graph
LPadding padding = graph.getPadding();
KVector offset = graph.getOffset();
KVector graphActualSize = graph.getActualSize();
double newActualGraphHeight = graphActualSize.y;
// of the graph, so we're setting y coordinates of NORTH and SOUTH dummies in a second iteration
for (LNode node : layer) {
if (node.getType() != NodeType.EXTERNAL_PORT) {
// We're only looking for hierarchical port dummies
continue;
}
PortSide extPortSide = node.getProperty(InternalProperties.EXT_PORT_SIDE);
KVector extPortSize = node.getProperty(InternalProperties.EXT_PORT_SIZE);
KVector nodePosition = node.getPosition();
// Set x coordinate
switch(extPortSide) {
case EAST:
nodePosition.x = graph.getSize().x + padding.right - offset.x;
break;
case WEST:
nodePosition.x = -offset.x - padding.left;
break;
}
// Set y coordinate
double requiredActualGraphHeight = 0.0;
switch(extPortSide) {
case EAST:
case WEST:
if (constraints == PortConstraints.FIXED_RATIO) {
double ratio = node.getProperty(InternalProperties.PORT_RATIO_OR_POSITION);
nodePosition.y = graphActualSize.y * ratio - node.getProperty(LayeredOptions.PORT_ANCHOR).y;
requiredActualGraphHeight = nodePosition.y + extPortSize.y;
node.borderToContentAreaCoordinates(false, true);
} else if (constraints == PortConstraints.FIXED_POS) {
nodePosition.y = node.getProperty(InternalProperties.PORT_RATIO_OR_POSITION) - node.getProperty(LayeredOptions.PORT_ANCHOR).y;
requiredActualGraphHeight = nodePosition.y + extPortSize.y;
node.borderToContentAreaCoordinates(false, true);
}
break;
}
newActualGraphHeight = Math.max(newActualGraphHeight, requiredActualGraphHeight);
}
// Make the graph larger, if necessary
graph.getSize().y += newActualGraphHeight - graphActualSize.y;
// Iterate over NORTH and SOUTH dummies now that the graph's height is fixed
for (LNode node : layer) {
if (node.getType() != NodeType.EXTERNAL_PORT) {
// We're only looking for hierarchical port dummies
continue;
}
PortSide extPortSide = node.getProperty(InternalProperties.EXT_PORT_SIDE);
KVector nodePosition = node.getPosition();
// Set y coordinate
switch(extPortSide) {
case NORTH:
nodePosition.y = -offset.y - padding.top;
break;
case SOUTH:
nodePosition.y = graph.getSize().y + padding.bottom - offset.y;
break;
}
}
}
use of org.eclipse.elk.alg.layered.graph.LNode in project elk by eclipse.
the class HierarchicalPortOrthogonalEdgeRouter method removeTemporaryNorthSouthDummies.
// /////////////////////////////////////////////////////////////////////////////
// STEP 4: REMOVE TEMPORARY DUMMIES
/**
* Removes the temporary hierarchical port dummies, reconnecting their incoming and outgoing
* edges to the original dummies and setting the appropriate bend points.
*
* @param layeredGraph the layered graph.
*/
private void removeTemporaryNorthSouthDummies(final LGraph layeredGraph) {
List<LNode> nodesToRemove = Lists.newArrayList();
// Iterate through all layers
for (Layer layer : layeredGraph) {
for (LNode node : layer) {
if (node.getType() != NodeType.EXTERNAL_PORT) {
// We're only looking for hierarchical port dummies
continue;
}
if (!node.hasProperty(InternalProperties.EXT_PORT_REPLACED_DUMMY)) {
// We're only looking for temporary north / south dummies
continue;
}
// There must be a port where all edges come in, another port where edges go out, and
// a port with an edge connecting node and origin (that one was added previously by
// this processor)
LPort nodeInPort = null;
LPort nodeOutPort = null;
LPort nodeOriginPort = null;
for (LPort port : node.getPorts()) {
switch(port.getSide()) {
case WEST:
nodeInPort = port;
break;
case EAST:
nodeOutPort = port;
break;
default:
nodeOriginPort = port;
}
}
// Find the edge connecting this dummy to the original external port dummy that we
// restored just a while ago
LEdge nodeToOriginEdge = nodeOriginPort.getOutgoingEdges().get(0);
// Compute bend points for incoming edges
KVectorChain incomingEdgeBendPoints = new KVectorChain(nodeToOriginEdge.getBendPoints());
KVector firstBendPoint = new KVector(nodeOriginPort.getPosition());
firstBendPoint.add(node.getPosition());
incomingEdgeBendPoints.add(0, firstBendPoint);
// Compute bend points for outgoing edges
KVectorChain outgoingEdgeBendPoints = KVectorChain.reverse(nodeToOriginEdge.getBendPoints());
KVector lastBendPoint = new KVector(nodeOriginPort.getPosition());
lastBendPoint.add(node.getPosition());
outgoingEdgeBendPoints.add(lastBendPoint);
// Retrieve the original hierarchical port dummy
LNode replacedDummy = (LNode) node.getProperty(InternalProperties.EXT_PORT_REPLACED_DUMMY);
LPort replacedDummyPort = replacedDummy.getPorts().get(0);
// Reroute all the input port's edges
LEdge[] edges = nodeInPort.getIncomingEdges().toArray(new LEdge[0]);
for (LEdge edge : edges) {
edge.setTarget(replacedDummyPort);
edge.getBendPoints().addAllAsCopies(edge.getBendPoints().size(), incomingEdgeBendPoints);
}
// Reroute all the output port's edges
edges = LGraphUtil.toEdgeArray(nodeOutPort.getOutgoingEdges());
for (LEdge edge : edges) {
edge.setSource(replacedDummyPort);
edge.getBendPoints().addAllAsCopies(0, outgoingEdgeBendPoints);
}
// Remove connection between node and original hierarchical port dummy
nodeToOriginEdge.setSource(null);
nodeToOriginEdge.setTarget(null);
// Remember the temporary node for removal
nodesToRemove.add(node);
}
}
// Remove nodes
for (LNode node : nodesToRemove) {
node.setLayer(null);
}
}
Aggregations