Search in sources :

Example 6 with LNode

use of org.eclipse.elk.alg.layered.graph.LNode 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 7 with LNode

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

the class InvertedPortProcessor method createEastPortSideDummies.

/**
 * Creates the necessary dummy nodes for an input port on the east side of a node, provided that
 * the edge connects two different nodes.
 *
 * @param layeredGraph
 *            the layered graph.
 * @param eastwardPort
 *            the offending port.
 * @param edge
 *            the edge connected to the port.
 * @param layerNodeList
 *            list of unassigned nodes belonging to the layer of the node the port belongs to.
 *            The new dummy node is added to this list and must be assigned to the layer later.
 */
private void createEastPortSideDummies(final LGraph layeredGraph, final LPort eastwardPort, final LEdge edge, final List<LNode> layerNodeList) {
    assert edge.getTarget() == eastwardPort;
    // Ignore self loops
    if (edge.getSource().getNode() == eastwardPort.getNode()) {
        return;
    }
    // Dummy node in the same layer
    LNode dummy = new LNode(layeredGraph);
    dummy.setType(NodeType.LONG_EDGE);
    dummy.setProperty(InternalProperties.ORIGIN, edge);
    dummy.setProperty(LayeredOptions.PORT_CONSTRAINTS, PortConstraints.FIXED_POS);
    layerNodeList.add(dummy);
    LPort dummyInput = new LPort();
    dummyInput.setNode(dummy);
    dummyInput.setSide(PortSide.WEST);
    LPort dummyOutput = new LPort();
    dummyOutput.setNode(dummy);
    dummyOutput.setSide(PortSide.EAST);
    // Reroute the original edge
    edge.setTarget(dummyInput);
    // Connect the dummy with the original port
    LEdge dummyEdge = new LEdge();
    dummyEdge.copyProperties(edge);
    dummyEdge.setProperty(LayeredOptions.JUNCTION_POINTS, null);
    dummyEdge.setSource(dummyOutput);
    dummyEdge.setTarget(eastwardPort);
    // Set LONG_EDGE_SOURCE and LONG_EDGE_TARGET properties on the LONG_EDGE dummy
    setLongEdgeSourceAndTarget(dummy, dummyInput, dummyOutput, eastwardPort);
    // Move head labels from the old edge over to the new one
    ListIterator<LLabel> labelIterator = edge.getLabels().listIterator();
    while (labelIterator.hasNext()) {
        LLabel label = labelIterator.next();
        EdgeLabelPlacement labelPlacement = label.getProperty(LayeredOptions.EDGE_LABELS_PLACEMENT);
        if (labelPlacement == EdgeLabelPlacement.HEAD) {
            // Remember which edge the label originally belonged to, unless it already knows
            if (!label.hasProperty(InternalProperties.END_LABEL_EDGE)) {
                label.setProperty(InternalProperties.END_LABEL_EDGE, edge);
            }
            labelIterator.remove();
            dummyEdge.getLabels().add(label);
        }
    }
}
Also used : LLabel(org.eclipse.elk.alg.layered.graph.LLabel) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) LPort(org.eclipse.elk.alg.layered.graph.LPort) LNode(org.eclipse.elk.alg.layered.graph.LNode) EdgeLabelPlacement(org.eclipse.elk.core.options.EdgeLabelPlacement)

Example 8 with LNode

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

the class InvertedPortProcessor method setLongEdgeSourceAndTarget.

/**
 * Properly sets the
 * {@link org.eclipse.elk.alg.layered.options.LayeredOptions#LONG_EDGE_SOURCE} and
 * {@link org.eclipse.elk.alg.layered.options.LayeredOptions#LONG_EDGE_TARGET} properties for
 * the given long edge dummy. This is required for the
 * {@link org.eclipse.elk.alg.layered.intermediate.HyperedgeDummyMerger} to work correctly.
 *
 * @param longEdgeDummy
 *            the long edge dummy whose properties to set.
 * @param dummyInputPort
 *            the dummy node's input port.
 * @param dummyOutputPort
 *            the dummy node's output port.
 * @param oddPort
 *            the odd port that prompted the dummy to be created.
 */
private void setLongEdgeSourceAndTarget(final LNode longEdgeDummy, final LPort dummyInputPort, final LPort dummyOutputPort, final LPort oddPort) {
    // There's exactly one edge connected to the input and output port
    LPort sourcePort = dummyInputPort.getIncomingEdges().get(0).getSource();
    LNode sourceNode = sourcePort.getNode();
    NodeType sourceNodeType = sourceNode.getType();
    LPort targetPort = dummyOutputPort.getOutgoingEdges().get(0).getTarget();
    LNode targetNode = targetPort.getNode();
    NodeType targetNodeType = targetNode.getType();
    // Set the LONG_EDGE_SOURCE property
    if (sourceNodeType == NodeType.LONG_EDGE) {
        // The source is a LONG_EDGE node; use its LONG_EDGE_SOURCE
        longEdgeDummy.setProperty(InternalProperties.LONG_EDGE_SOURCE, sourceNode.getProperty(InternalProperties.LONG_EDGE_SOURCE));
    } else {
        // The target is the original node; use it
        longEdgeDummy.setProperty(InternalProperties.LONG_EDGE_SOURCE, sourcePort);
    }
    // Set the LONG_EDGE_TARGET property
    if (targetNodeType == NodeType.LONG_EDGE) {
        // The target is a LONG_EDGE node; use its LONG_EDGE_TARGET
        longEdgeDummy.setProperty(InternalProperties.LONG_EDGE_TARGET, targetNode.getProperty(InternalProperties.LONG_EDGE_TARGET));
    } else {
        // The target is the original node; use it
        longEdgeDummy.setProperty(InternalProperties.LONG_EDGE_TARGET, targetPort);
    }
}
Also used : NodeType(org.eclipse.elk.alg.layered.graph.LNode.NodeType) LPort(org.eclipse.elk.alg.layered.graph.LPort) LNode(org.eclipse.elk.alg.layered.graph.LNode)

Example 9 with LNode

use of org.eclipse.elk.alg.layered.graph.LNode 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 10 with LNode

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

the class LabelDummyInserter method createLabelDummy.

/**
 * Creates a label dummy for the given edge.
 *
 * @param layeredGraph
 *            graph the dummy will later be placed in.
 * @param edge
 *            the edge the label dummy is created for.
 * @param thickness
 *            the edge's thickness.
 * @param representedLabels
 *            currently empty list of labels represented by the new label dummy. This is set on the edge as a
 *            property and will later be filled with the represented labels by the calling method.
 */
private LNode createLabelDummy(final LGraph layeredGraph, final LEdge edge, final double thickness, final List<LLabel> representedLabels) {
    LNode dummyNode = new LNode(layeredGraph);
    dummyNode.setType(NodeType.LABEL);
    dummyNode.setProperty(InternalProperties.ORIGIN, edge);
    dummyNode.setProperty(InternalProperties.REPRESENTED_LABELS, representedLabels);
    dummyNode.setProperty(LayeredOptions.PORT_CONSTRAINTS, PortConstraints.FIXED_POS);
    dummyNode.setProperty(InternalProperties.LONG_EDGE_SOURCE, edge.getSource());
    dummyNode.setProperty(InternalProperties.LONG_EDGE_TARGET, edge.getTarget());
    // Actually split the edge
    LongEdgeSplitter.splitEdge(edge, dummyNode);
    // Place ports at the edge's center
    double portPos = Math.floor(thickness / 2);
    for (LPort dummyPort : dummyNode.getPorts()) {
        dummyPort.getPosition().y = portPos;
    }
    return dummyNode;
}
Also used : LPort(org.eclipse.elk.alg.layered.graph.LPort) LNode(org.eclipse.elk.alg.layered.graph.LNode)

Aggregations

LNode (org.eclipse.elk.alg.layered.graph.LNode)471 LPort (org.eclipse.elk.alg.layered.graph.LPort)189 Layer (org.eclipse.elk.alg.layered.graph.Layer)185 LEdge (org.eclipse.elk.alg.layered.graph.LEdge)110 LGraph (org.eclipse.elk.alg.layered.graph.LGraph)91 Test (org.junit.Test)85 KVector (org.eclipse.elk.core.math.KVector)38 PortSide (org.eclipse.elk.core.options.PortSide)28 List (java.util.List)23 LLabel (org.eclipse.elk.alg.layered.graph.LLabel)22 GraphInfoHolder (org.eclipse.elk.alg.layered.p3order.GraphInfoHolder)16 TestAfterProcessor (org.eclipse.elk.alg.test.framework.annotations.TestAfterProcessor)16 KVectorChain (org.eclipse.elk.core.math.KVectorChain)15 NodeType (org.eclipse.elk.alg.layered.graph.LNode.NodeType)14 ArrayList (java.util.ArrayList)13 InternalProperties (org.eclipse.elk.alg.layered.options.InternalProperties)13 LayeredOptions (org.eclipse.elk.alg.layered.options.LayeredOptions)13 PortConstraints (org.eclipse.elk.core.options.PortConstraints)13 Set (java.util.Set)12 CrossingsCounter (org.eclipse.elk.alg.layered.p3order.counting.CrossingsCounter)10