use of org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop in project elk by eclipse.
the class PortRestorer method processOneSideLoops.
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Self Loop Placement (One Side)
private void processOneSideLoops(final SelfLoopOrderingStrategy ordering) {
for (SelfHyperLoop slLoop : slLoopsByType.get(SelfLoopType.ONE_SIDE)) {
// Obtain the port side
PortSide side = slLoop.getSLPorts().get(0).getLPort().getSide();
// We want ports with more outgoing edges to be to the left of ports with more incoming edges, so we need
// a sorted list of ports
List<SelfLoopPort> sortedPorts = new ArrayList<>(slLoop.getSLPorts());
sortedPorts.sort((slPort1, slPort2) -> Integer.compare(slPort1.getSLNetFlow(), slPort2.getSLNetFlow()));
switch(ordering) {
case SEQUENCED:
// Simply add all ports according to our list
addToTargetArea(sortedPorts, side, PortSideArea.MIDDLE, AddMode.APPEND);
break;
case STACKED:
// Compute which ports we want to have in the first group and which in the second group
int splitIndex = computePortListSplitIndex(sortedPorts);
// Prepend the first group to the middle list, and append the second group to that same list
addToTargetArea(sortedPorts.subList(0, splitIndex), side, PortSideArea.MIDDLE, AddMode.PREPEND);
addToTargetArea(sortedPorts.subList(splitIndex, sortedPorts.size()), side, PortSideArea.MIDDLE, AddMode.APPEND);
break;
default:
assert false;
}
}
}
use of org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop in project elk by eclipse.
the class PortRestorer method processThreeSideLoops.
private void processThreeSideLoops() {
for (SelfHyperLoop slLoop : slLoopsByType.get(SelfLoopType.THREE_SIDES)) {
// This array will yield the loop's start, middle, and end sides
PortSide[] sides = determineLoopConstellation(slLoop);
// Prepend to the start area, append to the other areas
addToTargetArea(slLoop, sides[0], PortSideArea.END, AddMode.PREPEND);
addToTargetArea(slLoop, sides[1], PortSideArea.MIDDLE, AddMode.APPEND);
addToTargetArea(slLoop, sides[2], PortSideArea.START, AddMode.APPEND);
}
}
use of org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop in project elk by eclipse.
the class PortSideAssigner method assignToNorthOrSouthSide.
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// North, South
/**
* Distributes all self loops to the northern or southern sides.
*/
private void assignToNorthOrSouthSide(final SelfLoopHolder slHolder) {
// Self loops can consist of more than two ports. Instead of simply assigning an equal number of self loops to
// both sides, we'd rather end up with a similar number of ports on both sides. This is what we're trying to
// to here. If one side falls behind, we fill that up with ports until the other falls behind. Beware: greedy
// algorithm ahead!
int northPorts = 0;
int southPorts = 0;
for (SelfHyperLoop slLoop : slHolder.getSLHyperLoops()) {
List<SelfLoopPort> slHiddenPorts = hiddenSelfLoopPortStream(slLoop).collect(Collectors.toList());
// Decide on a port side
PortSide newPortSide = null;
if (northPorts <= southPorts) {
newPortSide = PortSide.NORTH;
northPorts += slHiddenPorts.size();
} else if (southPorts < northPorts) {
newPortSide = PortSide.SOUTH;
southPorts += slHiddenPorts.size();
}
// Assign the ports
final PortSide finalNewPortSide = newPortSide;
slHiddenPorts.stream().map(slPort -> slPort.getLPort()).forEach(lPort -> lPort.setSide(finalNewPortSide));
}
}
use of org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop in project elk by eclipse.
the class LabelPlacer method assignSideAndAlignment.
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Side and Alignment
private void assignSideAndAlignment(final SelfLoopHolder slHolder) {
// Most loops are straightforward, but the one-sides northern and southern ones may not be. If the loops are
// stacked, we can simply center their labels. If they are sequenced, we want to go from the outer loops to the
// inner loops in pairs, and align their labels away from each other. To do so, we need to collect all of them
// first.
List<SelfHyperLoop> northernOneSidedSLLoops = null;
List<SelfHyperLoop> southernOneSidedSLLoops = null;
SelfLoopOrderingStrategy orderingStrategy = slHolder.getLNode().getProperty(LayeredOptions.EDGE_ROUTING_SELF_LOOP_ORDERING);
if (orderingStrategy == SelfLoopOrderingStrategy.SEQUENCED) {
northernOneSidedSLLoops = new ArrayList<>();
southernOneSidedSLLoops = new ArrayList<>();
}
// Assign sides and alignments; how this works differs for the different kinds of labels
for (SelfHyperLoop slLoop : slHolder.getSLHyperLoops()) {
// If this loop doesn't have any labels, don't bother
SelfHyperLoopLabels slLabels = slLoop.getSLLabels();
if (slLabels == null) {
continue;
}
assert !slLabels.getLLabels().isEmpty();
// How we place labels largely depends on the self loop type
switch(slLoop.getSelfLoopType()) {
case ONE_SIDE:
PortSide loopSide = slLoop.getOccupiedPortSides().iterator().next();
if (orderingStrategy == SelfLoopOrderingStrategy.SEQUENCED && (loopSide == PortSide.NORTH)) {
// Collect for deferred processing
northernOneSidedSLLoops.add(slLoop);
} else if (orderingStrategy == SelfLoopOrderingStrategy.SEQUENCED && (loopSide == PortSide.SOUTH)) {
// Collect for deferred processing
southernOneSidedSLLoops.add(slLoop);
} else {
assignOneSidedSimpleSideAndAlignment(slLoop, loopSide);
}
break;
case TWO_SIDES_CORNER:
assignTwoSidesCornerSideAndAlignment(slLoop);
break;
case TWO_SIDES_OPPOSING:
case THREE_SIDES:
assignTwoSidesOpposingAndThreeSidesSideAndAlignment(slLoop);
break;
case FOUR_SIDES:
assignFourSidesSideAndAlignment(slLoop);
break;
default:
assert false;
}
}
// Process deferred loops
if (northernOneSidedSLLoops != null) {
if (!northernOneSidedSLLoops.isEmpty()) {
assignOneSidedSequencedSideAndAlignment(northernOneSidedSLLoops, PortSide.NORTH);
}
if (!southernOneSidedSLLoops.isEmpty()) {
assignOneSidedSequencedSideAndAlignment(southernOneSidedSLLoops, PortSide.SOUTH);
}
}
}
use of org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop in project elk by eclipse.
the class LabelPlacer method assignOneSidedSequencedSideAndAlignment.
private void assignOneSidedSequencedSideAndAlignment(final List<SelfHyperLoop> slLoops, final PortSide portSide) {
assert !slLoops.isEmpty();
// Ensure sensible port IDs
int id = 0;
for (LPort lPort : slLoops.get(0).getSLHolder().getLNode().getPorts()) {
lPort.id = id++;
}
// port end up at list position 0
if (portSide == PortSide.NORTH) {
slLoops.sort((slLoop1, slLoop2) -> Integer.compare(slLoop1.getLeftmostPort().getLPort().id, slLoop2.getLeftmostPort().getLPort().id));
} else {
slLoops.sort((slLoop1, slLoop2) -> Integer.compare(slLoop2.getLeftmostPort().getLPort().id, slLoop1.getLeftmostPort().getLPort().id));
}
// Go from outside loops towards inside loops in pairs
int leftSlLoopIdx = 0;
int rightSlLoopIdx = slLoops.size() - 1;
while (leftSlLoopIdx < rightSlLoopIdx) {
SelfHyperLoop leftSlLoop = slLoops.get(leftSlLoopIdx);
SelfHyperLoop rightSlLoop = slLoops.get(rightSlLoopIdx);
// If the loop is on the northern side, the leftmost port actually is left of the rightmost port. It's
// flipped for the southern side
SelfLoopPort leftLoopAlignmentReference = portSide == PortSide.NORTH ? leftSlLoop.getRightmostPort() : leftSlLoop.getLeftmostPort();
SelfLoopPort rightLoopAlignmentReference = portSide == PortSide.NORTH ? rightSlLoop.getLeftmostPort() : rightSlLoop.getRightmostPort();
assignSideAndAlignment(leftSlLoop, portSide, Alignment.RIGHT, leftLoopAlignmentReference);
assignSideAndAlignment(rightSlLoop, portSide, Alignment.LEFT, rightLoopAlignmentReference);
leftSlLoopIdx++;
rightSlLoopIdx--;
}
// There might be a single loop in the middle
if (leftSlLoopIdx == rightSlLoopIdx) {
assignSideAndAlignment(slLoops.get(leftSlLoopIdx), portSide, Alignment.CENTER, null);
}
}
Aggregations