Search in sources :

Example 96 with LEdge

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

the class InvertedPortProcessor method createWestPortSideDummies.

/**
 * Creates the necessary dummy nodes for an output port on the west side of a node, provided
 * that the edge connects two different nodes.
 *
 * @param layeredGraph
 *            the layered graph
 * @param westwardPort
 *            the offending port.
 * @param edge
 *            the edge connected to the port.
 * @param layerNodeList
 *            list of unassigned nodes belonging to the layer of the node the port belongs to.
 *            The new dummy node is added to this list and must be assigned to the layer later.
 */
private void createWestPortSideDummies(final LGraph layeredGraph, final LPort westwardPort, final LEdge edge, final List<LNode> layerNodeList) {
    assert edge.getSource() == westwardPort;
    // Ignore self loops
    if (edge.getTarget().getNode() == westwardPort.getNode()) {
        return;
    }
    // Dummy node in the same layer
    LNode dummy = new LNode(layeredGraph);
    dummy.setType(NodeType.LONG_EDGE);
    dummy.setProperty(InternalProperties.ORIGIN, edge);
    dummy.setProperty(LayeredOptions.PORT_CONSTRAINTS, PortConstraints.FIXED_POS);
    layerNodeList.add(dummy);
    LPort dummyInput = new LPort();
    dummyInput.setNode(dummy);
    dummyInput.setSide(PortSide.WEST);
    LPort dummyOutput = new LPort();
    dummyOutput.setNode(dummy);
    dummyOutput.setSide(PortSide.EAST);
    // Reroute the original edge
    LPort originalTarget = edge.getTarget();
    edge.setTarget(dummyInput);
    // Connect the dummy with the original port
    LEdge dummyEdge = new LEdge();
    dummyEdge.copyProperties(edge);
    dummyEdge.setProperty(LayeredOptions.JUNCTION_POINTS, null);
    dummyEdge.setSource(dummyOutput);
    dummyEdge.setTarget(originalTarget);
    // Move any head labels over to the new dummy edge
    ListIterator<LLabel> labelIterator = edge.getLabels().listIterator();
    while (labelIterator.hasNext()) {
        LLabel label = labelIterator.next();
        if (label.getProperty(LayeredOptions.EDGE_LABELS_PLACEMENT) == EdgeLabelPlacement.HEAD) {
            // Remember which edge the label belonged to originally
            assert !label.hasProperty(InternalProperties.END_LABEL_EDGE);
            label.setProperty(InternalProperties.END_LABEL_EDGE, edge);
            labelIterator.remove();
            dummyEdge.getLabels().add(label);
        }
    }
    // Set LONG_EDGE_SOURCE and LONG_EDGE_TARGET properties on the LONG_EDGE dummy
    setLongEdgeSourceAndTarget(dummy, dummyInput, dummyOutput, westwardPort);
}
Also used : LLabel(org.eclipse.elk.alg.layered.graph.LLabel) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) LPort(org.eclipse.elk.alg.layered.graph.LPort) LNode(org.eclipse.elk.alg.layered.graph.LNode)

Example 97 with LEdge

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

the class LabelDummyInserter method process.

@Override
public void process(final LGraph layeredGraph, final IElkProgressMonitor monitor) {
    monitor.begin("Label dummy insertions", 1);
    // We cannot add the nodes to the graph while we're iterating over it, so remember the dummy nodes we create
    List<LNode> newDummyNodes = Lists.newArrayList();
    double edgeLabelSpacing = layeredGraph.getProperty(LayeredOptions.SPACING_EDGE_LABEL);
    double labelLabelSpacing = layeredGraph.getProperty(LayeredOptions.SPACING_LABEL_LABEL);
    Direction layoutDirection = layeredGraph.getProperty(LayeredOptions.DIRECTION);
    for (LNode node : layeredGraph.getLayerlessNodes()) {
        for (LEdge edge : node.getOutgoingEdges()) {
            if (edgeNeedsToBeProcessed(edge)) {
                double thickness = retrieveThickness(edge);
                // Create dummy node and remember represented labels (to be filled below)
                List<LLabel> representedLabels = Lists.newArrayListWithCapacity(edge.getLabels().size());
                LNode dummyNode = createLabelDummy(layeredGraph, edge, thickness, representedLabels);
                newDummyNodes.add(dummyNode);
                // Determine the size of the dummy node and move labels over to it
                KVector dummySize = dummyNode.getSize();
                ListIterator<LLabel> iterator = edge.getLabels().listIterator();
                while (iterator.hasNext()) {
                    LLabel label = iterator.next();
                    if (label.getProperty(LayeredOptions.EDGE_LABELS_PLACEMENT) == EdgeLabelPlacement.CENTER) {
                        // The way we stack labels depends on the layout direction
                        if (layoutDirection.isVertical()) {
                            dummySize.x += label.getSize().x + labelLabelSpacing;
                            dummySize.y = Math.max(dummySize.y, label.getSize().y);
                        } else {
                            dummySize.x = Math.max(dummySize.x, label.getSize().x);
                            dummySize.y += label.getSize().y + labelLabelSpacing;
                        }
                        // Move the label over to the dummy node's REPRESENTED_LABELS property
                        representedLabels.add(label);
                        iterator.remove();
                    }
                }
                // edge-label spacing yet
                if (layoutDirection.isVertical()) {
                    dummySize.x -= labelLabelSpacing;
                    dummySize.y += edgeLabelSpacing + thickness;
                } else {
                    dummySize.y += edgeLabelSpacing - labelLabelSpacing + thickness;
                }
            }
        }
    }
    // Add created dummies to graph
    layeredGraph.getLayerlessNodes().addAll(newDummyNodes);
    monitor.done();
}
Also used : LLabel(org.eclipse.elk.alg.layered.graph.LLabel) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) LNode(org.eclipse.elk.alg.layered.graph.LNode) KVector(org.eclipse.elk.core.math.KVector) Direction(org.eclipse.elk.core.options.Direction)

Example 98 with LEdge

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

the class LabelDummyRemover method process.

@Override
public void process(final LGraph layeredGraph, final IElkProgressMonitor monitor) {
    monitor.begin("Label dummy removal", 1);
    double edgeLabelSpacing = layeredGraph.getProperty(LayeredOptions.SPACING_EDGE_LABEL);
    double labelLabelSpacing = layeredGraph.getProperty(LayeredOptions.SPACING_LABEL_LABEL);
    Direction layoutDirection = layeredGraph.getProperty(LayeredOptions.DIRECTION);
    for (Layer layer : layeredGraph.getLayers()) {
        // An iterator is necessary for traversing nodes, since dummy nodes might be removed
        ListIterator<LNode> nodeIterator = layer.getNodes().listIterator();
        while (nodeIterator.hasNext()) {
            LNode node = nodeIterator.next();
            if (node.getType() == NodeType.LABEL) {
                // First, place labels on position of dummy node
                LEdge originEdge = (LEdge) node.getProperty(InternalProperties.ORIGIN);
                double thickness = originEdge.getProperty(LayeredOptions.EDGE_THICKNESS).doubleValue();
                boolean labelsBelowEdge = node.getProperty(InternalProperties.LABEL_SIDE) == LabelSide.BELOW;
                KVector currLabelPos = new KVector(node.getPosition());
                // position down a bit to respect the label spacing
                if (labelsBelowEdge) {
                    currLabelPos.y += thickness + edgeLabelSpacing;
                }
                // Calculate the space available for the placement of labels
                KVector labelSpace = new KVector(node.getSize().x, node.getSize().y - thickness - edgeLabelSpacing);
                // Place labels
                List<LLabel> representedLabels = node.getProperty(InternalProperties.REPRESENTED_LABELS);
                if (layoutDirection.isVertical()) {
                    placeLabelsForVerticalLayout(representedLabels, currLabelPos, labelLabelSpacing, labelSpace, labelsBelowEdge, layoutDirection);
                } else {
                    placeLabelsForHorizontalLayout(representedLabels, currLabelPos, labelLabelSpacing, labelSpace);
                }
                // Add represented labels back to the original edge
                originEdge.getLabels().addAll(representedLabels);
                // Whether we need to add unnecessary bend points around the label dummy depends on the edge
                // router. For orthogonal edge routing, they are not necessary. For splines, they may even be
                // harmful. For polylines, they are necessary to keep the routes edges take close to their labels
                LongEdgeJoiner.joinAt(node, layeredGraph.getProperty(LayeredOptions.EDGE_ROUTING) == EdgeRouting.POLYLINE);
                // Remove the node
                nodeIterator.remove();
            }
        }
    }
    monitor.done();
}
Also used : LLabel(org.eclipse.elk.alg.layered.graph.LLabel) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) LNode(org.eclipse.elk.alg.layered.graph.LNode) KVector(org.eclipse.elk.core.math.KVector) Direction(org.eclipse.elk.core.options.Direction) Layer(org.eclipse.elk.alg.layered.graph.Layer)

Example 99 with LEdge

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

the class LongEdgeJoiner method joinAt.

/**
 * Joins the edges connected to the given dummy node. The dummy node is then ready to be removed
 * from the graph.
 *
 * @param longEdgeDummy
 *            the dummy node whose incident edges to join.
 * @param addUnnecessaryBendpoints
 *            {@code true} if a bend point should be added to the edges at the position of the
 *            dummy node.
 */
public static void joinAt(final LNode longEdgeDummy, final boolean addUnnecessaryBendpoints) {
    // Get the input and output port (of which we assume to have only one, on the western side and
    // on the eastern side, respectively); the incoming edges are retained, and the outgoing edges
    // are discarded
    List<LEdge> inputPortEdges = longEdgeDummy.getPorts(PortSide.WEST).iterator().next().getIncomingEdges();
    List<LEdge> outputPortEdges = longEdgeDummy.getPorts(PortSide.EAST).iterator().next().getOutgoingEdges();
    int edgeCount = inputPortEdges.size();
    // If we are to add unnecessary bend points, we need to know where. We take the position of the
    // first port we find. (It doesn't really matter which port we're using, so we opt to keep it
    // surprisingly simple.)
    KVector unnecessaryBendpoint = longEdgeDummy.getPorts().get(0).getAbsoluteAnchor();
    // HyperedgeDummyMerger
    while (edgeCount-- > 0) {
        // Get the two edges
        LEdge survivingEdge = inputPortEdges.get(0);
        LEdge droppedEdge = outputPortEdges.get(0);
        // The surviving edge's target needs to be set to the old target of the dropped edge.
        // However, this doesn't replace the dropped edge with the surviving edge in the list of
        // incoming edges of the (new) target port, but instead appends the surviving edge. That in
        // turn messes with the implicit assumption that edges with the same index on input and
        // output ports of long edge dummies belong to each other. Thus, we need to ensure that the
        // surviving edge is at the correct index in the list of incoming edges. Hence the
        // complicated code below. (KIPRA-1670)
        List<LEdge> targetIncomingEdges = droppedEdge.getTarget().getIncomingEdges();
        int droppedEdgeListIndex = targetIncomingEdges.indexOf(droppedEdge);
        survivingEdge.setTargetAndInsertAtIndex(droppedEdge.getTarget(), droppedEdgeListIndex);
        // Remove the dropped edge from the graph
        droppedEdge.setSource(null);
        droppedEdge.setTarget(null);
        // Join their bend points and add possibly an unnecessary one
        KVectorChain survivingBendPoints = survivingEdge.getBendPoints();
        if (addUnnecessaryBendpoints) {
            survivingBendPoints.add(new KVector(unnecessaryBendpoint));
        }
        for (KVector bendPoint : droppedEdge.getBendPoints()) {
            survivingBendPoints.add(new KVector(bendPoint));
        }
        // Join their labels
        List<LLabel> survivingLabels = survivingEdge.getLabels();
        for (LLabel label : droppedEdge.getLabels()) {
            survivingLabels.add(label);
        }
        // Join their junction points
        KVectorChain survivingJunctionPoints = survivingEdge.getProperty(LayeredOptions.JUNCTION_POINTS);
        KVectorChain droppedJunctionsPoints = droppedEdge.getProperty(LayeredOptions.JUNCTION_POINTS);
        if (droppedJunctionsPoints != null) {
            if (survivingJunctionPoints == null) {
                survivingJunctionPoints = new KVectorChain();
                survivingEdge.setProperty(LayeredOptions.JUNCTION_POINTS, survivingJunctionPoints);
            }
            for (KVector jp : droppedJunctionsPoints) {
                survivingJunctionPoints.add(new KVector(jp));
            }
        }
    }
}
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) KVector(org.eclipse.elk.core.math.KVector)

Example 100 with LEdge

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

the class LongEdgeSplitter method process.

@Override
public void process(final LGraph layeredGraph, final IElkProgressMonitor monitor) {
    monitor.begin("Edge splitting", 1);
    if (layeredGraph.getLayers().size() <= 2) {
        monitor.done();
        return;
    }
    // Iterate through the layers
    ListIterator<Layer> layerIter = layeredGraph.getLayers().listIterator();
    Layer nextLayer = layerIter.next();
    while (layerIter.hasNext()) {
        Layer layer = nextLayer;
        nextLayer = layerIter.next();
        // Iterate through the nodes
        for (LNode node : layer) {
            // Iterate through the outgoing edges
            for (LPort port : node.getPorts()) {
                // Iterate through the edges
                for (LEdge edge : port.getOutgoingEdges()) {
                    LPort targetPort = edge.getTarget();
                    Layer targetLayer = targetPort.getNode().getLayer();
                    // If the edge doesn't go to the current or next layer, split it
                    if (targetLayer != layer && targetLayer != nextLayer) {
                        // If there is no next layer, something is wrong
                        assert layerIter.hasNext();
                        // Split the edge
                        splitEdge(edge, createDummyNode(layeredGraph, nextLayer, edge));
                    }
                }
            }
        }
    }
    monitor.done();
}
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) 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