Search in sources :

Example 1 with Layer

use of org.eclipse.elk.alg.layered.graph.Layer in project elk by eclipse.

the class HierarchicalPortOrthogonalEdgeRouter method removeTemporaryNorthSouthDummies.

// /////////////////////////////////////////////////////////////////////////////
// STEP 4: REMOVE TEMPORARY DUMMIES
/**
 * Removes the temporary hierarchical port dummies, reconnecting their incoming and outgoing
 * edges to the original dummies and setting the appropriate bend points.
 *
 * @param layeredGraph the layered graph.
 */
private void removeTemporaryNorthSouthDummies(final LGraph layeredGraph) {
    List<LNode> nodesToRemove = Lists.newArrayList();
    // Iterate through all layers
    for (Layer layer : layeredGraph) {
        for (LNode node : layer) {
            if (node.getType() != NodeType.EXTERNAL_PORT) {
                // We're only looking for hierarchical port dummies
                continue;
            }
            if (!node.hasProperty(InternalProperties.EXT_PORT_REPLACED_DUMMY)) {
                // We're only looking for temporary north / south dummies
                continue;
            }
            // There must be a port where all edges come in, another port where edges go out, and
            // a port with an edge connecting node and origin (that one was added previously by
            // this processor)
            LPort nodeInPort = null;
            LPort nodeOutPort = null;
            LPort nodeOriginPort = null;
            for (LPort port : node.getPorts()) {
                switch(port.getSide()) {
                    case WEST:
                        nodeInPort = port;
                        break;
                    case EAST:
                        nodeOutPort = port;
                        break;
                    default:
                        nodeOriginPort = port;
                }
            }
            // Find the edge connecting this dummy to the original external port dummy that we
            // restored just a while ago
            LEdge nodeToOriginEdge = nodeOriginPort.getOutgoingEdges().get(0);
            // Compute bend points for incoming edges
            KVectorChain incomingEdgeBendPoints = new KVectorChain(nodeToOriginEdge.getBendPoints());
            KVector firstBendPoint = new KVector(nodeOriginPort.getPosition());
            firstBendPoint.add(node.getPosition());
            incomingEdgeBendPoints.add(0, firstBendPoint);
            // Compute bend points for outgoing edges
            KVectorChain outgoingEdgeBendPoints = KVectorChain.reverse(nodeToOriginEdge.getBendPoints());
            KVector lastBendPoint = new KVector(nodeOriginPort.getPosition());
            lastBendPoint.add(node.getPosition());
            outgoingEdgeBendPoints.add(lastBendPoint);
            // Retrieve the original hierarchical port dummy
            LNode replacedDummy = (LNode) node.getProperty(InternalProperties.EXT_PORT_REPLACED_DUMMY);
            LPort replacedDummyPort = replacedDummy.getPorts().get(0);
            // Reroute all the input port's edges
            LEdge[] edges = nodeInPort.getIncomingEdges().toArray(new LEdge[0]);
            for (LEdge edge : edges) {
                edge.setTarget(replacedDummyPort);
                edge.getBendPoints().addAllAsCopies(edge.getBendPoints().size(), incomingEdgeBendPoints);
            }
            // Reroute all the output port's edges
            edges = LGraphUtil.toEdgeArray(nodeOutPort.getOutgoingEdges());
            for (LEdge edge : edges) {
                edge.setSource(replacedDummyPort);
                edge.getBendPoints().addAllAsCopies(0, outgoingEdgeBendPoints);
            }
            // Remove connection between node and original hierarchical port dummy
            nodeToOriginEdge.setSource(null);
            nodeToOriginEdge.setTarget(null);
            // Remember the temporary node for removal
            nodesToRemove.add(node);
        }
    }
    // Remove nodes
    for (LNode node : nodesToRemove) {
        node.setLayer(null);
    }
}
Also used : LEdge(org.eclipse.elk.alg.layered.graph.LEdge) KVectorChain(org.eclipse.elk.core.math.KVectorChain) LPort(org.eclipse.elk.alg.layered.graph.LPort) LNode(org.eclipse.elk.alg.layered.graph.LNode) KVector(org.eclipse.elk.core.math.KVector) Layer(org.eclipse.elk.alg.layered.graph.Layer)

Example 2 with Layer

use of org.eclipse.elk.alg.layered.graph.Layer in project elk by eclipse.

the class HighDegreeNodeLayeringProcessor method process.

@Override
public void process(final LGraph graph, final IElkProgressMonitor progressMonitor) {
    this.layeredGraph = graph;
    // retrieve some properties
    degreeThreshold = graph.getProperty(LayeredOptions.HIGH_DEGREE_NODES_THRESHOLD);
    treeHeightThreshold = graph.getProperty(LayeredOptions.HIGH_DEGREE_NODES_TREE_HEIGHT);
    // translate 0 to 'arbitrary height'
    if (treeHeightThreshold == 0) {
        treeHeightThreshold = Integer.MAX_VALUE;
    }
    // now iterate through all layer
    final ListIterator<Layer> layerIt = graph.getLayers().listIterator();
    while (layerIt.hasNext()) {
        Layer lay = layerIt.next();
        // -----------------------------------------------------------------------
        // #1 find high degree nodes and find their incoming and outgoing trees
        // -----------------------------------------------------------------------
        List<Pair<LNode, HighDegreeNodeInformation>> highDegreeNodes = Lists.newArrayList();
        int incMax = -1;
        int outMax = -1;
        for (LNode n : lay.getNodes()) {
            if (isHighDegreeNode(n)) {
                HighDegreeNodeInformation hdni = calculateInformation(n);
                incMax = Math.max(incMax, hdni.incTreesMaxHeight);
                outMax = Math.max(outMax, hdni.outTreesMaxHeight);
                highDegreeNodes.add(Pair.of(n, hdni));
            }
        }
        // -----------------------------------------------------------------------
        // #2 insert layers before the current layer and move the trees
        // -----------------------------------------------------------------------
        List<Layer> preLayers = Lists.newArrayList();
        for (int i = 0; i < incMax; ++i) {
            preLayers.add(0, prependLayer(layerIt));
        }
        for (Pair<LNode, HighDegreeNodeInformation> highDegreeNode : highDegreeNodes) {
            List<LNode> incRoots = highDegreeNode.getSecond().incTreeRoots;
            if (incRoots == null) {
                continue;
            }
            for (LNode incRoot : incRoots) {
                moveTree(incRoot, INCOMING_EDGES, preLayers);
            }
        }
        // -----------------------------------------------------------------------
        // #2 insert layers after the current layer and move the trees
        // -----------------------------------------------------------------------
        List<Layer> afterLayers = Lists.newArrayList();
        for (int i = 0; i < outMax; ++i) {
            afterLayers.add(appendLayer(layerIt));
        }
        for (Pair<LNode, HighDegreeNodeInformation> highDegreeNode : highDegreeNodes) {
            List<LNode> outRoots = highDegreeNode.getSecond().outTreeRoots;
            if (outRoots == null) {
                continue;
            }
            for (LNode outRoot : outRoots) {
                moveTree(outRoot, OUTGOING_EDGES, afterLayers);
            }
        }
    }
    // -----------------------------------------------------------------------
    // #2 it can happen that layers became empty
    // after the previous processing, remove them
    // -----------------------------------------------------------------------
    ListIterator<Layer> layerIt2 = graph.getLayers().listIterator();
    while (layerIt2.hasNext()) {
        Layer l = layerIt2.next();
        if (l.getNodes().isEmpty()) {
            layerIt2.remove();
        }
    }
}
Also used : LNode(org.eclipse.elk.alg.layered.graph.LNode) Layer(org.eclipse.elk.alg.layered.graph.Layer) Pair(org.eclipse.elk.core.util.Pair)

Example 3 with Layer

use of org.eclipse.elk.alg.layered.graph.Layer in project elk by eclipse.

the class InvertedPortProcessor method process.

@Override
public void process(final LGraph layeredGraph, final IElkProgressMonitor monitor) {
    monitor.begin("Inverted port preprocessing", 1);
    // Retrieve the layers in the graph
    List<Layer> layers = layeredGraph.getLayers();
    // Iterate through the layers and for each layer create a list of dummy nodes
    // that were created, but not yet assigned to the layer (to avoid concurrent
    // modification exceptions)
    ListIterator<Layer> layerIterator = layers.listIterator();
    Layer currentLayer = null;
    List<LNode> unassignedNodes = Lists.newArrayList();
    while (layerIterator.hasNext()) {
        // Update previous and current layers
        Layer previousLayer = currentLayer;
        currentLayer = layerIterator.next();
        // If the previous layer had unassigned nodes, assign them now and clear the list
        for (LNode node : unassignedNodes) {
            node.setLayer(previousLayer);
        }
        unassignedNodes.clear();
        // Iterate through the layer's nodes
        for (LNode node : currentLayer) {
            // Skip dummy nodes
            if (node.getType() != NodeType.NORMAL) {
                continue;
            }
            // port side problem won't appear)
            if (!node.getProperty(LayeredOptions.PORT_CONSTRAINTS).isSideFixed()) {
                continue;
            }
            // Look for input ports on the right side
            for (LPort port : node.getPorts(PortType.INPUT, PortSide.EAST)) {
                // For every edge going into this port, insert dummy nodes (do this using
                // a copy of the current list of edges, since the edges are modified when
                // dummy nodes are created)
                List<LEdge> edges = port.getIncomingEdges();
                LEdge[] edgeArray = LGraphUtil.toEdgeArray(edges);
                for (LEdge edge : edgeArray) {
                    createEastPortSideDummies(layeredGraph, port, edge, unassignedNodes);
                }
            }
            // Look for ports on the left side connected to edges going to higher layers
            for (LPort port : node.getPorts(PortType.OUTPUT, PortSide.WEST)) {
                // For every edge going out of this port, insert dummy nodes (do this using
                // a copy of the current list of edges, since the edges are modified when
                // dummy nodes are created)
                List<LEdge> edges = port.getOutgoingEdges();
                LEdge[] edgeArray = LGraphUtil.toEdgeArray(edges);
                for (LEdge edge : edgeArray) {
                    createWestPortSideDummies(layeredGraph, port, edge, unassignedNodes);
                }
            }
        }
    }
    // There may be unassigned nodes left
    for (LNode node : unassignedNodes) {
        node.setLayer(currentLayer);
    }
    monitor.done();
}
Also used : LEdge(org.eclipse.elk.alg.layered.graph.LEdge) LPort(org.eclipse.elk.alg.layered.graph.LPort) LNode(org.eclipse.elk.alg.layered.graph.LNode) Layer(org.eclipse.elk.alg.layered.graph.Layer)

Example 4 with Layer

use of org.eclipse.elk.alg.layered.graph.Layer in project elk by eclipse.

the class LabelAndNodeSizeProcessor method process.

@Override
public void process(final LGraph layeredGraph, final IElkProgressMonitor monitor) {
    monitor.begin("Node and Port Label Placement and Node Sizing", 1);
    NodeDimensionCalculation.calculateLabelAndNodeSizes(LGraphAdapters.adapt(layeredGraph, true, true, node -> node.getType() == NodeType.NORMAL));
    // which is the reason why we haven't handed them to the label and node size processing code
    if (layeredGraph.getProperty(InternalProperties.GRAPH_PROPERTIES).contains(GraphProperties.EXTERNAL_PORTS)) {
        Set<PortLabelPlacement> portLabelPlacement = layeredGraph.getProperty(LayeredOptions.PORT_LABELS_PLACEMENT);
        boolean placeNextToPort = portLabelPlacement.contains(PortLabelPlacement.NEXT_TO_PORT_IF_POSSIBLE);
        boolean treatAsGroup = layeredGraph.getProperty(LayeredOptions.PORT_LABELS_TREAT_AS_GROUP);
        for (Layer layer : layeredGraph.getLayers()) {
            layer.getNodes().stream().filter(node -> node.getType() == NodeType.EXTERNAL_PORT).forEach(dummy -> placeExternalPortDummyLabels(dummy, portLabelPlacement, placeNextToPort, treatAsGroup));
        }
    }
    monitor.done();
}
Also used : NodeDimensionCalculation(org.eclipse.elk.alg.common.nodespacing.NodeDimensionCalculation) GraphProperties(org.eclipse.elk.alg.layered.options.GraphProperties) Layer(org.eclipse.elk.alg.layered.graph.Layer) LLabel(org.eclipse.elk.alg.layered.graph.LLabel) KVector(org.eclipse.elk.core.math.KVector) IElkProgressMonitor(org.eclipse.elk.core.util.IElkProgressMonitor) Set(java.util.Set) ILayoutProcessor(org.eclipse.elk.core.alg.ILayoutProcessor) PortLabelPlacement(org.eclipse.elk.core.options.PortLabelPlacement) LayeredOptions(org.eclipse.elk.alg.layered.options.LayeredOptions) ElkRectangle(org.eclipse.elk.core.math.ElkRectangle) InternalProperties(org.eclipse.elk.alg.layered.options.InternalProperties) LGraph(org.eclipse.elk.alg.layered.graph.LGraph) LPort(org.eclipse.elk.alg.layered.graph.LPort) LGraphAdapters(org.eclipse.elk.alg.layered.graph.LGraphAdapters) LNode(org.eclipse.elk.alg.layered.graph.LNode) NodeType(org.eclipse.elk.alg.layered.graph.LNode.NodeType) PortLabelPlacement(org.eclipse.elk.core.options.PortLabelPlacement) Layer(org.eclipse.elk.alg.layered.graph.Layer)

Example 5 with Layer

use of org.eclipse.elk.alg.layered.graph.Layer in project elk by eclipse.

the class LabelDummySwitcher method swapNodes.

/**
 * Swaps the two given label dummy with the given long edge dummy. The dummies are assumed to be part of the same
 * long edge. The label dummy's new layer's width in the {@link #layerWidths} array is enlarged if the label dummy
 * is wider than the layer currently is.
 */
private void swapNodes(final LNode labelDummy, final LNode longEdgeDummy) {
    // Find the layers and the positions inside the layers of the dummy nodes. We need the positions later since
    // we run after crossing minimization and have to keep the order of nodes the same. An alternative for this
    // method would be not to change the layers and connections of the two nodes but to switch all of their
    // properties instead, but we reckon that might actually be more work
    Layer layer1 = labelDummy.getLayer();
    Layer layer2 = longEdgeDummy.getLayer();
    int dummy1LayerPosition = layer1.getNodes().indexOf(labelDummy);
    int dummy2LayerPosition = layer2.getNodes().indexOf(longEdgeDummy);
    // Detect incoming and outgoing ports of the nodes (this of course assumes that there's just one of each kind,
    // which should be true for long edge and label dummy nodes)
    LPort inputPort1 = labelDummy.getPorts(PortType.INPUT).iterator().next();
    LPort outputPort1 = labelDummy.getPorts(PortType.OUTPUT).iterator().next();
    LPort inputPort2 = longEdgeDummy.getPorts(PortType.INPUT).iterator().next();
    LPort outputPort2 = longEdgeDummy.getPorts(PortType.OUTPUT).iterator().next();
    // Store incoming and outgoing edges
    LEdge[] incomingEdges1 = LGraphUtil.toEdgeArray(inputPort1.getIncomingEdges());
    LEdge[] outgoingEdges1 = LGraphUtil.toEdgeArray(outputPort1.getOutgoingEdges());
    LEdge[] incomingEdges2 = LGraphUtil.toEdgeArray(inputPort2.getIncomingEdges());
    LEdge[] outgoingEdges2 = LGraphUtil.toEdgeArray(outputPort2.getOutgoingEdges());
    // Put first dummy into second dummy's layer and reroute second dummy's edges to first dummy
    labelDummy.setLayer(dummy2LayerPosition, layer2);
    for (LEdge edge : incomingEdges2) {
        edge.setTarget(inputPort1);
    }
    for (LEdge edge : outgoingEdges2) {
        edge.setSource(outputPort1);
    }
    // Put second dummy into first dummy's layer and reroute first dummy's edges to second dummy
    longEdgeDummy.setLayer(dummy1LayerPosition, layer1);
    for (LEdge edge : incomingEdges1) {
        edge.setTarget(inputPort2);
    }
    for (LEdge edge : outgoingEdges1) {
        edge.setSource(outputPort2);
    }
}
Also used : LEdge(org.eclipse.elk.alg.layered.graph.LEdge) LPort(org.eclipse.elk.alg.layered.graph.LPort) Layer(org.eclipse.elk.alg.layered.graph.Layer)

Aggregations

Layer (org.eclipse.elk.alg.layered.graph.Layer)209 LNode (org.eclipse.elk.alg.layered.graph.LNode)185 LPort (org.eclipse.elk.alg.layered.graph.LPort)64 LEdge (org.eclipse.elk.alg.layered.graph.LEdge)40 LGraph (org.eclipse.elk.alg.layered.graph.LGraph)36 Test (org.junit.Test)25 TestAfterProcessor (org.eclipse.elk.alg.test.framework.annotations.TestAfterProcessor)13 KVector (org.eclipse.elk.core.math.KVector)12 List (java.util.List)9 NodeType (org.eclipse.elk.alg.layered.graph.LNode.NodeType)6 InternalProperties (org.eclipse.elk.alg.layered.options.InternalProperties)6 LLabel (org.eclipse.elk.alg.layered.graph.LLabel)5 LayeredOptions (org.eclipse.elk.alg.layered.options.LayeredOptions)5 IElkProgressMonitor (org.eclipse.elk.core.util.IElkProgressMonitor)5 BPInfo (org.eclipse.elk.alg.layered.intermediate.wrapping.BreakingPointInserter.BPInfo)4 GraphInfoHolder (org.eclipse.elk.alg.layered.p3order.GraphInfoHolder)4 ILayoutProcessor (org.eclipse.elk.core.alg.ILayoutProcessor)4 PortSide (org.eclipse.elk.core.options.PortSide)4 Pair (org.eclipse.elk.core.util.Pair)4 ArrayList (java.util.ArrayList)3