Search in sources :

Example 41 with LEdge

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

the class ComponentsCompactor method createDummyNode.

private LNode createDummyNode(final LGraph graph) {
    // to handle it properly, we give it a tiny little dummy rectangle
    assert graph.getLayerlessNodes().size() == 1;
    LNode extPortDummy = graph.getLayerlessNodes().get(0);
    // create a small dummy node for the external port dummy
    LNode dummy = new LNode(graph);
    graph.getLayerlessNodes().add(dummy);
    // reassemble the size of the external dummy but assure
    // that no dimension is zero. Otherwise we may end up
    // with dimension-less hull rectangles which causes
    // the scanline to fail
    dummy.getSize().x = Math.max(1, extPortDummy.getSize().x);
    dummy.getSize().y = Math.max(1, extPortDummy.getSize().y);
    // set the position such that it is on the proper side
    // with respect to the dummy port
    dummy.getPosition().x = extPortDummy.getPosition().x;
    dummy.getPosition().y = extPortDummy.getPosition().y;
    switch(extPortDummy.getProperty(InternalProperties.EXT_PORT_SIDE)) {
        case WEST:
            dummy.getPosition().x += 2;
            break;
        case NORTH:
            dummy.getPosition().y += 2;
            break;
        case EAST:
            dummy.getPosition().x -= 2;
            break;
        case SOUTH:
            dummy.getPosition().y -= 2;
            break;
    }
    // give the dummy a port and create an edge for it
    LPort dummyPort = new LPort();
    dummyPort.setNode(dummy);
    LEdge dummyEdge = new LEdge();
    LPort extPortDummyPort = extPortDummy.getPorts().get(0);
    dummyEdge.setSource(extPortDummyPort);
    dummyEdge.setTarget(dummyPort);
    // position the dummy port such that the edge will be straight
    dummyPort.getPosition().reset().add(extPortDummyPort.getPosition());
    dummyPort.getAnchor().reset().add(extPortDummyPort.getAnchor());
    return dummy;
}
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)

Example 42 with LEdge

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

the class ComponentsCompactor method componentHullPoints.

private Hullpoints componentHullPoints(final LGraph graph) {
    final Hullpoints pts = new Hullpoints();
    for (LNode n : graph.getLayerlessNodes()) {
        if (n.getType() == NodeType.EXTERNAL_PORT) {
            continue;
        }
        // Note that labels of nodes are already part of a node's margins
        // the same is true for ports and their labels
        addLGraphElementBounds(pts, n, new KVector());
        // add bend points of the edges
        for (LEdge edge : n.getOutgoingEdges()) {
            if (isExternalEdge(edge)) {
                continue;
            }
            for (KVector bp : edge.getBendPoints()) {
                KVector absolute = bp;
                pts.add(new Point(absolute.x, absolute.y));
            }
        }
    }
    return pts;
}
Also used : LEdge(org.eclipse.elk.alg.layered.graph.LEdge) LNode(org.eclipse.elk.alg.layered.graph.LNode) Point(org.eclipse.elk.alg.layered.compaction.recthull.Point) KVector(org.eclipse.elk.core.math.KVector)

Example 43 with LEdge

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

the class ComponentsCompactor method compact.

// ------------------------------------------------------------------------------------------------
// public API
// ------------------------------------------------------------------------------------------------
/**
 * @param graphs
 *            the components to be compacted
 * @param originalGraphsSize
 *            the size of the overall graph as it is currently
 * @param spacing
 *            the desired spacing to be preserved between any pair of components
 */
public void compact(final List<LGraph> graphs, final KVector originalGraphsSize, final double spacing) {
    // determine the extreme points of the current diagram,
    // we will reuse this 'frame' to cut external extensions at appropriate lengths
    graphTopLeft = new KVector(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
    graphBottomRight = new KVector(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
    for (LGraph graph : graphs) {
        for (LNode node : graph.getLayerlessNodes()) {
            graphTopLeft.x = Math.min(graphTopLeft.x, node.getPosition().x - node.getMargin().left);
            graphTopLeft.y = Math.min(graphTopLeft.y, node.getPosition().y - node.getMargin().top);
            graphBottomRight.x = Math.max(graphBottomRight.x, node.getPosition().x + node.getSize().x + node.getMargin().right);
            graphBottomRight.y = Math.max(graphBottomRight.y, node.getPosition().y + node.getSize().y + node.getMargin().bottom);
        }
    }
    // from the lgraphs, create connected components
    IConnectedComponents<LNode, Set<LEdge>> ccs = new InternalConnectedComponents();
    for (LGraph graph : graphs) {
        IComponent<LNode, Set<LEdge>> c = transformLGraph(graph);
        ccs.getComponents().add(c);
        ((InternalComponent) c).containsRegularNodes |= !c.getExternalExtensionSides().isEmpty();
    }
    // for every component we create an element in the compactor
    compactor = OneDimensionalComponentsCompaction.init(ccs, spacing);
    // execute compaction
    compactor.compact(new BasicProgressMonitor());
    yetAnotherOffset = new KVector();
    compactedGraphSize = compactor.getGraphSize();
    // apply the positions
    for (IComponent<LNode, Set<LEdge>> cc : ccs.getComponents()) {
        // retrieve the common offset for the currently handled connected component
        KVector offset = compactor.getOffset(cc);
        // move it
        LGraphUtil.offsetGraph(((InternalComponent) cc).graph, offset.x, offset.y);
        // adjust positions of external ports
        for (LNode n : ((InternalComponent) cc).getNodes()) {
            if (n.getType() == NodeType.EXTERNAL_PORT) {
                KVector newPos = getExternalPortPosition(n.getPosition(), n.getProperty(InternalProperties.EXT_PORT_SIDE));
                n.getPosition().reset().add(newPos);
            }
        }
    }
    // external edges contribute to the graph's size ... however, only certain segments do.
    for (IComponent<LNode, Set<LEdge>> cc : ccs.getComponents()) {
        for (LEdge e : ((InternalComponent) cc).getExternalEdges()) {
            KVectorChain vc = new KVectorChain(e.getBendPoints());
            vc.add(0, e.getSource().getAbsoluteAnchor());
            vc.add(e.getTarget().getAbsoluteAnchor());
            KVector last = null;
            for (KVector v : vc) {
                if (last == null) {
                    last = v;
                    continue;
                }
                if (DoubleMath.fuzzyEquals(last.x, v.x, EPSILON)) {
                    yetAnotherOffset.x = Math.min(yetAnotherOffset.x, last.x);
                    compactedGraphSize.x = Math.max(compactedGraphSize.x, last.x);
                } else if (DoubleMath.fuzzyEquals(last.y, v.y, EPSILON)) {
                    yetAnotherOffset.y = Math.min(yetAnotherOffset.y, last.y);
                    compactedGraphSize.y = Math.max(compactedGraphSize.y, last.y);
                }
                last = v;
            }
        }
    }
    yetAnotherOffset.negate();
    compactedGraphSize.add(yetAnotherOffset);
}
Also used : Set(java.util.Set) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) KVectorChain(org.eclipse.elk.core.math.KVectorChain) LNode(org.eclipse.elk.alg.layered.graph.LNode) KVector(org.eclipse.elk.core.math.KVector) LGraph(org.eclipse.elk.alg.layered.graph.LGraph) BasicProgressMonitor(org.eclipse.elk.core.util.BasicProgressMonitor)

Example 44 with LEdge

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

the class CompoundGraphPostprocessor method process.

@Override
public void process(final LGraph graph, final IElkProgressMonitor monitor) {
    monitor.begin("Compound graph postprocessor", 1);
    // whether bend points should be added whenever crossing a hierarchy boundary
    boolean addUnnecessaryBendpoints = graph.getProperty(LayeredOptions.UNNECESSARY_BENDPOINTS);
    // restore the cross-hierarchy map that was built by the preprocessor
    Multimap<LEdge, CrossHierarchyEdge> crossHierarchyMap = graph.getProperty(InternalProperties.CROSS_HIERARCHY_MAP);
    // remember all dummy edges we encounter; these need to be removed at the end
    Set<LEdge> dummyEdges = Sets.newHashSet();
    // iterate over all original edges
    for (LEdge origEdge : crossHierarchyMap.keySet()) {
        // find all cross-hierarchy edges the original edge was split into, and sort them from source to target
        List<CrossHierarchyEdge> crossHierarchyEdges = new ArrayList<CrossHierarchyEdge>(crossHierarchyMap.get(origEdge));
        Collections.sort(crossHierarchyEdges, new CrossHierarchyEdgeComparator(graph));
        // find the original source and target ports for the original edge
        LPort sourcePort = crossHierarchyEdges.get(0).getActualSource();
        LPort targetPort = crossHierarchyEdges.get(crossHierarchyEdges.size() - 1).getActualTarget();
        // determine the reference graph for all bend points
        LNode referenceNode = sourcePort.getNode();
        LGraph referenceGraph;
        if (LGraphUtil.isDescendant(targetPort.getNode(), referenceNode)) {
            referenceGraph = referenceNode.getNestedGraph();
        } else {
            referenceGraph = referenceNode.getGraph();
        }
        // check whether there are any junction points
        KVectorChain junctionPoints = clearJunctionPoints(origEdge, crossHierarchyEdges);
        // reset bend points (we have computed new ones anyway)
        origEdge.getBendPoints().clear();
        // apply the computed layouts to the cross-hierarchy edge
        KVector lastPoint = null;
        for (CrossHierarchyEdge chEdge : crossHierarchyEdges) {
            // transform all coordinates from the graph of the dummy edge to the reference graph
            KVector offset = new KVector();
            LGraphUtil.changeCoordSystem(offset, chEdge.getGraph(), referenceGraph);
            LEdge ledge = chEdge.getEdge();
            KVectorChain bendPoints = new KVectorChain();
            bendPoints.addAllAsCopies(0, ledge.getBendPoints());
            bendPoints.offset(offset);
            // Note: if an NPE occurs here, that means ELK Layered has replaced the original edge
            KVector sourcePoint = new KVector(ledge.getSource().getAbsoluteAnchor());
            KVector targetPoint = new KVector(ledge.getTarget().getAbsoluteAnchor());
            sourcePoint.add(offset);
            targetPoint.add(offset);
            if (lastPoint != null) {
                KVector nextPoint;
                if (bendPoints.isEmpty()) {
                    nextPoint = targetPoint;
                } else {
                    nextPoint = bendPoints.getFirst();
                }
                // we add the source point as a bend point to properly connect the hierarchy levels
                // either if the last point of the previous hierarchy edge segment is a certain
                // level of tolerance away or if we are required to add unnecessary bend points
                boolean xDiffEnough = Math.abs(lastPoint.x - nextPoint.x) > OrthogonalRoutingGenerator.TOLERANCE;
                boolean yDiffEnough = Math.abs(lastPoint.y - nextPoint.y) > OrthogonalRoutingGenerator.TOLERANCE;
                if ((!addUnnecessaryBendpoints && xDiffEnough && yDiffEnough) || (addUnnecessaryBendpoints && (xDiffEnough || yDiffEnough))) {
                    origEdge.getBendPoints().add(sourcePoint);
                }
            }
            origEdge.getBendPoints().addAll(bendPoints);
            if (bendPoints.isEmpty()) {
                lastPoint = sourcePoint;
            } else {
                lastPoint = bendPoints.getLast();
            }
            // copy junction points
            copyJunctionPoints(ledge, junctionPoints, offset);
            // add offset to target port with a special property
            if (chEdge.getActualTarget() == targetPort) {
                if (targetPort.getNode().getGraph() != chEdge.getGraph()) {
                    // the target port is in a different coordinate system -- recompute the offset
                    offset = new KVector();
                    LGraphUtil.changeCoordSystem(offset, targetPort.getNode().getGraph(), referenceGraph);
                }
                origEdge.setProperty(InternalProperties.TARGET_OFFSET, offset);
            }
            // copy labels back to the original edge
            copyLabelsBack(ledge, origEdge, referenceGraph);
            // remember the dummy edge for later removal (dummy edges may be in use by several
            // different original edges, which is why we cannot just go and remove it now)
            dummyEdges.add(ledge);
        }
        // restore the original source port and target port
        origEdge.setSource(sourcePort);
        origEdge.setTarget(targetPort);
    }
    // remove the dummy edges from the graph (dummy ports and dummy nodes are retained)
    for (LEdge dummyEdge : dummyEdges) {
        dummyEdge.setSource(null);
        dummyEdge.setTarget(null);
    }
    monitor.done();
}
Also used : LEdge(org.eclipse.elk.alg.layered.graph.LEdge) KVectorChain(org.eclipse.elk.core.math.KVectorChain) ArrayList(java.util.ArrayList) LGraph(org.eclipse.elk.alg.layered.graph.LGraph) LPort(org.eclipse.elk.alg.layered.graph.LPort) LNode(org.eclipse.elk.alg.layered.graph.LNode) KVector(org.eclipse.elk.core.math.KVector)

Example 45 with LEdge

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

the class ElkGraphLayoutTransferrer method applyLayout.

/**
 * Applies the layout information contained in the given LGraph to the ElkGraph elements it was
 * created from. All source ElkGraph elements are expected to be accessible through their LGraph
 * counterparts through the {@link InternalProperties#ORIGIN} property.
 *
 * @param lgraph the LGraph whose layout information to apply.
 */
public void applyLayout(final LGraph lgraph) {
    Object graphOrigin = lgraph.getProperty(InternalProperties.ORIGIN);
    if (!(graphOrigin instanceof ElkNode)) {
        return;
    }
    // The ElkNode that represents this graph in the original ElkGraph
    ElkNode parentElkNode = (ElkNode) graphOrigin;
    // The LNode that represents this graph in the upper hierarchy level, if any
    LNode parentLNode = (LNode) lgraph.getParentNode();
    // Get the offset to be added to all coordinates
    KVector offset = new KVector(lgraph.getOffset());
    // Adjust offset (and with it the positions) by the requested padding
    LPadding lPadding = lgraph.getPadding();
    offset.x += lPadding.left;
    offset.y += lPadding.top;
    // Set node padding, if it was computed during layout
    final EnumSet<SizeOptions> sizeOptions = parentElkNode.getProperty(LayeredOptions.NODE_SIZE_OPTIONS);
    if (sizeOptions.contains(SizeOptions.COMPUTE_PADDING)) {
        ElkPadding padding = parentElkNode.getProperty(LayeredOptions.PADDING);
        padding.setBottom(lPadding.bottom);
        padding.setTop(lPadding.top);
        padding.setLeft(lPadding.left);
        padding.setRight(lPadding.right);
    }
    // Along the way, we collect the list of edges to be processed later
    List<LEdge> edgeList = Lists.newArrayList();
    // Process the nodes
    for (LNode lnode : lgraph.getLayerlessNodes()) {
        if (representsNode(lnode)) {
            applyNodeLayout(lnode, offset);
        } else if (representsExternalPort(lnode) && parentLNode == null) {
            // We have an external port here on the top-most hierarchy level of the current (possibly
            // hierarchical) layout run; set its position
            ElkPort elkport = (ElkPort) lnode.getProperty(InternalProperties.ORIGIN);
            KVector portPosition = LGraphUtil.getExternalPortPosition(lgraph, lnode, elkport.getWidth(), elkport.getHeight());
            elkport.setLocation(portPosition.x, portPosition.y);
        }
        // correctly)
        for (LPort port : lnode.getPorts()) {
            port.getOutgoingEdges().stream().filter(edge -> !LGraphUtil.isDescendant(edge.getTarget().getNode(), lnode)).forEach(edge -> edgeList.add(edge));
        }
    }
    // Collect edges that go from the current graph's representing LNode down into its descendants
    if (parentLNode != null) {
        for (LPort port : parentLNode.getPorts()) {
            port.getOutgoingEdges().stream().filter(edge -> LGraphUtil.isDescendant(edge.getTarget().getNode(), parentLNode)).forEach(edge -> edgeList.add(edge));
        }
    }
    // Iterate through all edges
    EdgeRouting routing = parentElkNode.getProperty(LayeredOptions.EDGE_ROUTING);
    for (LEdge ledge : edgeList) {
        applyEdgeLayout(ledge, routing, offset, lPadding);
    }
    // Setup the parent node
    applyParentNodeLayout(lgraph);
    // Process nested subgraphs
    for (LNode lnode : lgraph.getLayerlessNodes()) {
        LGraph nestedGraph = lnode.getNestedGraph();
        if (nestedGraph != null) {
            applyLayout(nestedGraph);
        }
    }
}
Also used : GraphProperties(org.eclipse.elk.alg.layered.options.GraphProperties) LLabel(org.eclipse.elk.alg.layered.graph.LLabel) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) ElkNode(org.eclipse.elk.graph.ElkNode) ElkPort(org.eclipse.elk.graph.ElkPort) PortLabelPlacement(org.eclipse.elk.core.options.PortLabelPlacement) LayeredOptions(org.eclipse.elk.alg.layered.options.LayeredOptions) KVectorChain(org.eclipse.elk.core.math.KVectorChain) ElkUtil(org.eclipse.elk.core.util.ElkUtil) Lists(com.google.common.collect.Lists) LabelDummySwitcher(org.eclipse.elk.alg.layered.intermediate.LabelDummySwitcher) InternalProperties(org.eclipse.elk.alg.layered.options.InternalProperties) ElkPadding(org.eclipse.elk.core.math.ElkPadding) EnumSet(java.util.EnumSet) NodePlacementStrategy(org.eclipse.elk.alg.layered.options.NodePlacementStrategy) NodeFlexibility(org.eclipse.elk.alg.layered.options.NodeFlexibility) PortConstraints(org.eclipse.elk.core.options.PortConstraints) ElkLabel(org.eclipse.elk.graph.ElkLabel) KVector(org.eclipse.elk.core.math.KVector) SizeOptions(org.eclipse.elk.core.options.SizeOptions) Set(java.util.Set) SizeConstraint(org.eclipse.elk.core.options.SizeConstraint) LGraphUtil(org.eclipse.elk.alg.layered.graph.LGraphUtil) LPadding(org.eclipse.elk.alg.layered.graph.LPadding) List(java.util.List) LGraph(org.eclipse.elk.alg.layered.graph.LGraph) ElkEdgeSection(org.eclipse.elk.graph.ElkEdgeSection) LPort(org.eclipse.elk.alg.layered.graph.LPort) EdgeRouting(org.eclipse.elk.core.options.EdgeRouting) LNode(org.eclipse.elk.alg.layered.graph.LNode) ElkEdge(org.eclipse.elk.graph.ElkEdge) ElkGraphUtil(org.eclipse.elk.graph.util.ElkGraphUtil) ElkNode(org.eclipse.elk.graph.ElkNode) SizeOptions(org.eclipse.elk.core.options.SizeOptions) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) ElkPort(org.eclipse.elk.graph.ElkPort) LPadding(org.eclipse.elk.alg.layered.graph.LPadding) EdgeRouting(org.eclipse.elk.core.options.EdgeRouting) LGraph(org.eclipse.elk.alg.layered.graph.LGraph) LPort(org.eclipse.elk.alg.layered.graph.LPort) LNode(org.eclipse.elk.alg.layered.graph.LNode) KVector(org.eclipse.elk.core.math.KVector) ElkPadding(org.eclipse.elk.core.math.ElkPadding)

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