Search in sources :

Example 1 with NNode

use of org.eclipse.elk.alg.common.networksimplex.NNode in project elk by eclipse.

the class NetworkSimplexLayerer method initialize.

/**
 * Helper method for the network simplex layerer. It instantiates all necessary attributes for
 * the execution of the network simplex layerer and initializes them with their default values.
 * All edges in the connected component given by the input argument will be determined, as well
 * as the number of incoming and outgoing edges of each node ( {@code inDegree}, respectively
 * {@code outDegree}). All sinks and source nodes in the connected component identified in this
 * step will be added to {@code sinks}, respectively {@code sources}.
 *
 * @param theNodes
 *            a {@code Collection} containing all nodes of the graph
 */
private NGraph initialize(final List<LNode> theNodes) {
    final Map<LNode, NNode> nodeMap = Maps.newHashMap();
    // transform nodes
    NGraph graph = new NGraph();
    for (LNode lNode : theNodes) {
        NNode nNode = NNode.of().origin(lNode).create(graph);
        nodeMap.put(lNode, nNode);
    }
    // transform edges
    for (LNode lNode : theNodes) {
        for (LEdge lEdge : lNode.getOutgoingEdges()) {
            // ignore self-loops
            if (lEdge.isSelfLoop()) {
                continue;
            }
            NEdge.of(lEdge).weight(1 * Math.max(1, lEdge.getProperty(LayeredOptions.PRIORITY_SHORTNESS))).delta(1).source(nodeMap.get(lEdge.getSource().getNode())).target(nodeMap.get(lEdge.getTarget().getNode())).create();
        }
    }
    return graph;
}
Also used : NNode(org.eclipse.elk.alg.common.networksimplex.NNode) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) NGraph(org.eclipse.elk.alg.common.networksimplex.NGraph) LNode(org.eclipse.elk.alg.layered.graph.LNode)

Example 2 with NNode

use of org.eclipse.elk.alg.common.networksimplex.NNode in project elk by eclipse.

the class NetworkSimplexLayerer method process.

/**
 * The main method of the network simplex layerer. It determines an optimal layering of all
 * nodes in the graph concerning a minimal length of all edges by using the network simplex
 * algorithm described in {@literal Emden R. Gansner, Eleftherios Koutsofios, Stephen
 * C. North, Kiem-Phong Vo: "A Technique for Drawing Directed Graphs", AT&T Bell Laboratories.
 * Note that the execution time of this implemented algorithm has not been proven quadratic yet.
 *
 * @param theLayeredGraph
 *            a layered graph which initially only contains layerless nodes and is
 *            then filled with layers
 * @param monitor
 *            the progress monitor
 */
public void process(final LGraph theLayeredGraph, final IElkProgressMonitor monitor) {
    monitor.begin("Network simplex layering", 1);
    layeredGraph = theLayeredGraph;
    int thoroughness = theLayeredGraph.getProperty(LayeredOptions.THOROUGHNESS) * ITER_LIMIT_FACTOR;
    List<LNode> theNodes = layeredGraph.getLayerlessNodes();
    if (theNodes.size() < 1) {
        monitor.done();
        return;
    }
    // layer graph, each connected component separately
    List<List<LNode>> connectedComponents = connectedComponents(theNodes);
    int[] previousLayeringNodeCounts = null;
    for (List<LNode> connComp : connectedComponents) {
        // determine a limit on the number of iterations
        int iterLimit = thoroughness * (int) Math.sqrt(connComp.size());
        NGraph graph = initialize(connComp);
        // execute the network simplex algorithm on the (sub-)graph
        NetworkSimplex.forGraph(graph).withIterationLimit(iterLimit).withPreviousLayering(previousLayeringNodeCounts).withBalancing(true).execute(monitor.subTask(1));
        // the layers are store in the NNode's layer field.
        List<Layer> layers = layeredGraph.getLayers();
        for (NNode nNode : graph.nodes) {
            // add additional layers to match required number
            while (layers.size() <= nNode.layer) {
                layers.add(layers.size(), new Layer(layeredGraph));
            }
            LNode lNode = (LNode) nNode.origin;
            lNode.setLayer(layers.get(nNode.layer));
        }
        if (connectedComponents.size() > 1) {
            previousLayeringNodeCounts = new int[layeredGraph.getLayers().size()];
            int layerIdx = 0;
            for (Layer l : layeredGraph) {
                previousLayeringNodeCounts[layerIdx++] = l.getNodes().size();
            }
        }
    }
    // empty the list of unlayered nodes
    theNodes.clear();
    // release the created resources
    dispose();
    monitor.done();
}
Also used : NNode(org.eclipse.elk.alg.common.networksimplex.NNode) NGraph(org.eclipse.elk.alg.common.networksimplex.NGraph) LNode(org.eclipse.elk.alg.layered.graph.LNode) List(java.util.List) LinkedList(java.util.LinkedList) Layer(org.eclipse.elk.alg.layered.graph.Layer)

Example 3 with NNode

use of org.eclipse.elk.alg.common.networksimplex.NNode in project elk by eclipse.

the class NetworkSimplexPlacer method applyPositions.

// ------------------------------------------------------------------------------------------------
// Apply Layout
// ------------------------------------------------------------------------------------------------
private void applyPositions() {
    for (Layer l : lGraph) {
        for (LNode lNode : l) {
            // find the node's corners
            NodeRep nodeRep = nodeReps[lNode.id];
            double minY = nodeRep.head.layer;
            double maxY = nodeRep.tail.layer;
            // set new position and size
            lNode.getPosition().y = minY;
            double sizeDelta = (maxY - minY) - lNode.getSize().y;
            boolean flexibleNode = isFlexibleNode(lNode);
            NodeFlexibility nf = getNodeFlexibility(lNode);
            // modify the size?
            if (flexibleNode && nf.isFlexibleSizeWhereSpacePermits()) {
                lNode.getSize().y += sizeDelta;
            }
            // reposition ports if allowed
            if (flexibleNode && nf.isFlexiblePorts()) {
                for (LPort p : lNode.getPorts()) {
                    if (PortSide.SIDES_EAST_WEST.contains(p.getSide())) {
                        NNode nNode = portMap.get(p);
                        p.getPosition().y = nNode.layer - minY;
                    }
                }
                // when the node got resized, the positions of labels and south ports have to be adjusted
                for (LLabel label : lNode.getLabels()) {
                    adjustLabelPosition(lNode, label, sizeDelta);
                }
                if (nf.isFlexibleSizeWhereSpacePermits()) {
                    lNode.getPortSideView(PortSide.SOUTH).forEach(p -> p.getPosition().y += sizeDelta);
                }
            }
        }
    }
}
Also used : NNode(org.eclipse.elk.alg.common.networksimplex.NNode) LLabel(org.eclipse.elk.alg.layered.graph.LLabel) LPort(org.eclipse.elk.alg.layered.graph.LPort) NodeFlexibility.getNodeFlexibility(org.eclipse.elk.alg.layered.options.NodeFlexibility.getNodeFlexibility) NodeFlexibility(org.eclipse.elk.alg.layered.options.NodeFlexibility) LNode(org.eclipse.elk.alg.layered.graph.LNode) Layer(org.eclipse.elk.alg.layered.graph.Layer)

Example 4 with NNode

use of org.eclipse.elk.alg.common.networksimplex.NNode in project elk by eclipse.

the class NetworkSimplexPlacer method insertInLayerEdgeAuxiliaryEdges.

/**
 * Insert {@link NEdge}s to keep edges connected to inverted ports short.
 */
private void insertInLayerEdgeAuxiliaryEdges() {
    lGraph.getLayers().stream().flatMap(l -> l.getNodes().stream()).filter(n -> n.getType() == NodeType.NORMAL).flatMap(n -> StreamSupport.stream(n.getConnectedEdges().spliterator(), false)).filter(e -> e.isInLayerEdge()).forEach(inLayerEdge -> {
        boolean srcIsDummy = inLayerEdge.getSource().getNode().getType() != NodeType.NORMAL;
        LPort thePort = srcIsDummy ? inLayerEdge.getTarget() : inLayerEdge.getSource();
        LNode dummyNode = inLayerEdge.getOther(thePort).getNode();
        NNode portRep = portMap.get(thePort);
        // head/tail doesn't matter since it's a dummy node
        NNode dummyRep = nodeReps[dummyNode.id].head;
        final NNode src, tgt;
        if (thePort.getNode().getIndex() < dummyNode.getIndex()) {
            // port --> dummy
            src = portRep;
            tgt = dummyRep;
        } else {
            // dummy --> port
            src = dummyRep;
            tgt = portRep;
        }
        NEdge.of().delta(0).weight(EDGE_WEIGHT_BASE).source(src).target(tgt).create();
    });
}
Also used : Arrays(java.util.Arrays) ElkMargin(org.eclipse.elk.core.math.ElkMargin) Iterables(com.google.common.collect.Iterables) GraphProperties(org.eclipse.elk.alg.layered.options.GraphProperties) Layer(org.eclipse.elk.alg.layered.graph.Layer) ListIterator(java.util.ListIterator) LLabel(org.eclipse.elk.alg.layered.graph.LLabel) NorthSouthPortPreprocessor(org.eclipse.elk.alg.layered.intermediate.NorthSouthPortPreprocessor) PortSide(org.eclipse.elk.core.options.PortSide) IElkProgressMonitor(org.eclipse.elk.core.util.IElkProgressMonitor) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) NGraph(org.eclipse.elk.alg.common.networksimplex.NGraph) Stack(java.util.Stack) LayeredOptions(org.eclipse.elk.alg.layered.options.LayeredOptions) ArrayList(java.util.ArrayList) Spacings(org.eclipse.elk.alg.layered.options.Spacings) IntermediateProcessorStrategy(org.eclipse.elk.alg.layered.intermediate.IntermediateProcessorStrategy) Lists(com.google.common.collect.Lists) InternalProperties(org.eclipse.elk.alg.layered.options.InternalProperties) Map(java.util.Map) NodeFlexibility.getNodeFlexibility(org.eclipse.elk.alg.layered.options.NodeFlexibility.getNodeFlexibility) StreamSupport(java.util.stream.StreamSupport) NetworkSimplex(org.eclipse.elk.alg.common.networksimplex.NetworkSimplex) NodeType(org.eclipse.elk.alg.layered.graph.LNode.NodeType) LayoutProcessorConfiguration(org.eclipse.elk.core.alg.LayoutProcessorConfiguration) NNode(org.eclipse.elk.alg.common.networksimplex.NNode) DoubleMath(com.google.common.math.DoubleMath) NodeFlexibility(org.eclipse.elk.alg.layered.options.NodeFlexibility) Iterator(java.util.Iterator) PortConstraints(org.eclipse.elk.core.options.PortConstraints) Predicate(java.util.function.Predicate) NEdge(org.eclipse.elk.alg.common.networksimplex.NEdge) Set(java.util.Set) ILayoutPhase(org.eclipse.elk.core.alg.ILayoutPhase) Maps(com.google.common.collect.Maps) Sets(com.google.common.collect.Sets) LGraphElement(org.eclipse.elk.alg.layered.graph.LGraphElement) List(java.util.List) LGraph(org.eclipse.elk.alg.layered.graph.LGraph) NodeLabelPlacement(org.eclipse.elk.core.options.NodeLabelPlacement) LayeredPhases(org.eclipse.elk.alg.layered.LayeredPhases) LabelAndNodeSizeProcessor(org.eclipse.elk.alg.layered.intermediate.LabelAndNodeSizeProcessor) LPort(org.eclipse.elk.alg.layered.graph.LPort) LNode(org.eclipse.elk.alg.layered.graph.LNode) Queue(java.util.Queue) NNode(org.eclipse.elk.alg.common.networksimplex.NNode) LPort(org.eclipse.elk.alg.layered.graph.LPort) LNode(org.eclipse.elk.alg.layered.graph.LNode)

Example 5 with NNode

use of org.eclipse.elk.alg.common.networksimplex.NNode in project elk by eclipse.

the class NetworkSimplexPlacer method transformEdge.

private void transformEdge(final LEdge lEdge) {
    // a dummy node
    NNode dummy = NNode.of().type("edge").create(nGraph);
    // calculate port offsets
    NodeRep srcRep = nodeReps[lEdge.getSource().getNode().id];
    NodeRep tgtRep = nodeReps[lEdge.getTarget().getNode().id];
    LPort srcPort = lEdge.getSource();
    LPort tgtPort = lEdge.getTarget();
    double srcOffset = srcPort.getAnchor().y;
    double tgtOffset = tgtPort.getAnchor().y;
    // for non-flexible nodes, ports are relative to node positions
    if (!srcRep.isFlexible) {
        srcOffset += srcPort.getPosition().y;
    }
    if (!tgtRep.isFlexible) {
        tgtOffset += tgtPort.getPosition().y;
    }
    assert DoubleMath.fuzzyEquals(srcOffset - tgtOffset, Math.round(srcOffset - tgtOffset), EPSILON) : "Port positions must be integral";
    int tgtDelta = (int) Math.max(0, srcOffset - tgtOffset);
    int srcDelta = (int) Math.max(0, tgtOffset - srcOffset);
    double weight = getEdgeWeight(lEdge);
    // an edge to the source
    NEdge left = NEdge.of(lEdge).weight(weight).delta(srcDelta).source(dummy).target(portMap.get(lEdge.getSource())).create();
    // an edge to the target
    NEdge right = NEdge.of(lEdge).weight(weight).delta(tgtDelta).source(dummy).target(portMap.get(lEdge.getTarget())).create();
    // remember
    EdgeRep edgeRep = new EdgeRep(lEdge, dummy, left, right);
    edgeReps[lEdge.id] = edgeRep;
}
Also used : NNode(org.eclipse.elk.alg.common.networksimplex.NNode) NEdge(org.eclipse.elk.alg.common.networksimplex.NEdge) LPort(org.eclipse.elk.alg.layered.graph.LPort)

Aggregations

NNode (org.eclipse.elk.alg.common.networksimplex.NNode)12 LNode (org.eclipse.elk.alg.layered.graph.LNode)8 LPort (org.eclipse.elk.alg.layered.graph.LPort)8 NGraph (org.eclipse.elk.alg.common.networksimplex.NGraph)6 NEdge (org.eclipse.elk.alg.common.networksimplex.NEdge)5 LEdge (org.eclipse.elk.alg.layered.graph.LEdge)5 Layer (org.eclipse.elk.alg.layered.graph.Layer)5 NodeFlexibility (org.eclipse.elk.alg.layered.options.NodeFlexibility)5 NodeFlexibility.getNodeFlexibility (org.eclipse.elk.alg.layered.options.NodeFlexibility.getNodeFlexibility)5 List (java.util.List)4 LLabel (org.eclipse.elk.alg.layered.graph.LLabel)4 Iterables (com.google.common.collect.Iterables)3 Lists (com.google.common.collect.Lists)3 Maps (com.google.common.collect.Maps)3 Sets (com.google.common.collect.Sets)3 DoubleMath (com.google.common.math.DoubleMath)3 ArrayList (java.util.ArrayList)3 Arrays (java.util.Arrays)3 Iterator (java.util.Iterator)3 ListIterator (java.util.ListIterator)3