Search in sources :

Example 1 with ElkMargin

use of org.eclipse.elk.core.math.ElkMargin in project lingua-franca by lf-lang.

the class InterfaceDependenciesVisualization method addInterfaceDependencies.

/**
 * Adds interface dependencies to the node if this option is active.
 * Visibility will be adjusted based on expansion state.
 */
public Spacing addInterfaceDependencies(KNode node, boolean expanded) {
    Spacing marginInit = null;
    if (getBooleanValue(SHOW_INTERFACE_DEPENDENCIES)) {
        List<Pair<KPort, KPort>> deps = getPortDependencies(node);
        if (!deps.isEmpty()) {
            for (Pair<KPort, KPort> pair : deps) {
                createDependencyEdge(pair, expanded);
            }
            // Fix content (label) of collapsed rendering
            KContainerRendering contentContainer = IterableExtensions.findFirst(Iterables.filter(node.getData(), KContainerRendering.class), it -> {
                return it.getProperty(KlighdProperties.COLLAPSED_RENDERING);
            });
            if (contentContainer != null) {
                if (!contentContainer.getProperty(LinguaFrancaShapeExtensions.REACTOR_CONTENT_CONTAINER)) {
                    contentContainer = IteratorExtensions.findFirst(Iterators.filter(contentContainer.eAllContents(), KContainerRendering.class), it -> {
                        return it.getProperty(LinguaFrancaShapeExtensions.REACTOR_CONTENT_CONTAINER);
                    });
                }
                if (contentContainer != null) {
                    List<KRendering> content = ImmutableList.copyOf(contentContainer.getChildren());
                    // Put into two new containers such that they are not centered/maximized
                    KRectangle firstContainer = _kContainerRenderingExtensions.addRectangle(contentContainer);
                    _kRenderingExtensions.setInvisible(firstContainer, true);
                    KRectangle secondContainer = _kContainerRenderingExtensions.addRectangle(firstContainer);
                    _kRenderingExtensions.setInvisible(secondContainer, true);
                    _kContainerRenderingExtensions.setGridPlacement(secondContainer, 1);
                    Iterables.addAll(secondContainer.getChildren(), content);
                    _kRenderingExtensions.setPointPlacementData(secondContainer, _kRenderingExtensions.LEFT, 0, 0.5f, _kRenderingExtensions.TOP, 0, 0, _kRenderingExtensions.H_CENTRAL, _kRenderingExtensions.V_TOP, 0, 0, 0, 0);
                    // Adjust ports separate dependency edges from label/content
                    if (content.size() > 0) {
                        marginInit = _utilityExtensions.getPortMarginsInitIfAbsent(node).add(new ElkMargin((content.size() * 20) - 8, 0, 0, 0));
                    }
                }
            }
        }
    }
    return marginInit;
}
Also used : CoreOptions(org.eclipse.elk.core.options.CoreOptions) Iterables(com.google.common.collect.Iterables) ElkMargin(org.eclipse.elk.core.math.ElkMargin) Spacing(org.eclipse.elk.core.math.Spacing) LinguaFrancaStyleExtensions(org.lflang.diagram.synthesis.styles.LinguaFrancaStyleExtensions) Inject(com.google.inject.Inject) Random(java.util.Random) Extension(org.eclipse.xtext.xbase.lib.Extension) AbstractSynthesisExtensions(org.lflang.diagram.synthesis.AbstractSynthesisExtensions) Iterators(com.google.common.collect.Iterators) KEdgeExtensions(de.cau.cs.kieler.klighd.krendering.extensions.KEdgeExtensions) KContainerRenderingExtensions(de.cau.cs.kieler.klighd.krendering.extensions.KContainerRenderingExtensions) KRenderingExtensions(de.cau.cs.kieler.klighd.krendering.extensions.KRenderingExtensions) KPolyline(de.cau.cs.kieler.klighd.krendering.KPolyline) LineStyle(de.cau.cs.kieler.klighd.krendering.LineStyle) ImmutableList(com.google.common.collect.ImmutableList) KRendering(de.cau.cs.kieler.klighd.krendering.KRendering) LinguaFrancaSynthesis(org.lflang.diagram.synthesis.LinguaFrancaSynthesis) DiagramSyntheses(de.cau.cs.kieler.klighd.syntheses.DiagramSyntheses) KEdge(de.cau.cs.kieler.klighd.kgraph.KEdge) KNode(de.cau.cs.kieler.klighd.kgraph.KNode) KPort(de.cau.cs.kieler.klighd.kgraph.KPort) KInvisibility(de.cau.cs.kieler.klighd.krendering.KInvisibility) SynthesisOption(de.cau.cs.kieler.klighd.SynthesisOption) Property(org.eclipse.elk.graph.properties.Property) KRenderingFactory(de.cau.cs.kieler.klighd.krendering.KRenderingFactory) Set(java.util.Set) KContainerRendering(de.cau.cs.kieler.klighd.krendering.KContainerRendering) LinguaFrancaShapeExtensions(org.lflang.diagram.synthesis.styles.LinguaFrancaShapeExtensions) Sets(com.google.common.collect.Sets) IteratorExtensions(org.eclipse.xtext.xbase.lib.IteratorExtensions) List(java.util.List) IterableExtensions(org.eclipse.xtext.xbase.lib.IterableExtensions) KlighdProperties(de.cau.cs.kieler.klighd.util.KlighdProperties) ViewSynthesisShared(de.cau.cs.kieler.klighd.krendering.ViewSynthesisShared) KRectangle(de.cau.cs.kieler.klighd.krendering.KRectangle) Pair(org.eclipse.xtext.xbase.lib.Pair) Spacing(org.eclipse.elk.core.math.Spacing) KPort(de.cau.cs.kieler.klighd.kgraph.KPort) KContainerRendering(de.cau.cs.kieler.klighd.krendering.KContainerRendering) KRendering(de.cau.cs.kieler.klighd.krendering.KRendering) Pair(org.eclipse.xtext.xbase.lib.Pair) KRectangle(de.cau.cs.kieler.klighd.krendering.KRectangle) ElkMargin(org.eclipse.elk.core.math.ElkMargin)

Example 2 with ElkMargin

use of org.eclipse.elk.core.math.ElkMargin 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 3 with ElkMargin

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

the class InteractiveExternalPortPositioner method findNorthSouthPortXCoordinate.

private Optional<Double> findNorthSouthPortXCoordinate(final LNode dummy) {
    // external port dummies must have exactly one port
    assert dummy.getPorts().size() == 1;
    LPort port = dummy.getPorts().get(0);
    if (!port.getOutgoingEdges().isEmpty() && !port.getIncomingEdges().isEmpty()) {
        throw new IllegalStateException("Interactive layout does not support " + "NORTH/SOUTH ports with incoming _and_ outgoing edges.");
    }
    if (!port.getOutgoingEdges().isEmpty()) {
        // find the minimum position
        double min = Double.POSITIVE_INFINITY;
        for (LEdge e : port.getOutgoingEdges()) {
            LNode n = e.getTarget().getNode();
            ElkMargin margins = n.getProperty(LayeredOptions.MARGINS);
            min = Math.min(min, n.getPosition().x - margins.left);
        }
        return Optional.of(min);
    }
    if (!port.getIncomingEdges().isEmpty()) {
        // find the maximum value
        double max = Double.NEGATIVE_INFINITY;
        for (LEdge e : port.getIncomingEdges()) {
            LNode n = e.getSource().getNode();
            ElkMargin margins = n.getProperty(LayeredOptions.MARGINS);
            max = Math.max(max, n.getPosition().x + n.getSize().x + margins.right);
        }
        return Optional.of(max);
    }
    // we should never reach here
    return Optional.absent();
}
Also used : LEdge(org.eclipse.elk.alg.layered.graph.LEdge) LPort(org.eclipse.elk.alg.layered.graph.LPort) LNode(org.eclipse.elk.alg.layered.graph.LNode) ElkMargin(org.eclipse.elk.core.math.ElkMargin)

Example 4 with ElkMargin

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

the class ElkGraphImporter method importGraph.

@Override
public Graph importGraph(final ElkNode inputGraph) {
    elkGraph = inputGraph;
    nodeMap = Maps.newHashMap();
    // calculate margins
    ElkGraphAdapter adapter = ElkGraphAdapters.adapt(elkGraph);
    NodeDimensionCalculation.calculateNodeMargins(adapter);
    // retrieve layout options
    String preferredRootID = elkGraph.getProperty(SporeCompactionOptions.PROCESSING_ORDER_PREFERRED_ROOT);
    SpanningTreeCostFunction costFunctionID = elkGraph.getProperty(SporeCompactionOptions.PROCESSING_ORDER_SPANNING_TREE_COST_FUNCTION);
    TreeConstructionStrategy treeConstructionStrategy = elkGraph.getProperty(SporeCompactionOptions.PROCESSING_ORDER_TREE_CONSTRUCTION);
    CompactionStrategy compactionStrategy = elkGraph.getProperty(SporeCompactionOptions.COMPACTION_COMPACTION_STRATEGY);
    RootSelection rootSelection = elkGraph.getProperty(SporeCompactionOptions.PROCESSING_ORDER_ROOT_SELECTION);
    spacingNodeNode = elkGraph.getProperty(SporeCompactionOptions.SPACING_NODE_NODE);
    ICostFunction costFunction = centerDistance;
    switch(costFunctionID) {
        case CENTER_DISTANCE:
            costFunction = centerDistance;
            break;
        case CIRCLE_UNDERLAP:
            costFunction = circleUnderlap;
            break;
        case RECTANGLE_UNDERLAP:
            costFunction = rectangleUnderlap;
            break;
        case INVERTED_OVERLAP:
            costFunction = invertedOverlap;
            break;
        case MINIMUM_ROOT_DISTANCE:
            costFunction = minimumRootDistance;
            break;
        default:
            throw new IllegalArgumentException("No implementation available for " + costFunctionID.toString());
    }
    // instantiate Graph
    graph = new Graph(costFunction, treeConstructionStrategy, compactionStrategy);
    graph.setProperty(InternalProperties.DEBUG_SVG, elkGraph.getProperty(SporeCompactionOptions.DEBUG_MODE));
    graph.orthogonalCompaction = elkGraph.getProperty(SporeCompactionOptions.COMPACTION_ORTHOGONAL);
    if (elkGraph.getChildren().isEmpty()) {
        // don't bother
        return graph;
    }
    // create Nodes representing the ElkNodes
    for (ElkNode elkNode : elkGraph.getChildren()) {
        double halfWidth = elkNode.getWidth() / 2;
        double halfHeight = elkNode.getHeight() / 2;
        KVector vertex = new KVector(elkNode.getX() + halfWidth, elkNode.getY() + halfHeight);
        // randomly shift identical points a tiny bit to make them unique
        while (nodeMap.containsKey(vertex)) {
            // SUPPRESS CHECKSTYLE NEXT 1 MagicNumber
            vertex.add((Math.random() - 0.5) * 0.001, (Math.random() - 0.5) * 0.001);
        // If two positions were identical, their corresponding edge in the spanning tree would be
        // of zero length, had no direction, and couldn't be scaled by anything.
        }
        ElkMargin margin = elkNode.getProperty(CoreOptions.MARGINS);
        Node node = new Node(vertex, new ElkRectangle(vertex.x - halfWidth - spacingNodeNode / 2 - margin.left, vertex.y - halfHeight - spacingNodeNode / 2 - margin.top, elkNode.getWidth() + spacingNodeNode + margin.getHorizontal(), elkNode.getHeight() + spacingNodeNode + margin.getVertical()));
        graph.vertices.add(node);
        nodeMap.put(vertex, Pair.of(node, elkNode));
    }
    // spanning tree root selection method
    switch(rootSelection) {
        case FIXED:
            if (preferredRootID == null) {
                // get first Node in list if no ID specified
                graph.preferredRoot = graph.vertices.get(0);
            } else {
                // find Node associated with the ElkNode containing the ID
                for (Node node : graph.vertices) {
                    String id = nodeMap.get(node.originalVertex).getSecond().getIdentifier();
                    if (id != null && id.equals(preferredRootID)) {
                        graph.preferredRoot = node;
                    }
                }
            }
            break;
        case CENTER_NODE:
            // find node that is most central in the drawing
            KVector center = new KVector(elkGraph.getWidth(), elkGraph.getHeight());
            // CHECKSTYLEOFF MagicNumber
            center.scale(0.5);
            center.add(elkGraph.getX(), elkGraph.getY());
            double closest = Double.POSITIVE_INFINITY;
            for (Node node : graph.vertices) {
                double distance = node.originalVertex.distance(center);
                if (distance < closest) {
                    closest = distance;
                    graph.preferredRoot = node;
                }
            }
            break;
        default:
            throw new IllegalArgumentException("No implementation available for " + rootSelection.toString());
    }
    return graph;
}
Also used : ICostFunction(org.eclipse.elk.alg.common.ICostFunction) SpanningTreeCostFunction(org.eclipse.elk.alg.spore.options.SpanningTreeCostFunction) CompactionStrategy(org.eclipse.elk.alg.spore.options.CompactionStrategy) ElkNode(org.eclipse.elk.graph.ElkNode) Node(org.eclipse.elk.alg.common.spore.Node) ElkNode(org.eclipse.elk.graph.ElkNode) ElkMargin(org.eclipse.elk.core.math.ElkMargin) RootSelection(org.eclipse.elk.alg.spore.options.RootSelection) Graph(org.eclipse.elk.alg.spore.graph.Graph) TreeConstructionStrategy(org.eclipse.elk.alg.spore.options.TreeConstructionStrategy) KVector(org.eclipse.elk.core.math.KVector) ElkRectangle(org.eclipse.elk.core.math.ElkRectangle) ElkGraphAdapter(org.eclipse.elk.core.util.adapters.ElkGraphAdapters.ElkGraphAdapter)

Example 5 with ElkMargin

use of org.eclipse.elk.core.math.ElkMargin 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)

Aggregations

ElkMargin (org.eclipse.elk.core.math.ElkMargin)13 KVector (org.eclipse.elk.core.math.KVector)5 LPort (org.eclipse.elk.alg.layered.graph.LPort)4 ElkPadding (org.eclipse.elk.core.math.ElkPadding)3 KPort (de.cau.cs.kieler.klighd.kgraph.KPort)2 LEdge (org.eclipse.elk.alg.layered.graph.LEdge)2 LNode (org.eclipse.elk.alg.layered.graph.LNode)2 ElkRectangle (org.eclipse.elk.core.math.ElkRectangle)2 IndividualSpacings (org.eclipse.elk.core.util.IndividualSpacings)2 ElkNode (org.eclipse.elk.graph.ElkNode)2 Function (com.google.common.base.Function)1 Optional (com.google.common.base.Optional)1 ImmutableList (com.google.common.collect.ImmutableList)1 Iterables (com.google.common.collect.Iterables)1 Iterators (com.google.common.collect.Iterators)1 Sets (com.google.common.collect.Sets)1 Inject (com.google.inject.Inject)1 SynthesisOption (de.cau.cs.kieler.klighd.SynthesisOption)1 KEdge (de.cau.cs.kieler.klighd.kgraph.KEdge)1 KNode (de.cau.cs.kieler.klighd.kgraph.KNode)1