Search in sources :

Example 1 with UnsupportedGraphException

use of org.eclipse.elk.core.UnsupportedGraphException in project elk by eclipse.

the class ElkLayered method reviewAndCorrectHierarchicalProcessors.

/**
 * It is not permitted that any of the child-graphs specifies a hierarchical
 * layout processor ({@link IHierarchyAwareLayoutProcessor}) that is not specified by the root node.
 *
 * It depends on the concrete processor how this is fixed.
 *
 * @param root the root graph
 * @param graphs all graphs of the handled hierarchy
 */
private void reviewAndCorrectHierarchicalProcessors(final LGraph root, final Collection<LGraph> graphs) {
    // Crossing minimization
    // overwrite invalid child configuration (only layer sweep is hierarchical)
    CrossingMinimizationStrategy parentCms = root.getProperty(LayeredOptions.CROSSING_MINIMIZATION_STRATEGY);
    if (parentCms != CrossingMinimizationStrategy.LAYER_SWEEP) {
        graphs.forEach(child -> {
            CrossingMinimizationStrategy childCms = child.getProperty(LayeredOptions.CROSSING_MINIMIZATION_STRATEGY);
            if (childCms == CrossingMinimizationStrategy.LAYER_SWEEP) {
                throw new UnsupportedGraphException("The hierarchy aware processor " + childCms + " in child node " + child + " is only allowed if the root node specifies the same hierarchical processor.");
            }
        });
    }
    // Greedy switch (simply copy the behavior of the root to all children)
    final GreedySwitchType rootType = root.getProperty(LayeredOptions.CROSSING_MINIMIZATION_GREEDY_SWITCH_HIERARCHICAL_TYPE);
    graphs.forEach(g -> g.setProperty(LayeredOptions.CROSSING_MINIMIZATION_GREEDY_SWITCH_HIERARCHICAL_TYPE, rootType));
}
Also used : UnsupportedGraphException(org.eclipse.elk.core.UnsupportedGraphException) CrossingMinimizationStrategy(org.eclipse.elk.alg.layered.options.CrossingMinimizationStrategy) GreedySwitchType(org.eclipse.elk.alg.layered.options.GreedySwitchType)

Example 2 with UnsupportedGraphException

use of org.eclipse.elk.core.UnsupportedGraphException in project elk by eclipse.

the class ElkGraphImporter method transformEdge.

// /////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Edge Transformation
/**
 * Transforms the given edge if it's not a hyperedge. If it is a hyperedge, throws an exception.
 *
 * @param elkedge the edge to transform
 * @param elkparent the node in the original graph which currently gets transformed into {@code lgraph}
 * @param lgraph the layered graph
 * @return the transformed edge, or {@code null} if it cannot be transformed
 * @throws UnsupportedGraphException if the edge is a hyperedge.
 */
private LEdge transformEdge(final ElkEdge elkedge, final ElkNode elkparent, final LGraph lgraph) {
    checkEdgeValidity(elkedge);
    // Get a few basic information about the edge
    ElkConnectableShape elkSourceShape = elkedge.getSources().get(0);
    ElkConnectableShape elkTargetShape = elkedge.getTargets().get(0);
    ElkNode elkSourceNode = ElkGraphUtil.connectableShapeToNode(elkSourceShape);
    ElkNode elkTargetNode = ElkGraphUtil.connectableShapeToNode(elkTargetShape);
    ElkEdgeSection edgeSection = elkedge.getSections().isEmpty() ? null : elkedge.getSections().get(0);
    // Find the transformed source and target nodes
    LNode sourceLNode = (LNode) nodeAndPortMap.get(elkSourceNode);
    LNode targetLNode = (LNode) nodeAndPortMap.get(elkTargetNode);
    LPort sourceLPort = null;
    LPort targetLPort = null;
    // Find the transformed source port, if any
    if (elkSourceShape instanceof ElkPort) {
        // If the ElkPort is a regular port, it will map to an LPort; if it's an external port, it
        // will map to an LNode
        LGraphElement sourceElem = nodeAndPortMap.get(elkSourceShape);
        if (sourceElem instanceof LPort) {
            sourceLPort = (LPort) sourceElem;
        } else if (sourceElem instanceof LNode) {
            sourceLNode = (LNode) sourceElem;
            sourceLPort = sourceLNode.getPorts().get(0);
        }
    }
    // Find the transformed target port, if any
    if (elkTargetShape instanceof ElkPort) {
        // If the ElkPort is a regular port, it will map to an LPort; if it's an external port, it
        // will map to an LNode
        LGraphElement targetElem = nodeAndPortMap.get(elkTargetShape);
        if (targetElem instanceof LPort) {
            targetLPort = (LPort) targetElem;
        } else if (targetElem instanceof LNode) {
            targetLNode = (LNode) targetElem;
            targetLPort = targetLNode.getPorts().get(0);
        }
    }
    // reason, we back out
    if (sourceLNode == null || targetLNode == null) {
        throw new UnsupportedGraphException("The source or the target of edge " + elkedge + " could not be found. " + "This usually happens when an edge connects a node laid out by ELK Layered to a node in " + "another level of hierarchy laid out by either another instance of ELK Layered or another " + "layout algorithm alltogether. The former can be solved by setting the hierarchyHandling " + "option to INCLUDE_CHILDREN.");
    }
    // Create a layered edge
    LEdge ledge = new LEdge();
    ledge.copyProperties(elkedge);
    ledge.setProperty(InternalProperties.ORIGIN, elkedge);
    // Clear junction points, since they are recomputed from scratch
    ledge.setProperty(LayeredOptions.JUNCTION_POINTS, null);
    // If we have a self-loop, set the appropriate graph property
    Set<GraphProperties> graphProperties = lgraph.getProperty(InternalProperties.GRAPH_PROPERTIES);
    if (sourceLNode == targetLNode) {
        graphProperties.add(GraphProperties.SELF_LOOPS);
    }
    // Create source and target ports if they do not exist yet
    if (sourceLPort == null) {
        PortType portType = PortType.OUTPUT;
        KVector sourcePoint = null;
        if (edgeSection != null && sourceLNode.getProperty(LayeredOptions.PORT_CONSTRAINTS).isSideFixed()) {
            sourcePoint = new KVector(edgeSection.getStartX(), edgeSection.getStartY());
            // The coordinates need to be relative to us
            ElkUtil.toAbsolute(sourcePoint, elkedge.getContainingNode());
            ElkUtil.toRelative(sourcePoint, elkparent);
            // source), we may need to adjust the coordinates
            if (ElkGraphUtil.isDescendant(elkTargetNode, elkSourceNode)) {
                // External source port: put it on the west side
                portType = PortType.INPUT;
                sourcePoint.add(sourceLNode.getPosition());
            }
        }
        sourceLPort = LGraphUtil.createPort(sourceLNode, sourcePoint, portType, lgraph);
    }
    if (targetLPort == null) {
        PortType portType = PortType.INPUT;
        KVector targetPoint = null;
        if (edgeSection != null && targetLNode.getProperty(LayeredOptions.PORT_CONSTRAINTS).isSideFixed()) {
            targetPoint = new KVector(edgeSection.getEndX(), edgeSection.getEndY());
            // Adjust the coordinates
            // MIGRATE Not sure yet if this really does what we want it to do
            ElkUtil.toAbsolute(targetPoint, elkedge.getContainingNode());
            ElkUtil.toRelative(targetPoint, elkparent);
        }
        targetLPort = LGraphUtil.createPort(targetLNode, targetPoint, portType, targetLNode.getGraph());
    }
    // Finally set the source and target of the edge
    ledge.setSource(sourceLPort);
    ledge.setTarget(targetLPort);
    // If the ports have multiple incoming or outgoing edges, the HYPEREDGE property needs to be set
    if (sourceLPort.getIncomingEdges().size() > 1 || sourceLPort.getOutgoingEdges().size() > 1 || targetLPort.getIncomingEdges().size() > 1 || targetLPort.getOutgoingEdges().size() > 1) {
        graphProperties.add(GraphProperties.HYPEREDGES);
    }
    // Transform the edge's labels
    for (ElkLabel elklabel : elkedge.getLabels()) {
        if (!elklabel.getProperty(LayeredOptions.NO_LAYOUT) && !Strings.isNullOrEmpty(elklabel.getText())) {
            LLabel llabel = transformLabel(elklabel);
            ledge.getLabels().add(llabel);
            // edge label placement is actually properly defined
            switch(llabel.getProperty(LayeredOptions.EDGE_LABELS_PLACEMENT)) {
                case HEAD:
                case TAIL:
                    graphProperties.add(GraphProperties.END_LABELS);
                    break;
                case CENTER:
                    graphProperties.add(GraphProperties.CENTER_LABELS);
                    llabel.setProperty(LayeredOptions.EDGE_LABELS_PLACEMENT, EdgeLabelPlacement.CENTER);
            }
        }
    }
    // Copy the original bend points of the edge in case they are required
    CrossingMinimizationStrategy crossMinStrat = lgraph.getProperty(LayeredOptions.CROSSING_MINIMIZATION_STRATEGY);
    NodePlacementStrategy nodePlaceStrat = lgraph.getProperty(LayeredOptions.NODE_PLACEMENT_STRATEGY);
    boolean bendPointsRequired = crossMinStrat == CrossingMinimizationStrategy.INTERACTIVE || nodePlaceStrat == NodePlacementStrategy.INTERACTIVE;
    if (edgeSection != null && !edgeSection.getBendPoints().isEmpty() && bendPointsRequired) {
        KVectorChain originalBendpoints = ElkUtil.createVectorChain(edgeSection);
        KVectorChain importedBendpoints = new KVectorChain();
        // MIGRATE We may have to do some coordinate conversion here
        for (KVector point : originalBendpoints) {
            importedBendpoints.add(new KVector(point));
        }
        ledge.setProperty(InternalProperties.ORIGINAL_BENDPOINTS, importedBendpoints);
    }
    return ledge;
}
Also used : UnsupportedGraphException(org.eclipse.elk.core.UnsupportedGraphException) NodePlacementStrategy(org.eclipse.elk.alg.layered.options.NodePlacementStrategy) ElkNode(org.eclipse.elk.graph.ElkNode) LLabel(org.eclipse.elk.alg.layered.graph.LLabel) GraphProperties(org.eclipse.elk.alg.layered.options.GraphProperties) ElkPort(org.eclipse.elk.graph.ElkPort) LGraphElement(org.eclipse.elk.alg.layered.graph.LGraphElement) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) KVectorChain(org.eclipse.elk.core.math.KVectorChain) ElkConnectableShape(org.eclipse.elk.graph.ElkConnectableShape) ElkEdgeSection(org.eclipse.elk.graph.ElkEdgeSection) ElkLabel(org.eclipse.elk.graph.ElkLabel) LPort(org.eclipse.elk.alg.layered.graph.LPort) CrossingMinimizationStrategy(org.eclipse.elk.alg.layered.options.CrossingMinimizationStrategy) LNode(org.eclipse.elk.alg.layered.graph.LNode) KVector(org.eclipse.elk.core.math.KVector) PortType(org.eclipse.elk.alg.layered.options.PortType)

Example 3 with UnsupportedGraphException

use of org.eclipse.elk.core.UnsupportedGraphException in project elk by eclipse.

the class ElkGraphImporter method transformEdges.

/**
 * Transforms the edges defined by the given layout node.
 *
 * @param parentNode the layout node whose edges to transform.
 * @param fgraph the force graph.
 * @param elemMap the element map that maps the original {@code KGraph} elements to the
 *                transformed {@code FGraph} elements.
 */
private void transformEdges(final ElkNode parentNode, final FGraph fgraph, final Map<ElkNode, FNode> elemMap) {
    for (ElkNode knode : parentNode.getChildren()) {
        for (ElkEdge kedge : ElkGraphUtil.allOutgoingEdges(knode)) {
            // We don't support hyperedges
            if (kedge.isHyperedge()) {
                throw new UnsupportedGraphException("Graph must not contain hyperedges.");
            }
            // exclude edges that pass hierarchy bounds as well as self-loops
            if (!kedge.isHierarchical() && knode != ElkGraphUtil.connectableShapeToNode(kedge.getTargets().get(0))) {
                // create a force edge
                FEdge newEdge = new FEdge();
                newEdge.copyProperties(kedge);
                // TODO
                // newEdge.checkProperties(Properties.LABEL_SPACING, Properties.REPULSIVE_POWER);
                newEdge.setProperty(InternalProperties.ORIGIN, kedge);
                newEdge.setSource(elemMap.get(knode));
                newEdge.setTarget(elemMap.get(ElkGraphUtil.connectableShapeToNode(kedge.getTargets().get(0))));
                fgraph.getEdges().add(newEdge);
                // transform the edge's labels
                for (ElkLabel klabel : kedge.getLabels()) {
                    FLabel newLabel = new FLabel(newEdge, klabel.getText());
                    newLabel.copyProperties(klabel);
                    newLabel.setProperty(InternalProperties.ORIGIN, klabel);
                    newLabel.getSize().x = Math.max(klabel.getWidth(), 1);
                    newLabel.getSize().y = Math.max(klabel.getHeight(), 1);
                    newLabel.refreshPosition();
                    fgraph.getLabels().add(newLabel);
                }
            }
        }
    }
}
Also used : UnsupportedGraphException(org.eclipse.elk.core.UnsupportedGraphException) FLabel(org.eclipse.elk.alg.force.graph.FLabel) ElkNode(org.eclipse.elk.graph.ElkNode) ElkLabel(org.eclipse.elk.graph.ElkLabel) FEdge(org.eclipse.elk.alg.force.graph.FEdge) ElkEdge(org.eclipse.elk.graph.ElkEdge)

Example 4 with UnsupportedGraphException

use of org.eclipse.elk.core.UnsupportedGraphException in project elk by eclipse.

the class DotExporter method transformEdges.

/**
 * Transform the edges of the given parent node.
 *
 * @param parent a parent node
 * @param statements the list to which new statements are added
 * @param transData transformation data
 */
private void transformEdges(final ElkNode parent, final List<Statement> statements, final IDotTransformationData<ElkNode, GraphvizModel> transData) {
    boolean hierarchy = transData.getProperty(HIERARCHY);
    boolean transformEdgeLayout = transData.getProperty(TRANSFORM_EDGE_LAYOUT);
    Direction direction = parent.getProperty(CoreOptions.DIRECTION);
    boolean vertical = direction == Direction.DOWN || direction == Direction.UP || direction == Direction.UNDEFINED;
    LinkedList<ElkNode> nodes = new LinkedList<>(parent.getChildren());
    BiMap<ElkGraphElement, String> nodeIds = transData.getProperty(GRAPH_ELEMS).inverse();
    while (!nodes.isEmpty()) {
        ElkNode source = nodes.removeFirst();
        for (ElkEdge edge : ElkGraphUtil.allOutgoingEdges(source)) {
            // We don't support hyperedges
            if (edge.isHyperedge()) {
                throw new UnsupportedGraphException("Hyperedges are not supported.");
            }
            ElkNode target = ElkGraphUtil.connectableShapeToNode(edge.getTargets().get(0));
            // cross-hierarchy edges are considered only if hierarchy mode is active
            if (source.getParent() == target.getParent() || hierarchy && isInsideGraph(target, transData.getSourceGraph())) {
                EdgeStatement edgeStatement = DotFactory.eINSTANCE.createEdgeStatement();
                List<Attribute> attributes = edgeStatement.getAttributes();
                // set source node or cluster
                Node sourceNode = DotFactory.eINSTANCE.createNode();
                if (hierarchy && !source.getChildren().isEmpty()) {
                    sourceNode.setName(source.getProperty(CLUSTER_DUMMY));
                    attributes.add(createAttribute(Attributes.LTAIL, nodeIds.get(source)));
                } else {
                    sourceNode.setName(nodeIds.get(source));
                }
                edgeStatement.setSourceNode(sourceNode);
                // set target node or cluster
                EdgeTarget edgeTarget = DotFactory.eINSTANCE.createEdgeTarget();
                Node targetNode = DotFactory.eINSTANCE.createNode();
                if (hierarchy && !target.getChildren().isEmpty()) {
                    targetNode.setName(target.getProperty(CLUSTER_DUMMY));
                    attributes.add(createAttribute(Attributes.LHEAD, nodeIds.get(target)));
                } else {
                    targetNode.setName(nodeIds.get(target));
                }
                edgeTarget.setTargetnode(targetNode);
                edgeStatement.getEdgeTargets().add(edgeTarget);
                // add edge labels at head, tail, and middle position
                setEdgeLabels(edge, attributes, vertical);
                if (transData.getProperty(USE_EDGE_IDS)) {
                    // add comment with edge identifier
                    String edgeID = getEdgeID(edge, transData);
                    attributes.add(createAttribute(Attributes.COMMENT, "\"" + edgeID + "\""));
                }
                // include edge routing for full export, if there is one
                if (!edge.getSections().isEmpty()) {
                    ElkEdgeSection edgeSection = edge.getSections().get(0);
                    if (transformEdgeLayout && (edgeSection.getBendPoints().size() > 0 || edgeSection.getStartX() != 0 || edgeSection.getStartY() != 0 || edgeSection.getEndX() != 0 || edgeSection.getEndY() != 0)) {
                        StringBuilder pos = new StringBuilder();
                        Iterator<KVector> pointIter = ElkUtil.createVectorChain(edgeSection).iterator();
                        while (pointIter.hasNext()) {
                            KVector point = pointIter.next();
                            ElkUtil.toAbsolute(point, edge.getContainingNode());
                            pos.append(point.x);
                            pos.append(",");
                            pos.append(point.y);
                            if (pointIter.hasNext()) {
                                pos.append(" ");
                            }
                        }
                        attributes.add(createAttribute(Attributes.POS, "\"" + pos + "\""));
                    }
                }
                statements.add(edgeStatement);
            }
        }
        if (hierarchy) {
            nodes.addAll(source.getChildren());
        }
    }
}
Also used : UnsupportedGraphException(org.eclipse.elk.core.UnsupportedGraphException) ElkNode(org.eclipse.elk.graph.ElkNode) Attribute(org.eclipse.elk.alg.graphviz.dot.dot.Attribute) ElkNode(org.eclipse.elk.graph.ElkNode) Node(org.eclipse.elk.alg.graphviz.dot.dot.Node) Direction(org.eclipse.elk.core.options.Direction) LinkedList(java.util.LinkedList) EdgeStatement(org.eclipse.elk.alg.graphviz.dot.dot.EdgeStatement) ElkEdgeSection(org.eclipse.elk.graph.ElkEdgeSection) EdgeTarget(org.eclipse.elk.alg.graphviz.dot.dot.EdgeTarget) KVector(org.eclipse.elk.core.math.KVector) ElkGraphElement(org.eclipse.elk.graph.ElkGraphElement) ElkEdge(org.eclipse.elk.graph.ElkEdge)

Aggregations

UnsupportedGraphException (org.eclipse.elk.core.UnsupportedGraphException)4 ElkNode (org.eclipse.elk.graph.ElkNode)3 CrossingMinimizationStrategy (org.eclipse.elk.alg.layered.options.CrossingMinimizationStrategy)2 KVector (org.eclipse.elk.core.math.KVector)2 ElkEdge (org.eclipse.elk.graph.ElkEdge)2 ElkEdgeSection (org.eclipse.elk.graph.ElkEdgeSection)2 ElkLabel (org.eclipse.elk.graph.ElkLabel)2 LinkedList (java.util.LinkedList)1 FEdge (org.eclipse.elk.alg.force.graph.FEdge)1 FLabel (org.eclipse.elk.alg.force.graph.FLabel)1 Attribute (org.eclipse.elk.alg.graphviz.dot.dot.Attribute)1 EdgeStatement (org.eclipse.elk.alg.graphviz.dot.dot.EdgeStatement)1 EdgeTarget (org.eclipse.elk.alg.graphviz.dot.dot.EdgeTarget)1 Node (org.eclipse.elk.alg.graphviz.dot.dot.Node)1 LEdge (org.eclipse.elk.alg.layered.graph.LEdge)1 LGraphElement (org.eclipse.elk.alg.layered.graph.LGraphElement)1 LLabel (org.eclipse.elk.alg.layered.graph.LLabel)1 LNode (org.eclipse.elk.alg.layered.graph.LNode)1 LPort (org.eclipse.elk.alg.layered.graph.LPort)1 GraphProperties (org.eclipse.elk.alg.layered.options.GraphProperties)1