use of org.eclipse.elk.alg.layered.graph.LPort 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.graph.LPort in project elk by eclipse.
the class NetworkSimplexPlacer method markCrossingEdges.
/**
* Marks the crossings of edges between the two passed layers.
*/
private void markCrossingEdges(final Layer left, final Layer right) {
final List<LEdge> openEdges = Lists.newArrayList();
// add all edges in the order they occur in the left layer
for (LNode node : left) {
for (LPort port : node.getPortSideView(PortSide.EAST)) {
for (LEdge edge : port.getOutgoingEdges()) {
if (edge.isInLayerEdge() || edge.isSelfLoop() || edge.getTarget().getNode().getLayer() != right) {
continue;
}
openEdges.add(edge);
}
}
}
// close the edges one after another, recording edge crossings
for (LNode node : Lists.reverse(right.getNodes())) {
for (LPort port : node.getPortSideView(PortSide.WEST)) {
// don't reverse, bottom up is correct
for (LEdge edge : port.getIncomingEdges()) {
if (edge.isInLayerEdge() || edge.isSelfLoop() || edge.getSource().getNode().getLayer() != left) {
continue;
}
// start at the end
ListIterator<LEdge> openEdgesIt = openEdges.listIterator(openEdges.size());
LEdge last = openEdgesIt.previous();
while (last != edge && openEdgesIt.hasPrevious()) {
// mark both edges as being part of an edge crossing
crossing[last.id] = true;
crossing[edge.id] = true;
last = openEdgesIt.previous();
}
if (openEdgesIt.hasPrevious()) {
openEdgesIt.remove();
}
}
}
}
}
use of org.eclipse.elk.alg.layered.graph.LPort in project elk by eclipse.
the class NetworkSimplexPlacer method insertInLayerEdgeAuxiliaryEdges.
/**
* Insert {@link NEdge}s to keep edges connected to inverted ports short.
*/
private void insertInLayerEdgeAuxiliaryEdges() {
lGraph.getLayers().stream().flatMap(l -> l.getNodes().stream()).filter(n -> n.getType() == NodeType.NORMAL).flatMap(n -> StreamSupport.stream(n.getConnectedEdges().spliterator(), false)).filter(e -> e.isInLayerEdge()).forEach(inLayerEdge -> {
boolean srcIsDummy = inLayerEdge.getSource().getNode().getType() != NodeType.NORMAL;
LPort thePort = srcIsDummy ? inLayerEdge.getTarget() : inLayerEdge.getSource();
LNode dummyNode = inLayerEdge.getOther(thePort).getNode();
NNode portRep = portMap.get(thePort);
// head/tail doesn't matter since it's a dummy node
NNode dummyRep = nodeReps[dummyNode.id].head;
final NNode src, tgt;
if (thePort.getNode().getIndex() < dummyNode.getIndex()) {
// port --> dummy
src = portRep;
tgt = dummyRep;
} else {
// dummy --> port
src = dummyRep;
tgt = portRep;
}
NEdge.of().delta(0).weight(EDGE_WEIGHT_BASE).source(src).target(tgt).create();
});
}
use of org.eclipse.elk.alg.layered.graph.LPort in project elk by eclipse.
the class LinearSegmentsNodePlacer method calcDeflection.
/**
* Calculate the force acting on the given linear segment. The force is stored in the segment's
* deflection field.
*
* @param segment the linear segment whose force is to be calculated
* @param incoming whether incoming edges should be considered
* @param outgoing whether outgoing edges should be considered
* @param deflectionDampening factor by which deflections are dampened
*/
private void calcDeflection(final LinearSegment segment, final boolean incoming, final boolean outgoing, final double deflectionDampening) {
double segmentDeflection = 0;
int nodeWeightSum = 0;
for (LNode node : segment.nodes) {
double nodeDeflection = 0;
int edgeWeightSum = 0;
int inputPrio = incoming ? node.getProperty(INPUT_PRIO) : Integer.MIN_VALUE;
int outputPrio = outgoing ? node.getProperty(OUTPUT_PRIO) : Integer.MIN_VALUE;
int minPrio = Math.max(inputPrio, outputPrio);
// Calculate force for every port/edge
for (LPort port : node.getPorts()) {
double portpos = node.getPosition().y + port.getPosition().y + port.getAnchor().y;
if (outgoing) {
for (LEdge edge : port.getOutgoingEdges()) {
LPort otherPort = edge.getTarget();
LNode otherNode = otherPort.getNode();
if (segment != linearSegments[otherNode.id]) {
int otherPrio = Math.max(otherNode.getProperty(INPUT_PRIO), otherNode.getProperty(OUTPUT_PRIO));
int prio = edge.getProperty(LayeredOptions.PRIORITY_STRAIGHTNESS);
if (prio >= minPrio && prio >= otherPrio) {
nodeDeflection += otherNode.getPosition().y + otherPort.getPosition().y + otherPort.getAnchor().y - portpos;
edgeWeightSum++;
}
}
}
}
if (incoming) {
for (LEdge edge : port.getIncomingEdges()) {
LPort otherPort = edge.getSource();
LNode otherNode = otherPort.getNode();
if (segment != linearSegments[otherNode.id]) {
int otherPrio = Math.max(otherNode.getProperty(INPUT_PRIO), otherNode.getProperty(OUTPUT_PRIO));
int prio = edge.getProperty(LayeredOptions.PRIORITY_STRAIGHTNESS);
if (prio >= minPrio && prio >= otherPrio) {
nodeDeflection += otherNode.getPosition().y + otherPort.getPosition().y + otherPort.getAnchor().y - portpos;
edgeWeightSum++;
}
}
}
}
}
// Avoid division by zero
if (edgeWeightSum > 0) {
segmentDeflection += nodeDeflection / edgeWeightSum;
nodeWeightSum++;
}
}
if (nodeWeightSum > 0) {
segment.deflection = deflectionDampening * segmentDeflection / nodeWeightSum;
segment.weight = nodeWeightSum;
} else {
segment.deflection = 0;
segment.weight = 0;
}
}
use of org.eclipse.elk.alg.layered.graph.LPort in project elk by eclipse.
the class LinearSegmentsNodePlacer method fillSegment.
/**
* Put a node into the given linear segment and check for following parts of a long edge.
*
* @param node
* the node to put into the linear segment
* @param segment
* a linear segment
* @return {@code true} if the given node was not already part of another segment and was thus
* added to the given segment.
*/
private boolean fillSegment(final LNode node, final LinearSegment segment) {
NodeType nodeType = node.getType();
if (node.id >= 0) {
// The node is already part of another linear segment
return false;
} else {
// Add the node to the given linear segment
node.id = segment.id;
segment.nodes.add(node);
}
segment.nodeType = nodeType;
if (nodeType == NodeType.LONG_EDGE || nodeType == NodeType.NORTH_SOUTH_PORT) {
// to be considered here
for (LPort sourcePort : node.getPorts()) {
for (LPort targetPort : sourcePort.getSuccessorPorts()) {
LNode targetNode = targetPort.getNode();
NodeType targetNodeType = targetNode.getType();
if (node.getLayer() != targetNode.getLayer()) {
// current no bignode and next node is LONG_EDGE and NORTH_SOUTH_PORT
if (targetNodeType == NodeType.LONG_EDGE || targetNodeType == NodeType.NORTH_SOUTH_PORT) {
if (fillSegment(targetNode, segment)) {
// That's quite enough.
return true;
}
}
}
}
}
}
return true;
}
Aggregations