Search in sources :

Example 11 with ElkRectangle

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

the class NodeMarginCalculator method processNode.

/**
 * Calculates the margin of the given node.
 *
 * @param node the node whose margin to calculate.
 * @param labelSpacing label spacing set on the layered graph.
 */
private void processNode(final NodeAdapter<?> node, final double labelSpacing) {
    // This will be our bounding box. We'll start with one that's the same size
    // as our node, and at the same position.
    ElkRectangle boundingBox = new ElkRectangle(node.getPosition().x, node.getPosition().y, node.getSize().x, node.getSize().y);
    // We'll reuse this rectangle as our box for elements to add to the bounding box
    ElkRectangle elementBox = new ElkRectangle();
    // Put the node's labels into the bounding box
    if (includeLabels) {
        for (LabelAdapter<?> label : node.getLabels()) {
            elementBox.x = label.getPosition().x + node.getPosition().x;
            elementBox.y = label.getPosition().y + node.getPosition().y;
            elementBox.width = label.getSize().x;
            elementBox.height = label.getSize().y;
            boundingBox.union(elementBox);
        }
    }
    // Do the same for ports and their labels
    for (PortAdapter<?> port : node.getPorts()) {
        // Calculate the port's upper left corner's x and y coordinate
        double portX = port.getPosition().x + node.getPosition().x;
        double portY = port.getPosition().y + node.getPosition().y;
        // The port itself
        if (includePorts) {
            elementBox.x = portX;
            elementBox.y = portY;
            elementBox.width = port.getSize().x;
            elementBox.height = port.getSize().y;
            boundingBox.union(elementBox);
        }
        // The port's labels
        if (includePortLabels) {
            for (LabelAdapter<?> label : port.getLabels()) {
                elementBox.x = label.getPosition().x + portX;
                elementBox.y = label.getPosition().y + portY;
                elementBox.width = label.getSize().x;
                elementBox.height = label.getSize().y;
                boundingBox.union(elementBox);
            }
        }
        // End labels of edges connected to the port
        if (includeEdgeHeadTailLabels) {
            KVector requiredPortLabelSpace = new KVector(-labelSpacing, -labelSpacing);
            // TODO: maybe leave space for manually placed ports
            if (node.getProperty(CoreOptions.PORT_LABELS_PLACEMENT).contains(PortLabelPlacement.OUTSIDE)) {
                for (LabelAdapter<?> label : port.getLabels()) {
                    requiredPortLabelSpace.x += label.getSize().x + labelSpacing;
                    requiredPortLabelSpace.y += label.getSize().y + labelSpacing;
                }
            }
            requiredPortLabelSpace.x = Math.max(requiredPortLabelSpace.x, 0.0);
            requiredPortLabelSpace.y = Math.max(requiredPortLabelSpace.y, 0.0);
            processEdgeHeadTailLabels(boundingBox, port.getOutgoingEdges(), port.getIncomingEdges(), node, port, requiredPortLabelSpace, labelSpacing);
        }
    }
    // Process end labels of edges directly connected to the node
    if (includeEdgeHeadTailLabels) {
        processEdgeHeadTailLabels(boundingBox, node.getOutgoingEdges(), node.getIncomingEdges(), node, null, null, labelSpacing);
    }
    // Reset the margin (guard against very small double precision errors which can cause the results to be small
    // negative values, which doesn't make sense -- see #616)
    ElkMargin margin = new ElkMargin(node.getMargin());
    margin.top = Math.max(0, node.getPosition().y - boundingBox.y);
    margin.bottom = Math.max(0, boundingBox.y + boundingBox.height - (node.getPosition().y + node.getSize().y));
    margin.left = Math.max(0, node.getPosition().x - boundingBox.x);
    margin.right = Math.max(0, boundingBox.x + boundingBox.width - (node.getPosition().x + node.getSize().x));
    node.setMargin(margin);
}
Also used : ElkRectangle(org.eclipse.elk.core.math.ElkRectangle) KVector(org.eclipse.elk.core.math.KVector) ElkMargin(org.eclipse.elk.core.math.ElkMargin)

Example 12 with ElkRectangle

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

the class NodeMarginCalculator method processEdgeHeadTailLabels.

/**
 * Adds the bounding boxes of the head or tail labels of the given sets of outgoing and incoming
 * edges to the given bounding box.
 *
 * @param boundingBox the bounding box that should be enlarged to include head and tail labels.
 * @param outgoingEdges set of outgoing edges whose tail labels should be included.
 * @param incomingEdges set of incoming edges whose head labels should be included.
 * @param node the node we're processing labels for.
 * @param port the port if the edges are connected to one.
 * @param portLabelSpace if the edges are connected to a port, this is the space required to
 *                               place the port's labels.
 * @param labelSpacing label spacing.
 */
private void processEdgeHeadTailLabels(final ElkRectangle boundingBox, final Iterable<EdgeAdapter<?>> outgoingEdges, final Iterable<EdgeAdapter<?>> incomingEdges, final NodeAdapter<?> node, final PortAdapter<?> port, final KVector portLabelSpace, final double labelSpacing) {
    ElkRectangle labelBox = new ElkRectangle();
    // For each edge, the tail labels of outgoing edges ...
    for (EdgeAdapter<?> edge : outgoingEdges) {
        for (LabelAdapter<?> label : edge.getLabels()) {
            if (label.getProperty(CoreOptions.EDGE_LABELS_PLACEMENT) == EdgeLabelPlacement.TAIL) {
                computeLabelBox(labelBox, label, false, node, port, portLabelSpace, labelSpacing);
                boundingBox.union(labelBox);
            }
        }
    }
    // ... and the head label of incoming edges shall be considered
    for (EdgeAdapter<?> edge : incomingEdges) {
        for (LabelAdapter<?> label : edge.getLabels()) {
            if (label.getProperty(CoreOptions.EDGE_LABELS_PLACEMENT) == EdgeLabelPlacement.HEAD) {
                computeLabelBox(labelBox, label, true, node, port, portLabelSpace, labelSpacing);
                boundingBox.union(labelBox);
            }
        }
    }
}
Also used : ElkRectangle(org.eclipse.elk.core.math.ElkRectangle)

Example 13 with ElkRectangle

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

the class DepthFirstCompaction method compactTree.

/**
 * Recursive function to compact a tree depth-first.
 * @param tree root of a tree
 */
private static void compactTree(final Tree<Node> tree) {
    // first compact the children of the current node
    tree.children.forEach(DepthFirstCompaction::compactTree);
    // remove underlap between root and its children
    for (Tree<Node> child : tree.children) {
        // find the direction and distance the subtree has to be moved to close the gap to the root node
        KVector compactionVector = tree.node.vertex.clone().sub(child.node.vertex);
        if (orthogonalCompaction) {
            ElkRectangle rt = tree.node.rect;
            ElkRectangle rc = child.node.rect;
            // restrict the compaction vector to its larger coordinate
            if (Math.abs(compactionVector.x) >= Math.abs(compactionVector.y)) {
                compactionVector.y = 0;
                // scale compaction vector to orthogonal distance between tree and child
                if (rc.y + rc.height > rt.y && rc.y < rt.y + rt.height) {
                    // overlap in vertical dimension
                    compactionVector.scaleToLength(Math.max(rt.x - (rc.x + rc.width), rc.x - (rt.x + rt.width)));
                }
            } else {
                compactionVector.x = 0;
                // scale compaction vector to orthogonal distance between tree and child
                if (rc.x + rc.width > rt.x && rc.x < rt.x + rt.width) {
                    // overlap in horizontal dimension
                    compactionVector.scaleToLength(Math.max(rt.y - (rc.y + rc.height), rc.y - (rt.y + rt.height)));
                }
            }
        } else {
            compactionVector.scaleToLength(tree.node.underlap(child.node));
        }
        // determine the maximum distance the subtree can be moved without collision, i.e. the minimum underlap
        double minUnderlap = compactionVector.length();
        // find minimum underlap between any node in the child and any other node in the rest of the
        // tree in compaction direction
        minUnderlap = getMinUnderlap(root, child, minUnderlap, compactionVector);
        // use the minimum underlap to move whole subtree
        compactionVector.scaleToLength(minUnderlap);
        translateSubtree(child, compactionVector);
        debugOut(tree, child);
    }
}
Also used : KVector(org.eclipse.elk.core.math.KVector) ElkRectangle(org.eclipse.elk.core.math.ElkRectangle)

Example 14 with ElkRectangle

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

the class ContainerCell method applyHorizontalLayout.

/**
 * Applies the given horizontal layout information to the given cell if it's not {@code null}.
 *
 * @param cell
 *            the cell to apply the layout information to.
 * @param x
 *            the cell's new x coordinate.
 * @param width
 *            the cell's new width.
 */
protected void applyHorizontalLayout(final Cell cell, final double x, final double width) {
    if (cell != null) {
        ElkRectangle cellRect = cell.getCellRectangle();
        cellRect.x = x;
        cellRect.width = width;
    }
}
Also used : ElkRectangle(org.eclipse.elk.core.math.ElkRectangle)

Example 15 with ElkRectangle

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

the class ContainerCell method applyVerticalLayout.

/**
 * Applies the given vertical layout information to the given cell if it's not {@code null}.
 *
 * @param cell
 *            the cell to apply the layout information to.
 * @param y
 *            the cell's new y coordinate.
 * @param height
 *            the cell's new height.
 */
protected void applyVerticalLayout(final Cell cell, final double y, final double height) {
    if (cell != null) {
        ElkRectangle cellRect = cell.getCellRectangle();
        cellRect.y = y;
        cellRect.height = height;
    }
}
Also used : ElkRectangle(org.eclipse.elk.core.math.ElkRectangle)

Aggregations

ElkRectangle (org.eclipse.elk.core.math.ElkRectangle)82 KVector (org.eclipse.elk.core.math.KVector)33 Test (org.junit.Test)27 Direction (org.eclipse.elk.core.options.Direction)18 CGraph (org.eclipse.elk.alg.layered.compaction.oned.CGraph)17 ElkPadding (org.eclipse.elk.core.math.ElkPadding)9 PortContext (org.eclipse.elk.alg.common.nodespacing.internal.PortContext)8 LabelCell (org.eclipse.elk.alg.common.nodespacing.cellsystem.LabelCell)7 CGroup (org.eclipse.elk.alg.layered.compaction.oned.CGroup)6 Point (org.eclipse.elk.alg.common.Point)4 LMargin (org.eclipse.elk.alg.layered.graph.LMargin)4 LPort (org.eclipse.elk.alg.layered.graph.LPort)4 ElkNode (org.eclipse.elk.graph.ElkNode)4 RectilinearConvexHull (org.eclipse.elk.alg.common.RectilinearConvexHull)3 AtomicCell (org.eclipse.elk.alg.common.nodespacing.cellsystem.AtomicCell)3 RectangleStripOverlapRemover (org.eclipse.elk.alg.common.overlaps.RectangleStripOverlapRemover)3 LEdge (org.eclipse.elk.alg.layered.graph.LEdge)3 LLabel (org.eclipse.elk.alg.layered.graph.LLabel)3 LNode (org.eclipse.elk.alg.layered.graph.LNode)3 Random (java.util.Random)2