Search in sources :

Example 6 with CGroup

use of org.eclipse.elk.alg.layered.compaction.oned.CGroup in project elk by eclipse.

the class OneDimensionalComponentsCompaction method compact.

/**
 * Internal compaction method, performs 3 compactions into each direction (horizontal first,
 * then vertical). The first compaction is unconstrained, the latter two consider the node locks.
 */
private double compact(final int run) {
    double delta = 0;
    // reset all groups' deltas
    for (CGroup g : compactionGraph.cGroups) {
        g.delta = 0;
        g.deltaNormalized = 0;
    }
    // ----------------------------------------------------
    // #1 We want to perform horizontal compaction first.
    // For this we have to add the vertical external
    // edges to the hulls to prevent edge node overlaps
    // ----------------------------------------------------
    addPlaceholders(Dir.HORZ);
    addExternalEdgeRepresentations(verticalExternalExtensions);
    compactor.calculateGroupOffsets();
    // there are new nodes in the compaction graph, we have to update the constraints
    compactor.forceConstraintsRecalculation();
    Direction direction = Direction.LEFT;
    // compact horizontally
    compactor.changeDirection(direction).compact().changeDirection(direction.opposite()).applyLockingStrategy().compact().changeDirection(direction).applyLockingStrategy().compact();
    // very important to transform back to LEFT
    // because the hitboxes representing external edges
    // that will be added in a second have not been transformed yet
    compactor.changeDirection(Direction.LEFT);
    // remove the vertical external edges again
    removeExternalEdgeRepresentations(verticalExternalExtensions);
    removePlaceholders(Dir.HORZ);
    // .. and offset the horizontal external edges (that will be added next)
    // according to the just finished horizontal compaction
    updateExternalExtensionDimensions(Dir.HORZ);
    updatePlaceholders(Dir.VERT);
    // ----------------------------------------------------
    // #2 We want to perform vertical compaction.
    // ----------------------------------------------------
    // now add them
    addPlaceholders(Dir.VERT);
    addExternalEdgeRepresentations(horizontalExternalExtensions);
    compactor.calculateGroupOffsets();
    // remember delta from horizontal compaction
    for (CGroup g : compactionGraph.cGroups) {
        delta += Math.abs(g.deltaNormalized);
    }
    // reset all groups' deltas
    for (CGroup g : compactionGraph.cGroups) {
        g.delta = 0;
        g.deltaNormalized = 0;
    }
    direction = Direction.UP;
    // compact vertically
    compactor.changeDirection(direction).forceConstraintsRecalculation().compact().changeDirection(direction.opposite()).applyLockingStrategy().compact().changeDirection(direction).applyLockingStrategy().compact();
    // transform back to LEFT
    compactor.changeDirection(Direction.LEFT);
    // remove the horizontal external edges
    removeExternalEdgeRepresentations(horizontalExternalExtensions);
    removePlaceholders(Dir.VERT);
    // ... offset the vertical external edges
    // (which have been excluded during the last compaction)
    updateExternalExtensionDimensions(Dir.VERT);
    updatePlaceholders(Dir.HORZ);
    compactor.forceConstraintsRecalculation();
    // ... and the delta from vertical compaction
    for (CGroup g : compactionGraph.cGroups) {
        delta += Math.abs(g.deltaNormalized);
    }
    return delta;
}
Also used : Direction(org.eclipse.elk.core.options.Direction) CGroup(org.eclipse.elk.alg.layered.compaction.oned.CGroup)

Example 7 with CGroup

use of org.eclipse.elk.alg.layered.compaction.oned.CGroup in project elk by eclipse.

the class OneDimensionalComponentsCompaction method removePlaceholders.

private void removePlaceholders(final Dir dir) {
    Set<Direction> dirs = (dir == Dir.VERT) ? UP_DOWN : LEFT_RIGHT;
    for (Direction d : dirs) {
        for (Pair<CGroup, CNode> pair : transformer.getExternalPlaceholder().get(d)) {
            compactionGraph.cNodes.remove(pair.getSecond());
            compactionGraph.cGroups.remove(pair.getSecond().cGroup);
        }
    }
}
Also used : CNode(org.eclipse.elk.alg.layered.compaction.oned.CNode) Direction(org.eclipse.elk.core.options.Direction) CGroup(org.eclipse.elk.alg.layered.compaction.oned.CGroup)

Example 8 with CGroup

use of org.eclipse.elk.alg.layered.compaction.oned.CGroup in project elk by eclipse.

the class LongestPathCompaction method compact.

@Override
public void compact(final OneDimensionalCompactor compactor) {
    // calculating the left-most position of any element
    // this will be our starting point for the compaction
    double minStartPos = Double.POSITIVE_INFINITY;
    for (CNode cNode : compactor.cGraph.cNodes) {
        minStartPos = Math.min(minStartPos, cNode.cGroup.reference.hitbox.x + cNode.cGroupOffset.x);
    }
    // finding the sinks of the constraint graph
    Queue<CGroup> sinks = Lists.newLinkedList();
    for (CGroup group : compactor.cGraph.cGroups) {
        group.startPos = minStartPos;
        if (group.outDegree == 0) {
            sinks.add(group);
        }
    }
    // process sinks until every node in the constraint graph was handled
    while (!sinks.isEmpty()) {
        CGroup group = sinks.poll();
        // record the movement of this group during the current compaction
        // this has to be recorded _before_ the nodes' positions are updated
        // and care has to be taken about the compaction direction. In certain
        // scenarios nodes may move "back-and-forth". To detect this, we associate
        // a negative delta with two of the compaction directions.
        double diff = group.reference.hitbox.x;
        // ------------------------------------------
        for (CNode node : group.cNodes) {
            // CNodes can be locked in place to avoid pulling clusters apart
            double suggestedX = group.startPos + node.cGroupOffset.x;
            if (// node.reposition
            node.cGroup.reposition || // does the "fixed" position violate the constraints?
            (node.getPosition() < suggestedX)) {
                node.startPos = suggestedX;
            } else {
                // leave the node where it was!
                node.startPos = node.hitbox.x;
            }
        }
        diff -= group.reference.startPos;
        group.delta += diff;
        if (compactor.direction == Direction.RIGHT || compactor.direction == Direction.DOWN) {
            group.deltaNormalized += diff;
        } else {
            group.deltaNormalized -= diff;
        }
        // ---------------------------------------------------
        for (CNode node : group.cNodes) {
            for (CNode incNode : node.constraints) {
                // determine the required spacing
                double spacing;
                if (compactor.direction.isHorizontal()) {
                    spacing = compactor.spacingsHandler.getHorizontalSpacing(node, incNode);
                } else {
                    spacing = compactor.spacingsHandler.getVerticalSpacing(node, incNode);
                }
                incNode.cGroup.startPos = Math.max(incNode.cGroup.startPos, node.startPos + node.hitbox.width + spacing - // respect the other group's node's offset
                incNode.cGroupOffset.x);
                // whether the node's current position should be preserved
                if (!incNode.reposition) {
                    incNode.cGroup.startPos = Math.max(incNode.cGroup.startPos, incNode.getPosition() - incNode.cGroupOffset.x);
                }
                incNode.cGroup.outDegree--;
                if (incNode.cGroup.outDegree == 0) {
                    sinks.add(incNode.cGroup);
                }
            }
        }
    }
    // ------------------------------------------------------
    for (CNode cNode : compactor.cGraph.cNodes) {
        cNode.applyPosition();
    }
}
Also used : CNode(org.eclipse.elk.alg.layered.compaction.oned.CNode) CGroup(org.eclipse.elk.alg.layered.compaction.oned.CGroup)

Example 9 with CGroup

use of org.eclipse.elk.alg.layered.compaction.oned.CGroup in project elk by eclipse.

the class ComponentsToCGraphTransformer method applyLayout.

/* -----------------------------------------------------------
     *                    Layout Application 
     * ----------------------------------------------------------- */
@Override
public void applyLayout() {
    for (CNode n : cGraph.cNodes) {
        n.applyElementPosition();
    }
    // calculating new graph size and offset
    KVector topLeft = new KVector(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
    KVector bottomRight = new KVector(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
    for (CNode cNode : cGraph.cNodes) {
        topLeft.x = Math.min(topLeft.x, cNode.hitbox.x);
        topLeft.y = Math.min(topLeft.y, cNode.hitbox.y);
        bottomRight.x = Math.max(bottomRight.x, cNode.hitbox.x + cNode.hitbox.width);
        bottomRight.y = Math.max(bottomRight.y, cNode.hitbox.y + cNode.hitbox.height);
    }
    // which allows to use them to determine the maximum position
    for (Pair<CGroup, CNode> placeholder : externalPlaceholder.values()) {
        CNode cNode = placeholder.getSecond();
        topLeft.x = Math.min(topLeft.x, cNode.hitbox.x);
        topLeft.y = Math.min(topLeft.y, cNode.hitbox.y);
        bottomRight.x = Math.max(bottomRight.x, cNode.hitbox.x + cNode.hitbox.width);
        bottomRight.y = Math.max(bottomRight.y, cNode.hitbox.y + cNode.hitbox.height);
    }
    globalOffset = topLeft.clone().negate();
    graphSize = bottomRight.clone().sub(topLeft);
    // resetting lists
    cGraph.cGroups.clear();
    cGraph.cNodes.clear();
}
Also used : CNode(org.eclipse.elk.alg.layered.compaction.oned.CNode) KVector(org.eclipse.elk.core.math.KVector) CGroup(org.eclipse.elk.alg.layered.compaction.oned.CGroup)

Example 10 with CGroup

use of org.eclipse.elk.alg.layered.compaction.oned.CGroup in project elk by eclipse.

the class OneDimensionalComponentsCompaction method updateExternalExtensionDimensions.

/**
 * During compaction of the x dimension the horizontal external extensions are not part of the
 * graph that is being compacted. As a consequence, their positions are not updated. We make up
 * for this in this method. Additionally, the dimensions of the diagram are respected and
 * external extensions are guaranteed to always extend to the very border of the diagram
 * (preventing components from overlapping with edges).
 *
 * @param dir
 *            whether to update the vertical or the horizontal extensions.
 */
private void updateExternalExtensionDimensions(final Dir dir) {
    for (Entry<IExternalExtension<E>, Pair<CGroup, CNode>> entry : transformer.getExternalExtensions().entrySet()) {
        IExternalExtension<E> ee = entry.getKey();
        if (dir == Dir.VERT) {
            if (ee.getDirection() != Direction.UP && ee.getDirection() != Direction.DOWN) {
                continue;
            }
        } else {
            if (ee.getDirection() != Direction.LEFT && ee.getDirection() != Direction.RIGHT) {
                continue;
            }
        }
        CNode cNode = entry.getValue().getSecond();
        // the node may not be associated with the group atm, thus cNode.group may be null
        CGroup group = entry.getValue().getFirst();
        // deltaNormalized is negative if a group was moved to the left,
        // positive if the group was moved to the right
        double adelta = group.deltaNormalized;
        switch(ee.getDirection()) {
            case LEFT:
                // x sticks to the left of the diagram
                cNode.hitbox.x = topLeft.x;
                cNode.hitbox.width = Math.max(1, cNode.hitbox.width + adelta);
                break;
            case RIGHT:
                cNode.hitbox.x = cNode.hitbox.x + adelta;
                cNode.hitbox.width = Math.max(1, cNode.hitbox.width - adelta);
                break;
            case UP:
                // y sticks to the top of the diagram
                cNode.hitbox.y = topLeft.y;
                cNode.hitbox.height = Math.max(1, cNode.hitbox.height + adelta);
                break;
            case DOWN:
                cNode.hitbox.y = cNode.hitbox.y + adelta;
                cNode.hitbox.height = Math.max(1, cNode.hitbox.height - adelta);
                break;
        }
    }
}
Also used : CNode(org.eclipse.elk.alg.layered.compaction.oned.CNode) CGroup(org.eclipse.elk.alg.layered.compaction.oned.CGroup) Pair(org.eclipse.elk.core.util.Pair)

Aggregations

CGroup (org.eclipse.elk.alg.layered.compaction.oned.CGroup)13 Direction (org.eclipse.elk.core.options.Direction)9 CGraph (org.eclipse.elk.alg.layered.compaction.oned.CGraph)6 CNode (org.eclipse.elk.alg.layered.compaction.oned.CNode)6 ElkRectangle (org.eclipse.elk.core.math.ElkRectangle)6 Test (org.junit.Test)5 KVector (org.eclipse.elk.core.math.KVector)2 Pair (org.eclipse.elk.core.util.Pair)1