Search in sources :

Example 1 with Pair

use of org.eclipse.elk.core.util.Pair 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 2 with Pair

use of org.eclipse.elk.core.util.Pair in project elk by eclipse.

the class ElkGraphImporter method updateGraph.

@Override
public void updateGraph(final Graph g) {
    Map<KVector, Pair<Node, ElkNode>> updatedNodeMap = Maps.newHashMap();
    // reset graph
    g.tEdges = null;
    g.tree = null;
    // update nodes
    for (Node n : g.vertices) {
        Pair<Node, ElkNode> original = nodeMap.get(n.originalVertex);
        n.originalVertex = n.rect.getCenter();
        updatedNodeMap.put(n.originalVertex, original);
    }
    nodeMap = updatedNodeMap;
}
Also used : ElkNode(org.eclipse.elk.graph.ElkNode) Node(org.eclipse.elk.alg.common.spore.Node) ElkNode(org.eclipse.elk.graph.ElkNode) KVector(org.eclipse.elk.core.math.KVector) Pair(org.eclipse.elk.core.util.Pair)

Example 3 with Pair

use of org.eclipse.elk.core.util.Pair in project elk by eclipse.

the class ElkLayered method hierarchicalLayout.

/**
 * Processors can be marked as operating on the full hierarchy by using the {@link IHierarchyAwareLayoutProcessor}
 * interface.
 *
 * All graphs are collected using a breadth-first search and this list is reversed, so that for each graph, all
 * following graphs are on the same hierarchy level or higher, i.e. closer to the parent graph. Each graph then has
 * a unique configuration of ELK Layered, which is comprised of a sequence of processors. The processors can vary
 * depending on the characteristics of each graph. The list of graphs and their algorithms is then traversed. If a
 * processor is not hierarchical it is simply executed. If it it is hierarchical and this graph is not the root
 * graph, this processor is skipped and the algorithm is paused until the processor has been executed on the root
 * graph. Then the algorithm is continued, starting with the level lowest in the hierarchy, i.e. furthest away from
 * the root graph.
 */
private void hierarchicalLayout(final LGraph lgraph, final IElkProgressMonitor monitor) {
    // Perform a reversed breadth first search: The graphs in the lowest hierarchy come first.
    Collection<LGraph> graphs = collectAllGraphsBottomUp(lgraph);
    // We have to make sure that hierarchical processors don't break the control flow
    // of the following layout execution (see e.g. #228). To be precise, if the root node of
    // the hierarchical graph doesn't include a hierarchical processor, nor may any of the children.
    reviewAndCorrectHierarchicalProcessors(lgraph, graphs);
    // Get list of processors for each graph, since they can be different.
    // Iterators are used, so that processing of a graph can be paused and continued easily.
    int work = 0;
    List<Pair<LGraph, Iterator<ILayoutProcessor<LGraph>>>> graphsAndAlgorithms = new ArrayList<>();
    for (LGraph g : graphs) {
        graphConfigurator.prepareGraphForLayout(g);
        List<ILayoutProcessor<LGraph>> processors = g.getProperty(InternalProperties.PROCESSORS);
        work += processors.size();
        Iterator<ILayoutProcessor<LGraph>> algorithm = processors.iterator();
        graphsAndAlgorithms.add(Pair.of(g, algorithm));
    }
    monitor.begin("Recursive hierarchical layout", work);
    // When the root graph has finished layout, the layout is complete.
    int slotIndex = 0;
    Iterator<ILayoutProcessor<LGraph>> rootProcessors = getProcessorsForRootGraph(graphsAndAlgorithms);
    while (rootProcessors.hasNext()) {
        // Layout from bottom up
        for (Pair<LGraph, Iterator<ILayoutProcessor<LGraph>>> graphAndAlgorithm : graphsAndAlgorithms) {
            Iterator<ILayoutProcessor<LGraph>> processors = graphAndAlgorithm.getSecond();
            LGraph graph = graphAndAlgorithm.getFirst();
            while (processors.hasNext()) {
                ILayoutProcessor<LGraph> processor = processors.next();
                if (!(processor instanceof IHierarchyAwareLayoutProcessor)) {
                    // elkjs-exclude-start
                    if (monitor.isLoggingEnabled()) {
                        DebugUtil.logDebugGraph(monitor, graph, slotIndex, "Before " + processor.getClass().getSimpleName());
                    }
                    // elkjs-exclude-end
                    notifyProcessorReady(graph, processor);
                    processor.process(graph, monitor.subTask(1));
                    notifyProcessorFinished(graph, processor);
                    slotIndex++;
                } else if (isRoot(graph)) {
                    // elkjs-exclude-start
                    if (monitor.isLoggingEnabled()) {
                        DebugUtil.logDebugGraph(monitor, graph, slotIndex, "Before " + processor.getClass().getSimpleName());
                    }
                    // elkjs-exclude-end
                    // If processor operates on the full hierarchy, it must be executed on the root
                    notifyProcessorReady(graph, processor);
                    processor.process(graph, monitor.subTask(1));
                    notifyProcessorFinished(graph, processor);
                    slotIndex++;
                    // Continue operation with the graph at the bottom of the hierarchy
                    break;
                } else {
                    // skip this processor and pause execution until root graph has processed.
                    break;
                }
            }
        }
    }
    // elkjs-exclude-start
    if (monitor.isLoggingEnabled()) {
        DebugUtil.logDebugGraph(monitor, lgraph, slotIndex, "Finished");
    }
    // elkjs-exclude-end
    monitor.done();
}
Also used : ILayoutProcessor(org.eclipse.elk.core.alg.ILayoutProcessor) ArrayList(java.util.ArrayList) LGraph(org.eclipse.elk.alg.layered.graph.LGraph) SizeConstraint(org.eclipse.elk.core.options.SizeConstraint) ListIterator(java.util.ListIterator) Iterator(java.util.Iterator) Pair(org.eclipse.elk.core.util.Pair)

Example 4 with Pair

use of org.eclipse.elk.core.util.Pair in project elk by eclipse.

the class DotExporter method parseSplinePoints.

/**
 * Puts the points of a position string into a list of splines.
 *
 * @param posString string with spline points
 * @param splines list of splines
 * @param offset offset to add to coordinates
 * @return the source and the target point, if specified by the position string
 */
private static Pair<KVector, KVector> parseSplinePoints(final String posString, final List<KVectorChain> splines, final KVector offset) {
    KVector sourcePoint = null, targetPoint = null;
    StringTokenizer splinesTokenizer = new StringTokenizer(posString, "\";");
    while (splinesTokenizer.hasMoreTokens()) {
        KVectorChain pointList = new KVectorChain();
        StringTokenizer posTokenizer = new StringTokenizer(splinesTokenizer.nextToken(), " \t");
        while (posTokenizer.hasMoreTokens()) {
            String token = posTokenizer.nextToken();
            try {
                if (token.startsWith("s")) {
                    if (sourcePoint == null) {
                        sourcePoint = new KVector();
                        int commaIndex = token.indexOf(',');
                        sourcePoint.parse(token.substring(commaIndex + 1));
                        sourcePoint.add(offset);
                    }
                } else if (token.startsWith("e")) {
                    if (targetPoint == null) {
                        targetPoint = new KVector();
                        int commaIndex = token.indexOf(',');
                        targetPoint.parse(token.substring(commaIndex + 1));
                        targetPoint.add(offset);
                    }
                } else {
                    KVector point = new KVector();
                    point.parse(token);
                    pointList.add(point.add(offset));
                }
            } catch (IllegalArgumentException exception) {
            // ignore exception
            }
        }
        splines.add(pointList);
    }
    return new Pair<KVector, KVector>(sourcePoint, targetPoint);
}
Also used : StringTokenizer(java.util.StringTokenizer) KVectorChain(org.eclipse.elk.core.math.KVectorChain) KVector(org.eclipse.elk.core.math.KVector) SizeConstraint(org.eclipse.elk.core.options.SizeConstraint) Pair(org.eclipse.elk.core.util.Pair)

Example 5 with Pair

use of org.eclipse.elk.core.util.Pair in project elk by eclipse.

the class DotImporter method transform.

/**
 * Transform the GraphViz model into a KGraph.
 *
 * @param transData
 *            the transformation data instance that holds the source graph and is enriched with
 *            the new target graphs
 */
public void transform(final IDotTransformationData<GraphvizModel, ElkNode> transData) {
    for (Graph graph : transData.getSourceGraph().getGraphs()) {
        ElkNode parent = ElkGraphUtil.createGraph();
        Map<String, ElkNode> nodeIdMap = Maps.newHashMap();
        transData.setProperty(NODE_ID_MAP, nodeIdMap);
        Map<Pair<ElkNode, String>, ElkPort> portIdMap = Maps.newHashMap();
        transData.setProperty(PORT_ID_MAP, portIdMap);
        transform(graph.getStatements(), parent, transData, new MapPropertyHolder(), new MapPropertyHolder());
        transData.getTargetGraphs().add(parent);
        parent.setProperty(PROP_GRAPH, graph);
    }
}
Also used : Graph(org.eclipse.elk.alg.graphviz.dot.dot.Graph) ElkNode(org.eclipse.elk.graph.ElkNode) ElkPort(org.eclipse.elk.graph.ElkPort) MapPropertyHolder(org.eclipse.elk.graph.properties.MapPropertyHolder) Pair(org.eclipse.elk.core.util.Pair)

Aggregations

Pair (org.eclipse.elk.core.util.Pair)23 LNode (org.eclipse.elk.alg.layered.graph.LNode)8 LEdge (org.eclipse.elk.alg.layered.graph.LEdge)6 ElkNode (org.eclipse.elk.graph.ElkNode)6 Layer (org.eclipse.elk.alg.layered.graph.Layer)5 KVector (org.eclipse.elk.core.math.KVector)5 LPort (org.eclipse.elk.alg.layered.graph.LPort)3 Lists (com.google.common.collect.Lists)2 Iterator (java.util.Iterator)2 List (java.util.List)2 ListIterator (java.util.ListIterator)2 Node (org.eclipse.elk.alg.common.spore.Node)2 CNode (org.eclipse.elk.alg.layered.compaction.oned.CNode)2 LGraph (org.eclipse.elk.alg.layered.graph.LGraph)2 LayeredOptions (org.eclipse.elk.alg.layered.options.LayeredOptions)2 SizeConstraint (org.eclipse.elk.core.options.SizeConstraint)2 IElkProgressMonitor (org.eclipse.elk.core.util.IElkProgressMonitor)2 ElkPort (org.eclipse.elk.graph.ElkPort)2 Iterables (com.google.common.collect.Iterables)1 Maps (com.google.common.collect.Maps)1