use of org.eclipse.elk.alg.layered.options.NodeFlexibility in project elk by eclipse.
the class NetworkSimplexPlacer method applyPositions.
// ------------------------------------------------------------------------------------------------
// Apply Layout
// ------------------------------------------------------------------------------------------------
private void applyPositions() {
for (Layer l : lGraph) {
for (LNode lNode : l) {
// find the node's corners
NodeRep nodeRep = nodeReps[lNode.id];
double minY = nodeRep.head.layer;
double maxY = nodeRep.tail.layer;
// set new position and size
lNode.getPosition().y = minY;
double sizeDelta = (maxY - minY) - lNode.getSize().y;
boolean flexibleNode = isFlexibleNode(lNode);
NodeFlexibility nf = getNodeFlexibility(lNode);
// modify the size?
if (flexibleNode && nf.isFlexibleSizeWhereSpacePermits()) {
lNode.getSize().y += sizeDelta;
}
// reposition ports if allowed
if (flexibleNode && nf.isFlexiblePorts()) {
for (LPort p : lNode.getPorts()) {
if (PortSide.SIDES_EAST_WEST.contains(p.getSide())) {
NNode nNode = portMap.get(p);
p.getPosition().y = nNode.layer - minY;
}
}
// when the node got resized, the positions of labels and south ports have to be adjusted
for (LLabel label : lNode.getLabels()) {
adjustLabelPosition(lNode, label, sizeDelta);
}
if (nf.isFlexibleSizeWhereSpacePermits()) {
lNode.getPortSideView(PortSide.SOUTH).forEach(p -> p.getPosition().y += sizeDelta);
}
}
}
}
}
use of org.eclipse.elk.alg.layered.options.NodeFlexibility in project elk by eclipse.
the class NetworkSimplexPlacer method isFlexibleNode.
// ------------------------------------------------------------------------------------------------
// Flexible Ports
// ------------------------------------------------------------------------------------------------
/**
* A node is <em>flexible</em> if
* <ul>
* <li>its port constraints are <b>not</b> {@link PortConstraints#FIXED_POS}, and</li>
* <li>the node's height is large enough to give the ports
* on both sides (WEST and EAST) enough room to potentially alter their position.</li>
* </ul>
*
* The rationale for the latter case is the following:
* if the height of a node is not enough to accommodate all ports
* and we are not allowed to change the node's size,
* we simply use the port positions that have been computed by the {@link LabelAndNodeSizeProcessor}.
* The processor is able to handle this situation properly.
*
* @param lNode a node
* @return whether the node is regarded flexible.
*/
public static boolean isFlexibleNode(final LNode lNode) {
// dummies are not flexible!
if (lNode.getType() != NodeType.NORMAL) {
return false;
}
// at least two ports are required ...
if (lNode.getPorts().size() <= 1) {
return false;
}
// if ports may not be moved there's no use in enlarging the node
PortConstraints pc = lNode.getProperty(LayeredOptions.PORT_CONSTRAINTS);
if (pc.isPosFixed()) {
return false;
}
NodeFlexibility nf = getNodeFlexibility(lNode);
if (nf == NodeFlexibility.NONE) {
return false;
}
// all ports, reuse the existing port positions
if (!nf.isFlexibleSizeWhereSpacePermits()) {
// we are not allowed to increase the node's size
double portSpacing = Spacings.getIndividualOrDefault(lNode, LayeredOptions.SPACING_PORT_PORT);
ElkMargin additionalPortSpacing = lNode.getProperty(LayeredOptions.SPACING_PORTS_SURROUNDING);
if (additionalPortSpacing == null) {
additionalPortSpacing = new ElkMargin(portSpacing, portSpacing, portSpacing, portSpacing);
}
// check west side
List<LPort> westPorts = lNode.getPortSideView(PortSide.WEST);
double requiredWestHeight = additionalPortSpacing.top + additionalPortSpacing.bottom + (westPorts.size() - 1) * portSpacing;
if (requiredWestHeight > lNode.getSize().y) {
return false;
}
// check east side
List<LPort> eastPorts = lNode.getPortSideView(PortSide.EAST);
double requiredEastHeight = additionalPortSpacing.top + additionalPortSpacing.bottom + (eastPorts.size() - 1) * portSpacing;
if (requiredEastHeight > lNode.getSize().y) {
return false;
}
}
return true;
}
use of org.eclipse.elk.alg.layered.options.NodeFlexibility in project elk by eclipse.
the class NetworkSimplexPlacer method insertFlexibleWhereSpaceAuxiliaryEdges.
/**
* Inserts auxiliary edges for the case that {@link NodeFlexibility#NODE_SIZE_WHERE_SPACE_PERMITS} node exist.
*/
private void insertFlexibleWhereSpaceAuxiliaryEdges() {
int minLayer = nGraph.nodes.stream().map(n -> n.layer).min(Integer::compare).get();
int maxLayer = nGraph.nodes.stream().map(n -> n.layer).max(Integer::compare).get();
int usedLayers = maxLayer - minLayer;
NNode globalSource = NNode.of().create(nGraph);
NNode globalSink = NNode.of().create(nGraph);
// make sure the distance between source and sink is preserved
NEdge.of().weight(NODE_SIZE_WEIGHT_STATIC * 2).delta(usedLayers).source(globalSource).target(globalSink).create();
// fix the position of most non-flexible nodes and make sure the flexible nodes
// can only increase in size
Arrays.stream(nodeReps).filter(nr -> nr.origin.getType() == NodeType.NORMAL).filter(// allow leaves to move
nr -> nr.origin.getPorts().size() > 1).forEach(nr -> {
NEdge.of().weight(0).delta(nr.tail.layer - minLayer).source(globalSource).target(nr.tail).create();
NEdge.of().weight(0).delta(usedLayers - nr.head.layer).source(nr.head).target(globalSink).create();
});
}
use of org.eclipse.elk.alg.layered.options.NodeFlexibility in project elk by eclipse.
the class NetworkSimplexPlacer method transformFixedOrderNode.
/**
* @return the corners that were created for {@link LNode}.
*/
private NodeRep transformFixedOrderNode(final LNode lNode) {
// -----------------------------------
// corner creation
// -----------------------------------
NNode topLeft = NNode.of().origin(lNode).type("flexible-head").create(nGraph);
NNode bottomLeft = NNode.of().origin(lNode).type("flexible-tail").create(nGraph);
NodeRep corners = new NodeRep(lNode, true, topLeft, bottomLeft);
// -----------------------------------
// weight & minimum length
// -----------------------------------
// the LabelAndNodeSizeProcessor ensures that any node size constraint is satisfied,
// i.e. the node's size is at least the specified minimum size and, if desired,
// the node is resized according to owned ports and labels
// as such we can safely use the current height as minimum height
double minHeight = lNode.getSize().y;
NodeFlexibility nf = getNodeFlexibility(lNode);
double sizeWeight = NODE_SIZE_WEIGHT_STATIC;
if (nf.isFlexibleSize()) {
// we are allowed to enlarge to node
// nevertheless, a little weight is good, otherwise the node can become arbitrarily tall
// especially since the edges that connect the node's do not carry nay weight
sizeWeight = NODE_SIZE_WEIGHT_FLEXIBLE;
}
NEdge nodeSizeEdge = NEdge.of().weight(sizeWeight).delta((int) Math.ceil(minHeight)).source(topLeft).target(bottomLeft).create();
if (nf == NodeFlexibility.NODE_SIZE_WHERE_SPACE_PERMITS) {
flexibleWhereSpacePermitsEdges.add(nodeSizeEdge);
}
// -----------------------------------
// port transformation
// -----------------------------------
// convert the ports to NNodes, note that the list of westward ports
// must be reversed since their original order is from bottom to top
transformPorts(Lists.reverse(lNode.getPortSideView(PortSide.WEST)), corners);
transformPorts(lNode.getPortSideView(PortSide.EAST), corners);
// return the corners for further processing
return corners;
}
Aggregations