Search in sources :

Example 51 with LEdge

use of org.eclipse.elk.alg.layered.graph.LEdge in project elk by eclipse.

the class AbstractGraphPlacer method moveGraph.

/**
 * Move the source graph into the destination graph using a specified offset. This method should
 * only be called once per graph, since it also applies the graph's set offset in addition to the
 * one given in the methods of this argument.
 *
 * @param destGraph the destination graph.
 * @param sourceGraph the source graph.
 * @param offsetx x coordinate offset.
 * @param offsety y coordinate offset.
 */
protected void moveGraph(final LGraph destGraph, final LGraph sourceGraph, final double offsetx, final double offsety) {
    KVector graphOffset = sourceGraph.getOffset().add(offsetx, offsety);
    for (LNode node : sourceGraph.getLayerlessNodes()) {
        node.getPosition().add(graphOffset);
        for (LPort port : node.getPorts()) {
            for (LEdge edge : port.getOutgoingEdges()) {
                edge.getBendPoints().offset(graphOffset);
                KVectorChain junctionPoints = edge.getProperty(LayeredOptions.JUNCTION_POINTS);
                if (junctionPoints != null) {
                    junctionPoints.offset(graphOffset);
                }
                for (LLabel label : edge.getLabels()) {
                    label.getPosition().add(graphOffset);
                }
            }
        }
        destGraph.getLayerlessNodes().add(node);
        node.setGraph(destGraph);
    }
}
Also used : LLabel(org.eclipse.elk.alg.layered.graph.LLabel) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) KVectorChain(org.eclipse.elk.core.math.KVectorChain) LPort(org.eclipse.elk.alg.layered.graph.LPort) LNode(org.eclipse.elk.alg.layered.graph.LNode) KVector(org.eclipse.elk.core.math.KVector)

Example 52 with LEdge

use of org.eclipse.elk.alg.layered.graph.LEdge in project elk by eclipse.

the class EndLabelSorter method createLabelGroups.

/**
 * Creates a list of {@link LabelGroup}s that group labels from the same edge.
 */
private List<LabelGroup> createLabelGroups(final LabelCell portLabelCell) {
    Map<LEdge, LabelGroup> edgeToGroupMap = new HashMap<>();
    // Make sure every label is contained in a label group
    for (LabelAdapter<?> label : portLabelCell.getLabels()) {
        LEdge edge = label.getProperty(InternalProperties.END_LABEL_EDGE);
        // label didn't have an END_LABEL_EDGE property set
        if (!edgeToGroupMap.containsKey(edge)) {
            edgeToGroupMap.put(edge, new LabelGroup(edge));
        }
        edgeToGroupMap.get(edge).labels.add(label);
    }
    return new ArrayList<>(edgeToGroupMap.values());
}
Also used : HashMap(java.util.HashMap) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) ArrayList(java.util.ArrayList)

Example 53 with LEdge

use of org.eclipse.elk.alg.layered.graph.LEdge in project elk by eclipse.

the class FinalSplineBendpointsCalculator method calculateControlPoints.

/**
 * The method dispatches the calculation of NUB control points for the passed {@code segment} to the
 * {@code calculateControlPoints*(..)} methods based on the following criteria.
 * <ul>
 * <li>the desired {@link SplineRoutingMode}</li>
 * <li>if the segment is straight</li>
 * <li>if the segment represents an in-layer edge due to inverted ports</li>
 * <li>if the segment represents a hyperedge</li>
 * </ul>
 */
private void calculateControlPoints(final SplineSegment segment) {
    // with hyperedges it can happen that this method is called multiple times for the same segment
    if (segment.handled) {
        return;
    }
    segment.handled = true;
    for (final LEdge edge : segment.edges) {
        if (segment.isStraight && !segment.isHyperEdge()) {
            calculateControlPointsStraight(segment);
            continue;
        }
        // Remember that the edge itself is not necessarily valid at this point
        // (it may have been remove by the long edge joiner, for instance)
        EdgeInformation ei = segment.edgeInformation.get(edge);
        // inverted ports are handled in the same way for
        if (ei.invertedLeft || ei.invertedRight) {
            calculateControlPointsInvertedEdge(edge, segment);
            continue;
        }
        // to compute sloppy control points at least one of the
        // two nodes connected by the segment must be a 'normal' node,
        // and in case horizontal compaction is active the predicate implemented
        // by the 'segmentAllowsSloppyRouting(..)' method must be true
        // for hyperedges sloppy routing is not possible
        boolean sloppy = splineRoutingMode == SplineRoutingMode.SLOPPY && (ei.normalSourceNode || ei.normalTargetNode) && segmentAllowsSloppyRouting(segment) && !segment.isHyperEdge();
        if (sloppy) {
            calculateControlPointsSloppy(edge, segment);
        } else {
            calculateControlPointsConservative(edge, segment);
        }
    }
    if (segment.inverseOrder) {
        segment.edges.forEach(e -> Collections.reverse(e.getBendPoints()));
    }
}
Also used : LEdge(org.eclipse.elk.alg.layered.graph.LEdge) EdgeInformation(org.eclipse.elk.alg.layered.p5edges.splines.SplineSegment.EdgeInformation)

Example 54 with LEdge

use of org.eclipse.elk.alg.layered.graph.LEdge in project elk by eclipse.

the class BKAligner method insideBlockShift.

/**
 * This phase moves the nodes inside a block, ensuring that all edges inside a block can be drawn
 * as straight lines. It is not included in the original algorithm and adds port and node size
 * handling.
 *
 * @param bal One of the four layouts which shall be used in this step
 */
public void insideBlockShift(final BKAlignedLayout bal) {
    Map<LNode, List<LNode>> blocks = getBlocks(bal);
    for (LNode root : blocks.keySet()) {
        // For each block, we place the top left corner of the root node at coordinate (0,0). We
        // then calculate the space required above the top left corner (due to other nodes placed
        // above and to top margins of nodes, including the root node) and the space required below
        // the top left corner. The sum of both becomes the block size, and the y coordinate of each
        // node relative to the block's top border becomes the inner shift of that node.
        double spaceAbove = 0.0;
        double spaceBelow = 0.0;
        // Reserve space for the root node
        spaceAbove = root.getMargin().top;
        spaceBelow = root.getSize().y + root.getMargin().bottom;
        bal.innerShift[root.id] = 0.0;
        // Iterate over all other nodes of the block
        LNode current = root;
        LNode next;
        while ((next = bal.align[current.id]) != root) {
            // Find the edge between the current and the next node
            LEdge edge = getEdge(current, next);
            // Calculate the y coordinate difference between the two nodes required to straighten
            // the edge
            double portPosDiff = 0.0;
            if (bal.hdir == HDirection.LEFT) {
                portPosDiff = edge.getTarget().getPosition().y + edge.getTarget().getAnchor().y - edge.getSource().getPosition().y - edge.getSource().getAnchor().y;
            } else {
                portPosDiff = edge.getSource().getPosition().y + edge.getSource().getAnchor().y - edge.getTarget().getPosition().y - edge.getTarget().getAnchor().y;
            }
            // The current node already has an inner shift value that we need to use as the basis
            // to calculate the next node's inner shift
            double nextInnerShift = bal.innerShift[current.id] + portPosDiff;
            bal.innerShift[next.id] = nextInnerShift;
            // Update the space required above and below the root node's top left corner
            spaceAbove = Math.max(spaceAbove, next.getMargin().top - nextInnerShift);
            spaceBelow = Math.max(spaceBelow, nextInnerShift + next.getSize().y + next.getMargin().bottom);
            // The next node is the current node in the next iteration
            current = next;
        }
        // Adjust each node's inner shift by the space required above the root node's top left
        // corner (which the inner shifts are relative to at the moment)
        current = root;
        do {
            bal.innerShift[current.id] = bal.innerShift[current.id] + spaceAbove;
            current = bal.align[current.id];
        } while (current != root);
        // Remember the block size
        bal.blockSize[root.id] = spaceAbove + spaceBelow;
    }
}
Also used : LEdge(org.eclipse.elk.alg.layered.graph.LEdge) LNode(org.eclipse.elk.alg.layered.graph.LNode) List(java.util.List)

Example 55 with LEdge

use of org.eclipse.elk.alg.layered.graph.LEdge in project elk by eclipse.

the class BKNodePlacer method markConflicts.

/**
 * This phase of the node placer marks all type 1 and type 2 conflicts.
 *
 * <p>The conflict types base on the distinction of inner segments and non-inner segments of edges.
 * A inner segment is present if an edge is drawn between two dummy nodes and thus is part of
 * a long edge. A non-inner segment is present if one of the connected nodes is not a dummy
 * node.</p>
 *
 * <p>Type 0 conflicts occur if two non-inner segments cross each other. Type 1 conflicts happen
 * when a non-inner segment and a inner segment cross. Type 2 conflicts are present if two
 * inner segments cross.</p>
 *
 * <p>The markers are later used to solve conflicts in favor of long edges. In case of type 2
 * conflicts, the marker favors the earlier node in layout order.</p>
 *
 * @param layeredGraph The layered graph to be layouted
 */
private void markConflicts(final LGraph layeredGraph) {
    int numberOfLayers = layeredGraph.getLayers().size();
    // Check if there are enough layers to detect conflicts
    if (numberOfLayers < MIN_LAYERS_FOR_CONFLICTS) {
        return;
    }
    // We'll need the number of nodes in the different layers quite often in this method, so save
    // them up front
    int[] layerSize = new int[numberOfLayers];
    int layerIndex = 0;
    for (Layer layer : layeredGraph.getLayers()) {
        layerSize[layerIndex++] = layer.getNodes().size();
    }
    // The following call succeeds since there are at least 3 layers in the graph
    Iterator<Layer> layerIterator = layeredGraph.getLayers().listIterator(2);
    for (int i = 1; i < numberOfLayers - 1; i++) {
        // The variable naming here follows the notation of the corresponding paper
        // Normally, underscores are not allowed in local variable names, but since there
        // is no way of properly writing indices beside underscores, Checkstyle will be
        // disabled here and in future methods containing indexed variables
        // CHECKSTYLEOFF Local Variable Names
        Layer currentLayer = layerIterator.next();
        Iterator<LNode> nodeIterator = currentLayer.getNodes().iterator();
        int k_0 = 0;
        int l = 0;
        for (int l_1 = 0; l_1 < layerSize[i + 1]; l_1++) {
            // In the paper, l and i are indices for the layer and the position in the layer
            // currentLayer.getNodes().get(l_1);
            LNode v_l_i = nodeIterator.next();
            if (l_1 == ((layerSize[i + 1]) - 1) || incidentToInnerSegment(v_l_i, i + 1, i)) {
                int k_1 = layerSize[i] - 1;
                if (incidentToInnerSegment(v_l_i, i + 1, i)) {
                    k_1 = ni.nodeIndex[ni.leftNeighbors.get(v_l_i.id).get(0).getFirst().id];
                }
                while (l <= l_1) {
                    LNode v_l = currentLayer.getNodes().get(l);
                    if (!incidentToInnerSegment(v_l, i + 1, i)) {
                        for (Pair<LNode, LEdge> upperNeighbor : ni.leftNeighbors.get(v_l.id)) {
                            int k = ni.nodeIndex[upperNeighbor.getFirst().id];
                            if (k < k_0 || k > k_1) {
                                // Marked edge can't return null here, because the upper neighbor
                                // relationship between v_l and upperNeighbor enforces the existence
                                // of at least one edge between the two nodes
                                markedEdges.add(upperNeighbor.getSecond());
                            }
                        }
                    }
                    l++;
                }
                k_0 = k_1;
            }
        }
    // CHECKSTYLEON Local Variable Names
    }
}
Also used : LEdge(org.eclipse.elk.alg.layered.graph.LEdge) LNode(org.eclipse.elk.alg.layered.graph.LNode) Layer(org.eclipse.elk.alg.layered.graph.Layer)

Aggregations

LEdge (org.eclipse.elk.alg.layered.graph.LEdge)148 LNode (org.eclipse.elk.alg.layered.graph.LNode)107 LPort (org.eclipse.elk.alg.layered.graph.LPort)80 Layer (org.eclipse.elk.alg.layered.graph.Layer)41 KVector (org.eclipse.elk.core.math.KVector)34 KVectorChain (org.eclipse.elk.core.math.KVectorChain)20 LLabel (org.eclipse.elk.alg.layered.graph.LLabel)17 LGraph (org.eclipse.elk.alg.layered.graph.LGraph)16 PortSide (org.eclipse.elk.core.options.PortSide)11 ArrayList (java.util.ArrayList)9 List (java.util.List)9 InternalProperties (org.eclipse.elk.alg.layered.options.InternalProperties)8 Set (java.util.Set)7 LayeredOptions (org.eclipse.elk.alg.layered.options.LayeredOptions)7 Map (java.util.Map)6 IElkProgressMonitor (org.eclipse.elk.core.util.IElkProgressMonitor)6 Lists (com.google.common.collect.Lists)5 Iterator (java.util.Iterator)5 ElkRectangle (org.eclipse.elk.core.math.ElkRectangle)5 Pair (org.eclipse.elk.core.util.Pair)5