Search in sources :

Example 6 with SelfHyperLoop

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;
        }
    }
}
Also used : ArrayList(java.util.ArrayList) SelfLoopPort(org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopPort) PortSide(org.eclipse.elk.core.options.PortSide) SelfHyperLoop(org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop)

Example 7 with SelfHyperLoop

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);
    }
}
Also used : PortSide(org.eclipse.elk.core.options.PortSide) SelfHyperLoop(org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop)

Example 8 with SelfHyperLoop

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));
    }
}
Also used : List(java.util.List) Stream(java.util.stream.Stream) InternalProperties(org.eclipse.elk.alg.layered.options.InternalProperties) PortSide(org.eclipse.elk.core.options.PortSide) SelfLoopPort(org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopPort) Collectors(java.util.stream.Collectors) SelfHyperLoop(org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop) LayeredOptions(org.eclipse.elk.alg.layered.options.LayeredOptions) ArrayList(java.util.ArrayList) SelfLoopHolder(org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopHolder) SelfLoopPort(org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopPort) PortSide(org.eclipse.elk.core.options.PortSide) SelfHyperLoop(org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop)

Example 9 with SelfHyperLoop

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);
        }
    }
}
Also used : SelfLoopOrderingStrategy(org.eclipse.elk.alg.layered.options.SelfLoopOrderingStrategy) SelfHyperLoopLabels(org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoopLabels) PortSide(org.eclipse.elk.core.options.PortSide) SelfHyperLoop(org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop)

Example 10 with SelfHyperLoop

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);
    }
}
Also used : LPort(org.eclipse.elk.alg.layered.graph.LPort) SelfLoopPort(org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopPort) SelfHyperLoop(org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop)

Aggregations

SelfHyperLoop (org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop)18 PortSide (org.eclipse.elk.core.options.PortSide)10 LPort (org.eclipse.elk.alg.layered.graph.LPort)6 ArrayList (java.util.ArrayList)4 SelfHyperLoopLabels (org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoopLabels)4 SelfLoopPort (org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopPort)4 KVector (org.eclipse.elk.core.math.KVector)3 List (java.util.List)2 Collectors (java.util.stream.Collectors)2 SelfLoopHolder (org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopHolder)2 InternalProperties (org.eclipse.elk.alg.layered.options.InternalProperties)2 HyperEdgeSegment (org.eclipse.elk.alg.layered.p5edges.orthogonal.HyperEdgeSegment)2 Arrays (java.util.Arrays)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 LinkedList (java.util.LinkedList)1 Map (java.util.Map)1 Queue (java.util.Queue)1 Set (java.util.Set)1 Stream (java.util.stream.Stream)1