Search in sources :

Example 1 with LEdge

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

the class HierarchicalPortOrthogonalEdgeRouter method connectNodeToDummy.

/**
 * Adds a port to the given node and connects that to the given dummy node.
 *
 * @param node the node to connect to the dummy.
 * @param dummy the external port dummy to connect the node to.
 */
private void connectNodeToDummy(final LGraph layeredGraph, final LNode node, final LNode dummy) {
    // First, add a port to the node. The port side depends on the node's hierarchical port side
    LPort outPort = new LPort();
    outPort.setNode(node);
    PortSide extPortSide = node.getProperty(InternalProperties.EXT_PORT_SIDE);
    outPort.setSide(extPortSide);
    // Find the dummy node's port
    LPort inPort = dummy.getPorts().get(0);
    // Connect the two nodes
    LEdge edge = new LEdge();
    edge.setSource(outPort);
    edge.setTarget(inPort);
}
Also used : LEdge(org.eclipse.elk.alg.layered.graph.LEdge) LPort(org.eclipse.elk.alg.layered.graph.LPort) PortSide(org.eclipse.elk.core.options.PortSide)

Example 2 with LEdge

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

the class HierarchicalPortOrthogonalEdgeRouter method correctSlantedEdgeSegments.

/**
 * Goes over the eastern and western hierarchical dummy nodes in the given layer and checks
 * whether their incident edges have slanted segments. Note that only the first and last
 * segment needs to be checked.
 *
 * @param layer the layer.
 */
private void correctSlantedEdgeSegments(final Layer layer) {
    for (LNode node : layer) {
        if (node.getType() != NodeType.EXTERNAL_PORT) {
            // We're only looking for hierarchical port dummies
            continue;
        }
        PortSide extPortSide = node.getProperty(InternalProperties.EXT_PORT_SIDE);
        if (extPortSide == PortSide.EAST || extPortSide == PortSide.WEST) {
            for (LEdge edge : node.getConnectedEdges()) {
                KVectorChain bendPoints = edge.getBendPoints();
                if (bendPoints.isEmpty()) {
                    // TODO: The edge has no bend points yet, but may still be slanted. Handle that!
                    continue;
                }
                // Correct a slanted segment connected to the source port if it belongs to our node
                LPort sourcePort = edge.getSource();
                if (sourcePort.getNode() == node) {
                    KVector firstBendPoint = bendPoints.getFirst();
                    firstBendPoint.y = sourcePort.getAbsoluteAnchor().y;
                }
                // Correct a slanted segment connected to the target port if it belongs to our node
                LPort targetPort = edge.getTarget();
                if (targetPort.getNode() == node) {
                    KVector lastBendPoint = bendPoints.getLast();
                    lastBendPoint.y = targetPort.getAbsoluteAnchor().y;
                }
            }
        }
    }
}
Also used : 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) PortSide(org.eclipse.elk.core.options.PortSide) KVector(org.eclipse.elk.core.math.KVector)

Example 3 with LEdge

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

the class HierarchicalPortOrthogonalEdgeRouter method routeEdges.

// /////////////////////////////////////////////////////////////////////////////
// STEP 3: EDGE ROUTING
/**
 * Routes nothern and southern hierarchical port edges and ajusts the graph's height and
 * offsets accordingly.
 *
 * @param monitor the progress monitor we're using.
 * @param layeredGraph the layered graph.
 * @param northSouthDummies the collection of restored northern and southern port dummies.
 */
private void routeEdges(final IElkProgressMonitor monitor, final LGraph layeredGraph, final Iterable<LNode> northSouthDummies) {
    // Prepare south and target layers for northern and southern routing
    Set<LNode> northernSourceLayer = Sets.newLinkedHashSet();
    Set<LNode> northernTargetLayer = Sets.newLinkedHashSet();
    Set<LNode> southernSourceLayer = Sets.newLinkedHashSet();
    Set<LNode> southernTargetLayer = Sets.newLinkedHashSet();
    // Find some routing parameters
    double nodeSpacing = layeredGraph.getProperty(LayeredOptions.SPACING_NODE_NODE).doubleValue();
    double edgeSpacing = layeredGraph.getProperty(LayeredOptions.SPACING_EDGE_EDGE).doubleValue();
    // connected to
    for (LNode hierarchicalPortDummy : northSouthDummies) {
        PortSide portSide = hierarchicalPortDummy.getProperty(InternalProperties.EXT_PORT_SIDE);
        if (portSide == PortSide.NORTH) {
            northernTargetLayer.add(hierarchicalPortDummy);
            for (LEdge edge : hierarchicalPortDummy.getIncomingEdges()) {
                northernSourceLayer.add(edge.getSource().getNode());
            }
        } else if (portSide == PortSide.SOUTH) {
            southernTargetLayer.add(hierarchicalPortDummy);
            for (LEdge edge : hierarchicalPortDummy.getIncomingEdges()) {
                southernSourceLayer.add(edge.getSource().getNode());
            }
        }
    }
    // Northern routing
    if (!northernSourceLayer.isEmpty()) {
        // Route the edges using a south-to-north orthogonal edge router
        OrthogonalRoutingGenerator routingGenerator = new OrthogonalRoutingGenerator(RoutingDirection.SOUTH_TO_NORTH, edgeSpacing, "extnorth");
        int slots = routingGenerator.routeEdges(monitor, layeredGraph, northernSourceLayer, 0, northernTargetLayer, -nodeSpacing - layeredGraph.getOffset().y);
        // If anything was routed, adjust the graph's offset and height
        if (slots > 0) {
            northernExtPortEdgeRoutingHeight = nodeSpacing + (slots - 1) * edgeSpacing;
            layeredGraph.getOffset().y += northernExtPortEdgeRoutingHeight;
            layeredGraph.getSize().y += northernExtPortEdgeRoutingHeight;
        }
    }
    // Southern routing
    if (!southernSourceLayer.isEmpty()) {
        // Route the edges using a north-to-south orthogonal edge router
        OrthogonalRoutingGenerator routingGenerator = new OrthogonalRoutingGenerator(RoutingDirection.NORTH_TO_SOUTH, edgeSpacing, "extsouth");
        int slots = routingGenerator.routeEdges(monitor, layeredGraph, southernSourceLayer, 0, southernTargetLayer, layeredGraph.getSize().y + nodeSpacing - layeredGraph.getOffset().y);
        // Adjust graph height.
        if (slots > 0) {
            layeredGraph.getSize().y += nodeSpacing + (slots - 1) * edgeSpacing;
        }
    }
}
Also used : LEdge(org.eclipse.elk.alg.layered.graph.LEdge) LNode(org.eclipse.elk.alg.layered.graph.LNode) PortSide(org.eclipse.elk.core.options.PortSide) OrthogonalRoutingGenerator(org.eclipse.elk.alg.layered.p5edges.orthogonal.OrthogonalRoutingGenerator) SizeConstraint(org.eclipse.elk.core.options.SizeConstraint)

Example 4 with LEdge

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

the class HierarchicalPortOrthogonalEdgeRouter method removeTemporaryNorthSouthDummies.

// /////////////////////////////////////////////////////////////////////////////
// STEP 4: REMOVE TEMPORARY DUMMIES
/**
 * Removes the temporary hierarchical port dummies, reconnecting their incoming and outgoing
 * edges to the original dummies and setting the appropriate bend points.
 *
 * @param layeredGraph the layered graph.
 */
private void removeTemporaryNorthSouthDummies(final LGraph layeredGraph) {
    List<LNode> nodesToRemove = Lists.newArrayList();
    // Iterate through all layers
    for (Layer layer : layeredGraph) {
        for (LNode node : layer) {
            if (node.getType() != NodeType.EXTERNAL_PORT) {
                // We're only looking for hierarchical port dummies
                continue;
            }
            if (!node.hasProperty(InternalProperties.EXT_PORT_REPLACED_DUMMY)) {
                // We're only looking for temporary north / south dummies
                continue;
            }
            // There must be a port where all edges come in, another port where edges go out, and
            // a port with an edge connecting node and origin (that one was added previously by
            // this processor)
            LPort nodeInPort = null;
            LPort nodeOutPort = null;
            LPort nodeOriginPort = null;
            for (LPort port : node.getPorts()) {
                switch(port.getSide()) {
                    case WEST:
                        nodeInPort = port;
                        break;
                    case EAST:
                        nodeOutPort = port;
                        break;
                    default:
                        nodeOriginPort = port;
                }
            }
            // Find the edge connecting this dummy to the original external port dummy that we
            // restored just a while ago
            LEdge nodeToOriginEdge = nodeOriginPort.getOutgoingEdges().get(0);
            // Compute bend points for incoming edges
            KVectorChain incomingEdgeBendPoints = new KVectorChain(nodeToOriginEdge.getBendPoints());
            KVector firstBendPoint = new KVector(nodeOriginPort.getPosition());
            firstBendPoint.add(node.getPosition());
            incomingEdgeBendPoints.add(0, firstBendPoint);
            // Compute bend points for outgoing edges
            KVectorChain outgoingEdgeBendPoints = KVectorChain.reverse(nodeToOriginEdge.getBendPoints());
            KVector lastBendPoint = new KVector(nodeOriginPort.getPosition());
            lastBendPoint.add(node.getPosition());
            outgoingEdgeBendPoints.add(lastBendPoint);
            // Retrieve the original hierarchical port dummy
            LNode replacedDummy = (LNode) node.getProperty(InternalProperties.EXT_PORT_REPLACED_DUMMY);
            LPort replacedDummyPort = replacedDummy.getPorts().get(0);
            // Reroute all the input port's edges
            LEdge[] edges = nodeInPort.getIncomingEdges().toArray(new LEdge[0]);
            for (LEdge edge : edges) {
                edge.setTarget(replacedDummyPort);
                edge.getBendPoints().addAllAsCopies(edge.getBendPoints().size(), incomingEdgeBendPoints);
            }
            // Reroute all the output port's edges
            edges = LGraphUtil.toEdgeArray(nodeOutPort.getOutgoingEdges());
            for (LEdge edge : edges) {
                edge.setSource(replacedDummyPort);
                edge.getBendPoints().addAllAsCopies(0, outgoingEdgeBendPoints);
            }
            // Remove connection between node and original hierarchical port dummy
            nodeToOriginEdge.setSource(null);
            nodeToOriginEdge.setTarget(null);
            // Remember the temporary node for removal
            nodesToRemove.add(node);
        }
    }
    // Remove nodes
    for (LNode node : nodesToRemove) {
        node.setLayer(null);
    }
}
Also used : 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) Layer(org.eclipse.elk.alg.layered.graph.Layer)

Example 5 with LEdge

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

the class InvertedPortProcessor method createEastPortSideDummies.

/**
 * Creates the necessary dummy nodes for an input port on the east side of a node, provided that
 * the edge connects two different nodes.
 *
 * @param layeredGraph
 *            the layered graph.
 * @param eastwardPort
 *            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 createEastPortSideDummies(final LGraph layeredGraph, final LPort eastwardPort, final LEdge edge, final List<LNode> layerNodeList) {
    assert edge.getTarget() == eastwardPort;
    // Ignore self loops
    if (edge.getSource().getNode() == eastwardPort.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
    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(eastwardPort);
    // Set LONG_EDGE_SOURCE and LONG_EDGE_TARGET properties on the LONG_EDGE dummy
    setLongEdgeSourceAndTarget(dummy, dummyInput, dummyOutput, eastwardPort);
    // Move head labels from the old edge over to the new one
    ListIterator<LLabel> labelIterator = edge.getLabels().listIterator();
    while (labelIterator.hasNext()) {
        LLabel label = labelIterator.next();
        EdgeLabelPlacement labelPlacement = label.getProperty(LayeredOptions.EDGE_LABELS_PLACEMENT);
        if (labelPlacement == EdgeLabelPlacement.HEAD) {
            // Remember which edge the label originally belonged to, unless it already knows
            if (!label.hasProperty(InternalProperties.END_LABEL_EDGE)) {
                label.setProperty(InternalProperties.END_LABEL_EDGE, edge);
            }
            labelIterator.remove();
            dummyEdge.getLabels().add(label);
        }
    }
}
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) EdgeLabelPlacement(org.eclipse.elk.core.options.EdgeLabelPlacement)

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