Search in sources :

Example 11 with ElkPadding

use of org.eclipse.elk.core.math.ElkPadding in project elk by eclipse.

the class RectPackingLayoutProvider method layout.

/**
 * Calculating and applying layout to the model.
 */
@Override
public void layout(final ElkNode layoutGraph, final IElkProgressMonitor progressMonitor) {
    progressMonitor.begin("Rectangle Packing", 1);
    if (progressMonitor.isLoggingEnabled()) {
        progressMonitor.logGraph(layoutGraph, "Input");
    }
    // The desired aspect ratio.
    double aspectRatio = layoutGraph.getProperty(RectPackingOptions.ASPECT_RATIO);
    // The strategy for the initial width approximation.
    OptimizationGoal goal = layoutGraph.getProperty(RectPackingOptions.OPTIMIZATION_GOAL);
    // Option for better width approximation.
    boolean lastPlaceShift = layoutGraph.getProperty(RectPackingOptions.LAST_PLACE_SHIFT);
    // Option to only do the initial width approximation.
    boolean onlyFirstIteration = layoutGraph.getProperty(RectPackingOptions.ONLY_FIRST_ITERATION);
    // Option whether the nodes should be expanded to fill the bounding rectangle.
    boolean expandNodes = layoutGraph.getProperty(RectPackingOptions.EXPAND_NODES);
    // The padding surrounding the drawing.
    ElkPadding padding = layoutGraph.getProperty(RectPackingOptions.PADDING);
    // The spacing between two nodes.
    double nodeNodeSpacing = layoutGraph.getProperty(RectPackingOptions.SPACING_NODE_NODE);
    // Whether the nodes are compacted after the initial placement.
    boolean compaction = layoutGraph.getProperty(RectPackingOptions.ROW_COMPACTION);
    // Whether the nodes should be expanded to fit the aspect ratio during node expansion.
    // Only effective if nodes are expanded.
    boolean expandToAspectRatio = layoutGraph.getProperty(RectPackingOptions.EXPAND_TO_ASPECT_RATIO);
    // Whether interactive layout is activ.
    boolean interactive = layoutGraph.getProperty(RectPackingOptions.INTERACTIVE);
    // A target width for the algorithm. If this is set the width approximation step is skipped.
    double targetWidth = layoutGraph.getProperty(RectPackingOptions.TARGET_WIDTH);
    List<ElkNode> rectangles = layoutGraph.getChildren();
    DrawingUtil.resetCoordinates(rectangles);
    DrawingData drawing;
    if (interactive) {
        List<ElkNode> fixedNodes = new ArrayList<>();
        for (ElkNode elkNode : rectangles) {
            if (elkNode.hasProperty(RectPackingOptions.DESIRED_POSITION)) {
                fixedNodes.add(elkNode);
            }
        }
        for (ElkNode elkNode : fixedNodes) {
            rectangles.remove(elkNode);
        }
        Collections.sort(fixedNodes, (a, b) -> {
            int positionA = a.getProperty(RectPackingOptions.DESIRED_POSITION);
            int positionB = b.getProperty(RectPackingOptions.DESIRED_POSITION);
            if (positionA == positionB) {
                return -1;
            } else {
                return Integer.compare(positionA, positionB);
            }
        });
        for (ElkNode elkNode : fixedNodes) {
            int position = elkNode.getProperty(RectPackingOptions.DESIRED_POSITION);
            position = Math.min(position, rectangles.size());
            rectangles.add(position, elkNode);
        }
        int index = 0;
        for (ElkNode elkNode : rectangles) {
            elkNode.setProperty(RectPackingOptions.CURRENT_POSITION, index);
            index++;
        }
    }
    // Get minimum size of parent.
    KVector minSize = ElkUtil.effectiveMinSizeConstraintFor(layoutGraph);
    // Remove padding to get the space the algorithm can use.
    minSize.x -= padding.getHorizontal();
    minSize.y -= padding.getVertical();
    double maxWidth = minSize.x;
    if (targetWidth < 0 || targetWidth < minSize.x) {
        // Initial width approximation.
        AreaApproximation firstIt = new AreaApproximation(aspectRatio, goal, lastPlaceShift);
        drawing = firstIt.approxBoundingBox(rectangles, nodeNodeSpacing, padding);
        if (progressMonitor.isLoggingEnabled()) {
            progressMonitor.logGraph(layoutGraph, "After approximation");
        }
    } else {
        drawing = new DrawingData(aspectRatio, targetWidth, 0, DrawingDataDescriptor.WHOLE_DRAWING);
    }
    // Readd padding for next steps.
    minSize.x += padding.getHorizontal();
    minSize.y += padding.getVertical();
    // Placement according to approximated width.
    if (!onlyFirstIteration) {
        DrawingUtil.resetCoordinates(rectangles);
        RowFillingAndCompaction secondIt = new RowFillingAndCompaction(aspectRatio, expandNodes, expandToAspectRatio, compaction, nodeNodeSpacing);
        // Modify the initial approximation if necessary.
        maxWidth = Math.max(minSize.x, drawing.getDrawingWidth());
        // Run placement, compaction, and expansion (if enabled).
        drawing = secondIt.start(rectangles, maxWidth, minSize, progressMonitor, layoutGraph);
    }
    // Final touch.
    applyPadding(rectangles, padding);
    ElkUtil.resizeNode(layoutGraph, drawing.getDrawingWidth() + padding.getHorizontal(), drawing.getDrawingHeight() + padding.getVertical(), false, true);
    // if requested, compute nodes's dimensions, place node labels, ports, port labels, etc.
    if (!layoutGraph.getProperty(RectPackingOptions.OMIT_NODE_MICRO_LAYOUT)) {
        NodeMicroLayout.forGraph(layoutGraph).execute();
    }
    if (progressMonitor.isLoggingEnabled()) {
        progressMonitor.logGraph(layoutGraph, "Output");
    }
    progressMonitor.done();
}
Also used : RowFillingAndCompaction(org.eclipse.elk.alg.rectpacking.seconditeration.RowFillingAndCompaction) ElkNode(org.eclipse.elk.graph.ElkNode) DrawingData(org.eclipse.elk.alg.rectpacking.util.DrawingData) ArrayList(java.util.ArrayList) KVector(org.eclipse.elk.core.math.KVector) ElkPadding(org.eclipse.elk.core.math.ElkPadding) OptimizationGoal(org.eclipse.elk.alg.rectpacking.options.OptimizationGoal) AreaApproximation(org.eclipse.elk.alg.rectpacking.firstiteration.AreaApproximation)

Example 12 with ElkPadding

use of org.eclipse.elk.core.math.ElkPadding in project elk by eclipse.

the class CalculateGraphSize method process.

/**
 * Shift the nodes such that each nodes has x and y coordinates bigger 0.
 */
public void process(final ElkNode graph, final IElkProgressMonitor progressMonitor) {
    progressMonitor.begin("Calculate Graph Size", 1);
    progressMonitor.logGraph(graph, "Before");
    // calculate the offset from border spacing and node distribution
    double minXPos = Double.MAX_VALUE;
    double minYPos = Double.MAX_VALUE;
    double maxXPos = Double.MIN_VALUE;
    double maxYPos = Double.MIN_VALUE;
    for (ElkNode node : graph.getChildren()) {
        double posX = node.getX();
        double posY = node.getY();
        double width = node.getWidth();
        double height = node.getHeight();
        ElkMargin margins = node.getProperty(CoreOptions.MARGINS);
        minXPos = Math.min(minXPos, posX - margins.left);
        minYPos = Math.min(minYPos, posY - margins.top);
        maxXPos = Math.max(maxXPos, posX + width + margins.right);
        maxYPos = Math.max(maxYPos, posY + height + margins.bottom);
    }
    ElkPadding padding = graph.getProperty(CoreOptions.PADDING);
    KVector offset = new KVector(minXPos - padding.getLeft(), minYPos - padding.getTop());
    // process the nodes
    for (ElkNode node : graph.getChildren()) {
        // set the node position
        node.setX(node.getX() - offset.x);
        node.setY(node.getY() - offset.y);
    }
    // set up the graph
    double width = maxXPos - minXPos + padding.getHorizontal();
    double height = maxYPos - minYPos + padding.getVertical();
    graph.setWidth(width);
    graph.setHeight(height);
    progressMonitor.logGraph(graph, "After");
}
Also used : ElkNode(org.eclipse.elk.graph.ElkNode) KVector(org.eclipse.elk.core.math.KVector) ElkPadding(org.eclipse.elk.core.math.ElkPadding) ElkMargin(org.eclipse.elk.core.math.ElkMargin)

Example 13 with ElkPadding

use of org.eclipse.elk.core.math.ElkPadding in project elk by eclipse.

the class BoxLayoutProvider method layout.

@Override
public void layout(final ElkNode layoutNode, final IElkProgressMonitor progressMonitor) {
    progressMonitor.begin("Box layout", 2);
    float objSpacing = layoutNode.getProperty(BoxLayouterOptions.SPACING_NODE_NODE).floatValue();
    ElkPadding padding = layoutNode.getProperty(BoxLayouterOptions.PADDING);
    boolean expandNodes = layoutNode.getProperty(BoxLayouterOptions.EXPAND_NODES);
    boolean interactive = layoutNode.getProperty(BoxLayouterOptions.INTERACTIVE);
    switch(layoutNode.getProperty(BoxLayouterOptions.BOX_PACKING_MODE)) {
        case SIMPLE:
            placeBoxes(layoutNode, objSpacing, padding, expandNodes, interactive);
            break;
        default:
            // any of the groups
            placeBoxesGrouping(layoutNode, objSpacing, padding, expandNodes);
    }
    progressMonitor.done();
}
Also used : ElkPadding(org.eclipse.elk.core.math.ElkPadding)

Example 14 with ElkPadding

use of org.eclipse.elk.core.math.ElkPadding in project elk by eclipse.

the class DotExporter method transformNodes.

/**
 * Transform the child nodes of the given parent node.
 *
 * @param parent a parent node
 * @param statements the list to which new statements are added
 * @param offset offset of the parent node in the whole graph
 * @param transData transformation data
 */
private void transformNodes(final ElkNode parent, final List<Statement> statements, final KVector offset, final IDotTransformationData<ElkNode, GraphvizModel> transData) {
    // set attributes for the whole graph
    setGraphAttributes(statements, parent, transData);
    // create nodes and subgraphs
    boolean hierarchy = transData.getProperty(HIERARCHY);
    boolean transformNodeLayout = transData.getProperty(TRANSFORM_NODE_LAYOUT);
    boolean transformNodeLabels = transData.getProperty(TRANSFORM_NODE_LABELS);
    for (ElkNode childNode : parent.getChildren()) {
        NodeStatement nodeStatement = DotFactory.eINSTANCE.createNodeStatement();
        List<Attribute> attributes = nodeStatement.getAttributes();
        String nodeID;
        // if hierarchy mode is active, create a subgraph, else a regular node
        if (hierarchy && !childNode.getChildren().isEmpty()) {
            String clusterNodeID = getNodeID(childNode, NodeType.CLUSTER, transData);
            Subgraph subgraph = DotFactory.eINSTANCE.createSubgraph();
            subgraph.setName(clusterNodeID);
            statements.add(subgraph);
            // transform child nodes recursively
            ElkPadding padding = childNode.getProperty(CoreOptions.PADDING);
            double subgraphx = childNode.getX() + padding.getLeft();
            double subgraphy = childNode.getY() + padding.getTop();
            transformNodes(childNode, subgraph.getStatements(), new KVector(offset).add(subgraphx, subgraphy), transData);
            // create a dummy node for compound edges
            nodeID = getNodeID(childNode, NodeType.DUMMY, transData);
            attributes.add(createAttribute(Attributes.STYLE, "invis"));
            attributes.add(createAttribute(Attributes.WIDTH, 0));
            attributes.add(createAttribute(Attributes.HEIGHT, 0));
            subgraph.getStatements().add(nodeStatement);
        } else {
            nodeID = getNodeID(childNode, NodeType.NODE, transData);
            // set width and height
            ElkUtil.resizeNode(childNode);
            if (childNode.getWidth() > 0) {
                attributes.add(createAttribute(Attributes.WIDTH, childNode.getWidth() / DPI));
            }
            if (childNode.getHeight() > 0) {
                attributes.add(createAttribute(Attributes.HEIGHT, childNode.getHeight() / DPI));
            }
            if (transformNodeLabels && !childNode.getLabels().isEmpty() && childNode.getLabels().get(0).getText().length() > 0) {
                attributes.add(createAttribute(Attributes.LABEL, createString(childNode.getLabels().get(0).getText())));
            }
            // add node position if interactive layout is chosen
            if (transformNodeLayout && (childNode.getX() != 0 || childNode.getY() != 0)) {
                double xpos = (childNode.getX() + childNode.getWidth() / 2 + offset.x);
                double ypos = (childNode.getY() + childNode.getHeight() / 2 + offset.y);
                String posString = "\"" + Double.toString(xpos) + "," + Double.toString(ypos) + "\"";
                attributes.add(createAttribute(Attributes.POS, posString));
            }
            statements.add(nodeStatement);
        }
        Node node = DotFactory.eINSTANCE.createNode();
        node.setName(nodeID);
        nodeStatement.setNode(node);
    }
}
Also used : ElkNode(org.eclipse.elk.graph.ElkNode) Attribute(org.eclipse.elk.alg.graphviz.dot.dot.Attribute) NodeStatement(org.eclipse.elk.alg.graphviz.dot.dot.NodeStatement) ElkNode(org.eclipse.elk.graph.ElkNode) Node(org.eclipse.elk.alg.graphviz.dot.dot.Node) Subgraph(org.eclipse.elk.alg.graphviz.dot.dot.Subgraph) KVector(org.eclipse.elk.core.math.KVector) ElkPadding(org.eclipse.elk.core.math.ElkPadding)

Example 15 with ElkPadding

use of org.eclipse.elk.core.math.ElkPadding in project elk by eclipse.

the class DotExporter method transferLayout.

/**
 * Applies the layout information attached to the given Dot instance to the KGraph instance
 * using the mapping created by a previous call to {@code transform}. Has to be called after a
 * call to {@code transform}.
 *
 * @param transData the transformation data instance
 */
public void transferLayout(final IDotTransformationData<ElkNode, GraphvizModel> transData) {
    ElkPadding padding = transData.getSourceGraph().getProperty(CoreOptions.PADDING);
    Graph graph = transData.getTargetGraphs().get(0).getGraphs().get(0);
    // process nodes and subgraphs
    KVector baseOffset = new KVector();
    applyLayout(transData.getSourceGraph(), graph.getStatements(), baseOffset, padding, transData);
    // finally process the edges
    LinkedList<Statement> statements = new LinkedList<Statement>(graph.getStatements());
    KVector edgeOffset = baseOffset.add(padding.getLeft(), padding.getTop());
    while (!statements.isEmpty()) {
        Statement statement = statements.removeFirst();
        if (statement instanceof EdgeStatement) {
            applyEdgeLayout((EdgeStatement) statement, edgeOffset, transData);
        } else if (statement instanceof Subgraph) {
            statements.addAll(((Subgraph) statement).getStatements());
        }
    }
}
Also used : Graph(org.eclipse.elk.alg.graphviz.dot.dot.Graph) EdgeStatement(org.eclipse.elk.alg.graphviz.dot.dot.EdgeStatement) NodeStatement(org.eclipse.elk.alg.graphviz.dot.dot.NodeStatement) AttributeStatement(org.eclipse.elk.alg.graphviz.dot.dot.AttributeStatement) Statement(org.eclipse.elk.alg.graphviz.dot.dot.Statement) Subgraph(org.eclipse.elk.alg.graphviz.dot.dot.Subgraph) KVector(org.eclipse.elk.core.math.KVector) ElkPadding(org.eclipse.elk.core.math.ElkPadding) LinkedList(java.util.LinkedList) EdgeStatement(org.eclipse.elk.alg.graphviz.dot.dot.EdgeStatement)

Aggregations

ElkPadding (org.eclipse.elk.core.math.ElkPadding)73 ElkNode (org.eclipse.elk.graph.ElkNode)34 KVector (org.eclipse.elk.core.math.KVector)25 Test (org.junit.Test)18 BasicProgressMonitor (org.eclipse.elk.core.util.BasicProgressMonitor)15 ElkLabel (org.eclipse.elk.graph.ElkLabel)10 ElkRectangle (org.eclipse.elk.core.math.ElkRectangle)9 ElkEdge (org.eclipse.elk.graph.ElkEdge)9 KText (de.cau.cs.kieler.klighd.krendering.KText)5 ArrayList (java.util.ArrayList)5 HashMap (java.util.HashMap)5 ElkEdgeSection (org.eclipse.elk.graph.ElkEdgeSection)5 KLabel (de.cau.cs.kieler.klighd.kgraph.KLabel)4 KContainerRendering (de.cau.cs.kieler.klighd.krendering.KContainerRendering)4 ElkMargin (org.eclipse.elk.core.math.ElkMargin)4 ElkPort (org.eclipse.elk.graph.ElkPort)4 KNode (de.cau.cs.kieler.klighd.kgraph.KNode)3 HashSet (java.util.HashSet)3 NodeStatement (org.eclipse.elk.alg.graphviz.dot.dot.NodeStatement)3 Subgraph (org.eclipse.elk.alg.graphviz.dot.dot.Subgraph)3