Search in sources :

Example 1 with SelfLoopHolder

use of org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopHolder in project elk by eclipse.

the class SelfLoopPostProcessor method processNode.

private void processNode(final LNode lNode) {
    SelfLoopHolder slHolder = lNode.getProperty(InternalProperties.SELF_LOOP_HOLDER);
    slHolder.getSLHyperLoops().stream().flatMap(slLoop -> slLoop.getSLEdges().stream()).forEach(slEdge -> restoreEdge(lNode, slEdge));
    slHolder.getSLHyperLoops().stream().filter(slLoop -> slLoop.getSLLabels() != null).forEach(slLoop -> slLoop.getSLLabels().applyPlacement(lNode.getPosition()));
}
Also used : SelfLoopHolder(org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopHolder) SelfLoopEdge(org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopEdge) InternalProperties(org.eclipse.elk.alg.layered.options.InternalProperties) LGraph(org.eclipse.elk.alg.layered.graph.LGraph) IElkProgressMonitor(org.eclipse.elk.core.util.IElkProgressMonitor) LNode(org.eclipse.elk.alg.layered.graph.LNode) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) ILayoutProcessor(org.eclipse.elk.core.alg.ILayoutProcessor) NodeType(org.eclipse.elk.alg.layered.graph.LNode.NodeType) SelfLoopHolder(org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopHolder)

Example 2 with SelfLoopHolder

use of org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopHolder in project elk by eclipse.

the class SelfLoopPreProcessor method process.

@Override
public void process(final LGraph graph, final IElkProgressMonitor progressMonitor) {
    progressMonitor.begin("Self-Loop pre-processing", 1);
    for (LNode lnode : graph.getLayerlessNodes()) {
        if (SelfLoopHolder.needsSelfLoopProcessing(lnode)) {
            SelfLoopHolder slHolder = SelfLoopHolder.install(lnode);
            hideSelfLoops(slHolder);
            hidePorts(slHolder);
        }
    }
    progressMonitor.done();
}
Also used : SelfLoopHolder(org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopHolder) LNode(org.eclipse.elk.alg.layered.graph.LNode)

Example 3 with SelfLoopHolder

use of org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopHolder in project elk by eclipse.

the class RoutingDirector method determineFourSideLoopRoutes.

// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Route Determination (Four Sides)
/**
 * For four-sided self loops, we have at least one port on every side. If we look at the list of ports, this means
 * that we want to insert a break between some pair of ports adjacent in that list: one will become the leftmost
 * port, and the other will become the rightmost port. What we want to do is find the pair of ports with the maximum
 * number of ports with external connections between them, since that will minimize the number of edge crossings our
 * routing will produce.
 */
private void determineFourSideLoopRoutes(final SelfHyperLoop slLoop) {
    // The self loop ports are sorted by ID
    List<SelfLoopPort> sortedSLPorts = slLoop.getSLPorts();
    SelfLoopHolder slHolder = slLoop.getSLHolder();
    // Go through each pair of adjacent ports and find the one which incurs the highest penalty if we drew an edge
    // between them. That's the pair we want to split the loop at. We start with the uppermost port on the western
    // side and the leftmost on the northern side and then compare successive pairs against those two
    SelfLoopPort worstLeftPort = sortedSLPorts.get(sortedSLPorts.size() - 1);
    SelfLoopPort worstRightPort = sortedSLPorts.get(0);
    int worstPenalty = computeEdgePenalty(slHolder, worstLeftPort, worstRightPort);
    for (int rightPortIndex = 1; rightPortIndex < sortedSLPorts.size(); rightPortIndex++) {
        SelfLoopPort currLeftPort = sortedSLPorts.get(rightPortIndex - 1);
        SelfLoopPort currRightPort = sortedSLPorts.get(rightPortIndex);
        int currPenalty = computeEdgePenalty(slHolder, currLeftPort, currRightPort);
        if (currPenalty > worstPenalty) {
            worstLeftPort = currLeftPort;
            worstRightPort = currRightPort;
            worstPenalty = currPenalty;
        }
    }
    // Since we _don't_ want to draw the self loop between the left and right ports, we switch them here
    slLoop.setLeftmostPort(worstRightPort);
    slLoop.setRightmostPort(worstLeftPort);
}
Also used : SelfLoopHolder(org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopHolder) SelfLoopPort(org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopPort)

Example 4 with SelfLoopHolder

use of org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopHolder in project elk by eclipse.

the class RoutingSlotAssigner method shiftTowardsNodeOnSide.

private void shiftTowardsNodeOnSide(final SelfLoopHolder slHolder, final PortSide side, final int[] nextFreeRoutingSlotAtPort, final boolean[][] labelCrossingMatrix) {
    // We will iterate over the self loops that occupy that port side, sorted ascendingly by routing slot
    List<SelfHyperLoop> slLoops = slHolder.getSLHyperLoops().stream().filter(slLoop -> slLoop.getOccupiedPortSides().contains(side)).sorted((sl1, sl2) -> Integer.compare(sl1.getRoutingSlot(side), sl2.getRoutingSlot(side))).collect(Collectors.toList());
    // Find the indices of the first and last regular port on the port side
    int minLPortIndex = Integer.MAX_VALUE;
    int maxLPortIndex = Integer.MIN_VALUE;
    for (LPort lPort : slHolder.getLNode().getPorts()) {
        if (lPort.getSide() == side) {
            minLPortIndex = Math.min(minLPortIndex, lPort.id);
            maxLPortIndex = Math.max(maxLPortIndex, lPort.id);
        }
    }
    if (minLPortIndex == Integer.MAX_VALUE) {
        // won't cause label overlaps.
        for (int i = 0; i < slLoops.size(); i++) {
            slLoops.get(i).setRoutingSlot(side, i);
        }
    } else {
        int[] slotAssignedToLabel = new int[labelCrossingMatrix.length];
        Arrays.fill(slotAssignedToLabel, -1);
        // no label our loop label conflicts with is assigned to that slot
        for (SelfHyperLoop slLoop : slLoops) {
            boolean[] activeAtPort = slLoopActivityOverPorts.get(slLoop);
            int lowestAvailableSlot = 0;
            for (int portIndex = minLPortIndex; portIndex <= maxLPortIndex; portIndex++) {
                if (activeAtPort[portIndex]) {
                    lowestAvailableSlot = Math.max(lowestAvailableSlot, nextFreeRoutingSlotAtPort[portIndex]);
                }
            }
            // conflict-free slot
            if (slLoop.getSLLabels() != null) {
                int ourLabelIdx = slLoop.getSLLabels().id;
                Set<Integer> slotsWithLabelConflicts = new HashSet<>();
                for (int otherLabelIdx = 0; otherLabelIdx < labelCrossingMatrix.length; otherLabelIdx++) {
                    if (labelCrossingMatrix[ourLabelIdx][otherLabelIdx]) {
                        slotsWithLabelConflicts.add(slotAssignedToLabel[otherLabelIdx]);
                    }
                }
                // Find the first slot (starting with out lowest available) that does not appear in the set
                while (slotsWithLabelConflicts.contains(lowestAvailableSlot)) {
                    lowestAvailableSlot++;
                }
            }
            // Assign the loop to that routing slot and update out routing slot array
            slLoop.setRoutingSlot(side, lowestAvailableSlot);
            for (int portIndex = minLPortIndex; portIndex <= maxLPortIndex; portIndex++) {
                if (activeAtPort[portIndex]) {
                    nextFreeRoutingSlotAtPort[portIndex] = lowestAvailableSlot + 1;
                }
            }
            // If we have a label, update the label's routing slot
            if (slLoop.getSLLabels() != null) {
                slotAssignedToLabel[slLoop.getSLLabels().id] = lowestAvailableSlot;
            }
        }
    }
}
Also used : Arrays(java.util.Arrays) PortSide(org.eclipse.elk.core.options.PortSide) SelfLoopPort(org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopPort) Set(java.util.Set) HashMap(java.util.HashMap) Collectors(java.util.stream.Collectors) SelfHyperLoop(org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop) ArrayList(java.util.ArrayList) SelfLoopHolder(org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopHolder) HashSet(java.util.HashSet) HyperEdgeSegment(org.eclipse.elk.alg.layered.p5edges.orthogonal.HyperEdgeSegment) List(java.util.List) InternalProperties(org.eclipse.elk.alg.layered.options.InternalProperties) Map(java.util.Map) LPort(org.eclipse.elk.alg.layered.graph.LPort) OrthogonalRoutingGenerator(org.eclipse.elk.alg.layered.p5edges.orthogonal.OrthogonalRoutingGenerator) Queue(java.util.Queue) LinkedList(java.util.LinkedList) HyperEdgeSegmentDependency(org.eclipse.elk.alg.layered.p5edges.orthogonal.HyperEdgeSegmentDependency) SelfHyperLoopLabels(org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoopLabels) LPort(org.eclipse.elk.alg.layered.graph.LPort) SelfHyperLoop(org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop) HashSet(java.util.HashSet)

Example 5 with SelfLoopHolder

use of org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopHolder in project elk by eclipse.

the class PortRestorer method restorePorts.

// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Port Restoring
private void restorePorts(final SelfLoopHolder slHolder) {
    // We're building up a new port list and replace the old one once we're finished. That's more efficient than
    // continually inserting ports into the middle of the existing list.
    LNode lNode = slHolder.getLNode();
    // We'll add the old ports in bursts and always remember where the next burst starts
    List<LPort> oldPortList = new ArrayList<>(lNode.getPorts());
    int nextOldPortIndex = 0;
    List<LPort> newPortList = lNode.getPorts();
    newPortList.clear();
    // Go over the target areas and add them in between the regular ports
    addAll(targetAreas.get(PortSide.NORTH, PortSideArea.START), lNode);
    nextOldPortIndex = addAllThat(oldPortList, nextOldPortIndex, (lPort) -> lPort.getSide() == PortSide.NORTH && isNorthSouthPortWithWestOrWestEastConnections(lPort), newPortList);
    addAll(targetAreas.get(PortSide.NORTH, PortSideArea.MIDDLE), lNode);
    nextOldPortIndex = addAllThat(oldPortList, nextOldPortIndex, (lPort) -> lPort.getSide() == PortSide.NORTH, newPortList);
    addAll(targetAreas.get(PortSide.NORTH, PortSideArea.END), lNode);
    addAll(targetAreas.get(PortSide.EAST, PortSideArea.START), lNode);
    addAll(targetAreas.get(PortSide.EAST, PortSideArea.MIDDLE), lNode);
    nextOldPortIndex = addAllThat(oldPortList, nextOldPortIndex, (lPort) -> lPort.getSide() == PortSide.EAST, newPortList);
    addAll(targetAreas.get(PortSide.EAST, PortSideArea.END), lNode);
    addAll(targetAreas.get(PortSide.SOUTH, PortSideArea.START), lNode);
    nextOldPortIndex = addAllThat(oldPortList, nextOldPortIndex, (lPort) -> lPort.getSide() == PortSide.SOUTH && isNorthSouthPortWithEastConnections(lPort), newPortList);
    addAll(targetAreas.get(PortSide.SOUTH, PortSideArea.MIDDLE), lNode);
    nextOldPortIndex = addAllThat(oldPortList, nextOldPortIndex, (lPort) -> lPort.getSide() == PortSide.SOUTH, newPortList);
    addAll(targetAreas.get(PortSide.SOUTH, PortSideArea.END), lNode);
    addAll(targetAreas.get(PortSide.WEST, PortSideArea.START), lNode);
    nextOldPortIndex = addAllThat(oldPortList, nextOldPortIndex, (lPort) -> lPort.getSide() == PortSide.WEST, newPortList);
    addAll(targetAreas.get(PortSide.WEST, PortSideArea.MIDDLE), lNode);
    addAll(targetAreas.get(PortSide.WEST, PortSideArea.END), lNode);
    assert newPortList.size() >= oldPortList.size() && newPortList.size() >= slHolder.getSLPortMap().size();
    assert !slHolder.arePortsHidden() || newPortList.size() > oldPortList.size();
}
Also used : ArrayListMultimap(com.google.common.collect.ArrayListMultimap) Arrays(java.util.Arrays) PortSide(org.eclipse.elk.core.options.PortSide) ListMultimap(com.google.common.collect.ListMultimap) Predicate(java.util.function.Predicate) SelfLoopPort(org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopPort) Collection(java.util.Collection) IElkProgressMonitor(org.eclipse.elk.core.util.IElkProgressMonitor) Set(java.util.Set) Collectors(java.util.stream.Collectors) SelfLoopType(org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopType) 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) List(java.util.List) ArrayTable(com.google.common.collect.ArrayTable) InternalProperties(org.eclipse.elk.alg.layered.options.InternalProperties) SelfLoopOrderingStrategy(org.eclipse.elk.alg.layered.options.SelfLoopOrderingStrategy) LPort(org.eclipse.elk.alg.layered.graph.LPort) LNode(org.eclipse.elk.alg.layered.graph.LNode) Table(com.google.common.collect.Table) EnumSet(java.util.EnumSet) LPort(org.eclipse.elk.alg.layered.graph.LPort) ArrayList(java.util.ArrayList) LNode(org.eclipse.elk.alg.layered.graph.LNode)

Aggregations

SelfLoopHolder (org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopHolder)7 SelfLoopPort (org.eclipse.elk.alg.layered.intermediate.loops.SelfLoopPort)5 InternalProperties (org.eclipse.elk.alg.layered.options.InternalProperties)4 PortSide (org.eclipse.elk.core.options.PortSide)4 ArrayList (java.util.ArrayList)3 List (java.util.List)3 Collectors (java.util.stream.Collectors)3 LNode (org.eclipse.elk.alg.layered.graph.LNode)3 SelfHyperLoop (org.eclipse.elk.alg.layered.intermediate.loops.SelfHyperLoop)3 Arrays (java.util.Arrays)2 Set (java.util.Set)2 LPort (org.eclipse.elk.alg.layered.graph.LPort)2 LayeredOptions (org.eclipse.elk.alg.layered.options.LayeredOptions)2 IElkProgressMonitor (org.eclipse.elk.core.util.IElkProgressMonitor)2 ArrayListMultimap (com.google.common.collect.ArrayListMultimap)1 ArrayTable (com.google.common.collect.ArrayTable)1 ListMultimap (com.google.common.collect.ListMultimap)1 Table (com.google.common.collect.Table)1 Collection (java.util.Collection)1 EnumSet (java.util.EnumSet)1