Search in sources :

Example 26 with ElkEdge

use of org.eclipse.elk.graph.ElkEdge in project elk by eclipse.

the class RandomLayoutProvider method randomize.

/**
 * Randomize the given graph.
 *
 * @param parent the parent node of the graph
 * @param random the random number generator
 * @param aspectRatio desired aspect ratio (must not be 0)
 * @param spacing desired object spacing
 * @param offset offset to the border
 */
private void randomize(final ElkNode parent, final Random random, final double aspectRatio, final double spacing, final ElkPadding padding) {
    // determine width and height of the drawing and count the number of edges
    double nodesArea = 0.0f, maxWidth = 0.0f, maxHeight = 0.0f;
    int m = 1;
    for (ElkNode node : parent.getChildren()) {
        m += Iterables.size(ElkGraphUtil.allOutgoingEdges(node));
        double width = node.getWidth();
        maxWidth = Math.max(maxWidth, width);
        double height = node.getHeight();
        maxHeight = Math.max(maxHeight, height);
        nodesArea += width * height;
    }
    int n = parent.getChildren().size();
    // a heuristic formula that determines an area in which nodes are randomly distributed
    double drawArea = nodesArea + 2 * spacing * spacing * m * n;
    double areaSqrt = (double) Math.sqrt(drawArea);
    double drawWidth = Math.max(areaSqrt * aspectRatio, maxWidth);
    double drawHeight = Math.max(areaSqrt / aspectRatio, maxHeight);
    // randomize node positions
    for (ElkNode node : parent.getChildren()) {
        double x = padding.getLeft() + random.nextDouble() * (drawWidth - node.getWidth());
        double y = padding.getLeft() + random.nextDouble() * (drawHeight - node.getHeight());
        node.setLocation(x, y);
    }
    // randomize edge positions
    double totalWidth = drawWidth + padding.getHorizontal();
    double totalHeight = drawHeight + padding.getVertical();
    for (ElkNode source : parent.getChildren()) {
        for (ElkEdge edge : ElkGraphUtil.allOutgoingEdges(source)) {
            if (!edge.isHierarchical()) {
                randomize(edge, random, totalWidth, totalHeight);
            }
        }
    }
    totalWidth += padding.getLeft() + padding.getRight();
    totalHeight += padding.getTop() + padding.getBottom();
    ElkUtil.resizeNode(parent, totalWidth, totalHeight, false, true);
}
Also used : ElkNode(org.eclipse.elk.graph.ElkNode) ElkBendPoint(org.eclipse.elk.graph.ElkBendPoint) ElkEdge(org.eclipse.elk.graph.ElkEdge)

Example 27 with ElkEdge

use of org.eclipse.elk.graph.ElkEdge in project elk by eclipse.

the class GmfLayoutEditPolicy method addLabelLayout.

/**
 * Adds an edge label layout to the given command.
 *
 * @param command
 *            command to which the edge label layout shall be added
 * @param klabel
 *            label with layout data
 * @param labelEditPart
 *            edit part to which layout is applied
 * @param scale
 *            scale factor for coordinates
 */
private void addLabelLayout(final GmfLayoutCommand command, final ElkLabel klabel, final GraphicalEditPart labelEditPart, final double scale) {
    ElkGraphElement parent = klabel.getParent();
    // node and port labels are processed separately
    if (parent instanceof ElkNode || parent instanceof ElkPort) {
        View view = (View) labelEditPart.getModel();
        int xpos = (int) (klabel.getX() * scale);
        int ypos = (int) (klabel.getY() * scale);
        Object oldx = ViewUtil.getStructuralFeatureValue(view, NotationPackage.eINSTANCE.getLocation_X());
        Object oldy = ViewUtil.getStructuralFeatureValue(view, NotationPackage.eINSTANCE.getLocation_Y());
        if (oldx == null || oldy == null || xpos != (Integer) oldx || ypos != (Integer) oldy) {
            command.addShapeLayout(view, new Point(xpos, ypos), null);
        }
        return;
    } else if (parent instanceof ElkEdge) {
        // calculate direct new location of the label
        Rectangle targetBounds = new Rectangle(labelEditPart.getFigure().getBounds());
        targetBounds.x = (int) (klabel.getX() * scale);
        targetBounds.y = (int) (klabel.getY() * scale);
        ConnectionEditPart connectionEditPart = (ConnectionEditPart) labelEditPart.getParent();
        PointList bendPoints = getBendPoints((ElkEdge) parent, connectionEditPart.getFigure(), scale);
        EObject modelElement = connectionEditPart.getNotationView().getElement();
        EdgeLabelPlacement labelPlacement = klabel.getProperty(CoreOptions.EDGE_LABELS_PLACEMENT);
        // the list of bend points must be reversed
        if (modelElement instanceof EReference && labelPlacement == EdgeLabelPlacement.TAIL) {
            bendPoints = bendPoints.getCopy();
            bendPoints.reverse();
        }
        // get the referencePoint for the label
        int fromEnd, keyPoint = ConnectionLocator.MIDDLE;
        if (labelEditPart instanceof LabelEditPart) {
            keyPoint = ((LabelEditPart) labelEditPart).getKeyPoint();
        }
        switch(keyPoint) {
            case ConnectionLocator.SOURCE:
                fromEnd = SOURCE_LOCATION;
                break;
            case ConnectionLocator.TARGET:
                fromEnd = TARGET_LOCATION;
                break;
            default:
                fromEnd = MIDDLE_LOCATION;
                break;
        }
        Point refPoint = PointListUtilities.calculatePointRelativeToLine(bendPoints, 0, fromEnd, true);
        // get the new relative location
        Point normalPoint = offsetFromRelativeCoordinate(targetBounds, bendPoints, refPoint);
        if (normalPoint != null) {
            command.addShapeLayout((View) labelEditPart.getModel(), normalPoint, null);
        }
    }
}
Also used : PointList(org.eclipse.draw2d.geometry.PointList) LabelEditPart(org.eclipse.gmf.runtime.diagram.ui.editparts.LabelEditPart) ConnectionEditPart(org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart) ElkNode(org.eclipse.elk.graph.ElkNode) ElkPort(org.eclipse.elk.graph.ElkPort) Rectangle(org.eclipse.draw2d.geometry.Rectangle) Point(org.eclipse.draw2d.geometry.Point) PrecisionPoint(org.eclipse.draw2d.geometry.PrecisionPoint) View(org.eclipse.gmf.runtime.notation.View) Point(org.eclipse.draw2d.geometry.Point) PrecisionPoint(org.eclipse.draw2d.geometry.PrecisionPoint) EObject(org.eclipse.emf.ecore.EObject) EObject(org.eclipse.emf.ecore.EObject) EdgeLabelPlacement(org.eclipse.elk.core.options.EdgeLabelPlacement) ElkGraphElement(org.eclipse.elk.graph.ElkGraphElement) EReference(org.eclipse.emf.ecore.EReference) ElkEdge(org.eclipse.elk.graph.ElkEdge)

Example 28 with ElkEdge

use of org.eclipse.elk.graph.ElkEdge in project elk by eclipse.

the class RandomGraphGenerator method connect.

/**
 * Connects two nodes with an edge.
 *
 * @param source
 *            the source node
 * @param target
 *            the target node
 * @param directed
 *            whether the edge should be directed or undirected
 * @return the edge
 */
private ElkEdge connect(final ElkConnectableShape source, final ElkConnectableShape target) {
    ElkNode sourceNode = null;
    ElkNode targetNode = null;
    ElkPort sourcePort = null;
    ElkPort targetPort = null;
    if (source instanceof ElkNode) {
        sourceNode = (ElkNode) source;
    }
    if (source instanceof ElkPort) {
        sourcePort = (ElkPort) source;
        sourceNode = sourcePort.getParent();
    }
    if (target instanceof ElkPort) {
        targetPort = (ElkPort) target;
        targetNode = targetPort.getParent();
    }
    if (target instanceof ElkNode) {
        targetNode = (ElkNode) target;
    }
    ElkEdge edge = ElkGraphUtil.createEdge(null);
    if (get(GeneratorOptions.ENABLE_PORTS)) {
        if (source instanceof ElkNode) {
            sourcePort = retrievePort(sourceNode, true);
        }
        if (!isHypernode(sourceNode)) {
            // remove node
            if (edge.getSources().contains(sourceNode)) {
                edge.getSources().remove(sourceNode);
            }
            edge.getSources().add(sourcePort);
        // edge.setSourcePort(sourcePort);
        }
        if (!isHypernode(targetNode)) {
            if (targetPort == null) {
                targetPort = retrievePort(targetNode, false);
            }
            if (edge.getTargets().contains(targetNode)) {
                edge.getTargets().remove(targetNode);
            }
            edge.getTargets().remove(target);
            edge.getTargets().add(targetPort);
        // edge.setTargetPort(targetPort);
        }
    } else {
        edge.getSources().add(sourceNode);
        edge.getTargets().add(targetNode);
    }
    if (get(GeneratorOptions.EDGE_LABELS)) {
        addEdgeLabel(edge);
    }
    ElkGraphUtil.updateContainment(edge);
    return edge;
}
Also used : ElkNode(org.eclipse.elk.graph.ElkNode) ElkPort(org.eclipse.elk.graph.ElkPort) ElkEdge(org.eclipse.elk.graph.ElkEdge)

Example 29 with ElkEdge

use of org.eclipse.elk.graph.ElkEdge in project elk by eclipse.

the class RandomGraphGenerator method findNodeWithDFS.

/**
 * Returns whether a node can be reached from another node. PRECONDITION: the graph containing
 * the nodes has to be acyclic! If that condition is not met the method is likely to loop
 * infinitely!
 *
 * @param start
 *            the start node
 * @param end
 *            the end node
 * @return whether the end node can be reached from the start node
 */
private static boolean findNodeWithDFS(final ElkNode start, final ElkNode end) {
    Queue<ElkNode> nodes = new LinkedList<ElkNode>();
    nodes.add(start);
    do {
        ElkNode node = nodes.poll();
        if (node == end) {
            return true;
        }
        for (ElkEdge edge : node.getOutgoingEdges()) {
            for (ElkConnectableShape target : edge.getTargets()) {
                if (target instanceof ElkNode) {
                    nodes.add((ElkNode) target);
                } else if (target instanceof ElkPort) {
                    ElkPort port = (ElkPort) target;
                    nodes.add(port.getParent());
                }
            }
        }
    } while (!nodes.isEmpty());
    return false;
}
Also used : ElkNode(org.eclipse.elk.graph.ElkNode) ElkPort(org.eclipse.elk.graph.ElkPort) ElkConnectableShape(org.eclipse.elk.graph.ElkConnectableShape) LinkedList(java.util.LinkedList) ElkEdge(org.eclipse.elk.graph.ElkEdge)

Example 30 with ElkEdge

use of org.eclipse.elk.graph.ElkEdge in project elk by eclipse.

the class RandomGraphGenerator method generateTriconnectedGraph.

// CHECKSTYLEON MagicNumber
/**
 * Generates a triconnected graph. The implementation is based upon the one used in the OGDF
 * library.
 *
 * @param parent
 *            the parent node
 * @param n
 *            the number of nodes
 * @param p1
 *            the probability for the first additional edge to be added
 * @param p2
 *            the probability for the second additional edge to be added
 * @param hierarchyLevel
 *            the current hierarchy level
 */
// CHECKSTYLEOFF MagicNumber
private void generateTriconnectedGraph(final ElkNode parent, final int n, final float p1, final float p2, final int hierarchyLevel) {
    int realN = Math.max(n, 4);
    // start with a clique of size 4
    List<ElkNode> cliqueNodes = createClique(parent, 4);
    // array of all nodes
    ElkNode[] nodes = new ElkNode[realN];
    int i = 0;
    for (ElkNode node : cliqueNodes) {
        nodes[i++] = node;
    }
    // array of neighbors
    ElkEdge[] neighbors = new ElkEdge[realN];
    // neighbor markings
    // 0 = not marked
    // 1 = marked left
    // 2 = marked right
    // 3 = marked both
    int[] marks = new int[n];
    // generate the graph
    for (; i < n; ++i) {
        ElkNode node = nodes[randomInt(0, i - 1)];
        // create a new node to split 'node' in two
        ElkNode newNode = createNode(parent);
        nodes[i] = newNode;
        // build array of all neighbors
        int d = node.getOutgoingEdges().size() + node.getIncomingEdges().size();
        int j = 0;
        for (ElkEdge edge : node.getOutgoingEdges()) {
            neighbors[j++] = edge;
        }
        for (ElkEdge edge : node.getIncomingEdges()) {
            neighbors[j++] = edge;
        }
        // mark two distinct neighbors for left
        for (j = 2; j > 0; ) {
            int r = randomInt(0, d - 1);
            if ((marks[r] & 1) == 0) {
                marks[r] |= 1;
                --j;
            }
        }
        // mark two distinct neighbors for right
        for (j = 2; j > 0; ) {
            int r = randomInt(0, d - 1);
            if ((marks[r] & 2) == 0) {
                marks[r] |= 2;
                --j;
            }
        }
        // perform the node-split
        for (j = 0; j < d; ++j) {
            int mark = marks[j];
            marks[j] = 0;
            // decide to with which node each neighbor is connected
            double x = random.nextDouble();
            switch(mark) {
                case 0:
                    if (x < p1) {
                        mark = 1;
                    } else if (x < p1 + p2) {
                        mark = 2;
                    } else {
                        mark = 3;
                    }
                    break;
                case 1:
                case 2:
                    if (x >= p1 + p2) {
                        mark = 3;
                    }
                    break;
            }
            // move edge or create new one if necessary
            ElkEdge edge = neighbors[j];
            switch(mark) {
                case 2:
                    if (edge.getSources().contains(node)) {
                        moveSource(edge, node, newNode);
                    } else {
                        moveTarget(edge, node, newNode);
                    }
                    break;
                case 3:
                    if (edge.getSources().contains(node)) {
                        connect(newNode, edge.getTargets().get(0));
                    } else {
                        connect(newNode, edge.getSources().get(0));
                    }
                    break;
            }
        }
        connect(node, newNode);
    }
    // recursively create hierarchy if applicable
    float hierarchyChance = get(GeneratorOptions.HIERARCHY_CHANCE);
    if (hierarchyChance > 0.0f && hierarchyLevel < maxHierarchyLevel) {
        for (ElkNode node : parent.getChildren()) {
            if (!isHypernode(node) && random.nextFloat() < hierarchyChance) {
                // determine the number of nodes in the compound node
                float hierarchyNodesFactor = get(GeneratorOptions.HIERARCHY_NODES_FACTOR);
                int cn = randomInt(1, (int) (hierarchyNodesFactor * n));
                generateTriconnectedGraph(node, cn, p1, p2, hierarchyLevel + 1);
            }
        }
    }
}
Also used : ElkNode(org.eclipse.elk.graph.ElkNode) ElkEdge(org.eclipse.elk.graph.ElkEdge)

Aggregations

ElkEdge (org.eclipse.elk.graph.ElkEdge)73 ElkNode (org.eclipse.elk.graph.ElkNode)59 ElkPort (org.eclipse.elk.graph.ElkPort)27 KVector (org.eclipse.elk.core.math.KVector)23 ElkEdgeSection (org.eclipse.elk.graph.ElkEdgeSection)21 ElkLabel (org.eclipse.elk.graph.ElkLabel)20 ElkConnectableShape (org.eclipse.elk.graph.ElkConnectableShape)10 LinkedList (java.util.LinkedList)9 ElkBendPoint (org.eclipse.elk.graph.ElkBendPoint)9 ElkGraphElement (org.eclipse.elk.graph.ElkGraphElement)9 SizeConstraint (org.eclipse.elk.core.options.SizeConstraint)8 Test (org.junit.Test)8 ArrayList (java.util.ArrayList)7 List (java.util.List)6 ElkPadding (org.eclipse.elk.core.math.ElkPadding)6 KVectorChain (org.eclipse.elk.core.math.KVectorChain)5 HashSet (java.util.HashSet)4 Lists (com.google.common.collect.Lists)3 Collection (java.util.Collection)3 Set (java.util.Set)3