Search in sources :

Example 1 with CNode

use of org.eclipse.elk.alg.common.compaction.oned.CNode in project elk by eclipse.

the class DebugUtil method drawHitboxes.

/**
 * For debugging. Writes hitboxes to svg.
 *
 * @param fileName
 *          filename.
 */
public static void drawHitboxes(final CGraph cGraph, final String fileName) {
    // determine viewBox
    KVector topLeft = new KVector(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
    KVector bottomRight = new KVector(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
    for (CNode cNode : cGraph.cNodes) {
        topLeft.x = Math.min(topLeft.x, cNode.hitbox.x);
        topLeft.y = Math.min(topLeft.y, cNode.hitbox.y);
        bottomRight.x = Math.max(bottomRight.x, cNode.hitbox.x + cNode.hitbox.width);
        bottomRight.y = Math.max(bottomRight.y, cNode.hitbox.y + cNode.hitbox.height);
    }
    KVector size = bottomRight.clone().sub(topLeft);
    // drawing hitboxes to svg
    PrintWriter out;
    try {
        out = new PrintWriter(new FileWriter(fileName));
        out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        out.println("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"100%\" height=\"100%\"" + "  viewBox=\"" + (topLeft.x) + " " + (topLeft.y) + " " + size.x + " " + size.y + "\">");
        out.println("<defs><marker id=\"markerArrow\" markerWidth=\"10\" " + "markerHeight=\"10\" refX=\"0\" refY=\"3\" orient=\"auto\">" + "  <path d=\"M0,0 L0,6 L9,3 z\" style=\"fill: #000000;\" />" + "</marker></defs>");
        for (CNode cNode : cGraph.cNodes) {
            // the node's representation
            out.println(cNode.getDebugSVG());
            // the constraints
            for (CNode inc : cNode.constraints) {
                out.println("<line x1=\"" + (inc.hitbox.x) + "\" y1=\"" + (inc.hitbox.y + inc.hitbox.height / 2) + "\" x2=\"" + (cNode.hitbox.x + cNode.hitbox.width) + "\" y2=\"" + (cNode.hitbox.y + cNode.hitbox.height / 2) + "\" stroke=\"black\" opacity=\"0.4\"" + " style=\"marker-end: url(#markerArrow);\" />");
            }
        }
        out.println("</svg>");
        out.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
Also used : CNode(org.eclipse.elk.alg.common.compaction.oned.CNode) FileWriter(java.io.FileWriter) IOException(java.io.IOException) KVector(org.eclipse.elk.core.math.KVector) PrintWriter(java.io.PrintWriter)

Example 2 with CNode

use of org.eclipse.elk.alg.common.compaction.oned.CNode in project elk by eclipse.

the class LGraphToCGraphTransformer method verticalSegmentToCNode.

private void verticalSegmentToCNode(final VerticalSegment verticalSegment) {
    // create CNode representation for the last segment
    CNode cNode = CNode.of().origin(verticalSegment).type("vs").hitbox(new ElkRectangle(verticalSegment.hitbox)).toStringDelegate(VS_TO_STRING_DELEGATE).create(cGraph);
    // assumption: during creation of LNode representing CNodes, these CNodes have been fitted with their own group
    if (!verticalSegment.potentialGroupParents.isEmpty()) {
        verticalSegment.potentialGroupParents.get(0).cGroup.addCNode(cNode);
    }
    Quadruplet vsLock = new Quadruplet();
    lockMap.put(cNode, vsLock);
    // segments belonging to multiple edges should be locked
    // in the direction that fewer different ports are connected in
    // (only used if LEFT_RIGHT_CONNECTION_LOCKING is active)
    Set<LPort> inc = Sets.newHashSet();
    Set<LPort> out = Sets.newHashSet();
    for (LEdge e : verticalSegment.representedLEdges) {
        inc.add(e.getSource());
        out.add(e.getTarget());
    }
    int difference = inc.size() - out.size();
    if (difference < 0) {
        vsLock.set(true, Direction.LEFT);
        vsLock.set(false, Direction.RIGHT);
    } else if (difference > 0) {
        vsLock.set(false, Direction.LEFT);
        vsLock.set(true, Direction.RIGHT);
    }
    verticalSegment.joined.forEach(other -> verticalSegmentsMap.put(other, cNode));
    verticalSegmentsMap.put(verticalSegment, cNode);
}
Also used : CNode(org.eclipse.elk.alg.common.compaction.oned.CNode) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) Quadruplet(org.eclipse.elk.alg.common.compaction.oned.Quadruplet) LPort(org.eclipse.elk.alg.layered.graph.LPort) ElkRectangle(org.eclipse.elk.core.math.ElkRectangle)

Example 3 with CNode

use of org.eclipse.elk.alg.common.compaction.oned.CNode in project elk by eclipse.

the class LGraphToCGraphTransformer method applyLayout.

/**
 * Apply the layout from the internal constraint graph back to the original lgraph.
 */
public void applyLayout() {
    // apply the compacted positions to nodes
    cGraph.cNodes.stream().filter(cNode -> cNode.origin instanceof LNode).forEach(cNode -> {
        LNode lNode = (LNode) cNode.origin;
        lNode.getPosition().x = cNode.hitbox.x + lNode.getMargin().left;
    });
    // adjust comment boxes
    applyCommentPositions();
    // apply new positions to vertical segments
    cGraph.cNodes.stream().filter(cNode -> cNode.origin instanceof VerticalSegment).forEach(cNode -> {
        double deltaX = cNode.hitbox.x - cNode.hitboxPreCompaction.x;
        VerticalSegment vs = (VerticalSegment) cNode.origin;
        vs.affectedBends.forEach(b -> b.x += deltaX);
        vs.affectedBoundingBoxes.forEach(bb -> bb.x += deltaX);
        vs.junctionPoints.forEach(jp -> jp.x += deltaX);
    });
    // be properly located in between non-straight parts
    if (edgeRouting == EdgeRouting.SPLINES) {
        // offset selfloops of splines
        nodesMap.keySet().stream().flatMap(n -> StreamSupport.stream(n.getOutgoingEdges().spliterator(), false)).filter(e -> e.isSelfLoop()).forEach(sl -> {
            LNode lNode = sl.getSource().getNode();
            CNode cNode = nodesMap.get(lNode);
            double deltaX = cNode.hitbox.x - cNode.hitboxPreCompaction.x;
            sl.getBendPoints().offset(deltaX, 0);
        });
        // offset straight segments
        layeredGraph.getLayers().stream().flatMap(l -> l.getNodes().stream()).flatMap(n -> StreamSupport.stream(n.getOutgoingEdges().spliterator(), false)).map(e -> e.getProperty(InternalProperties.SPLINE_ROUTE_START)).filter(chain -> chain != null && !chain.isEmpty()).forEach(spline -> adjustSplineControlPoints(spline));
    }
    // calculating new graph size and offset
    KVector topLeft = new KVector(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
    KVector bottomRight = new KVector(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
    for (CNode cNode : cGraph.cNodes) {
        topLeft.x = Math.min(topLeft.x, cNode.hitbox.x);
        topLeft.y = Math.min(topLeft.y, cNode.hitbox.y);
        bottomRight.x = Math.max(bottomRight.x, cNode.hitbox.x + cNode.hitbox.width);
        bottomRight.y = Math.max(bottomRight.y, cNode.hitbox.y + cNode.hitbox.height);
    }
    layeredGraph.getOffset().reset().add(topLeft.clone().negate());
    layeredGraph.getSize().reset().add(bottomRight.clone().sub(topLeft));
    // external port dummies may have been moved ... put them back
    applyExternalPortPositions(topLeft, bottomRight);
    cleanup();
}
Also used : Iterables(com.google.common.collect.Iterables) Layer(org.eclipse.elk.alg.layered.graph.Layer) PortSide(org.eclipse.elk.core.options.PortSide) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) Function(java.util.function.Function) LayeredOptions(org.eclipse.elk.alg.layered.options.LayeredOptions) ElkRectangle(org.eclipse.elk.core.math.ElkRectangle) Lists(com.google.common.collect.Lists) CGraph(org.eclipse.elk.alg.common.compaction.oned.CGraph) InternalProperties(org.eclipse.elk.alg.layered.options.InternalProperties) Map(java.util.Map) StreamSupport(java.util.stream.StreamSupport) Pair(org.eclipse.elk.core.util.Pair) EnumSet(java.util.EnumSet) NodeType(org.eclipse.elk.alg.layered.graph.LNode.NodeType) Iterator(java.util.Iterator) CGroup(org.eclipse.elk.alg.common.compaction.oned.CGroup) KVector(org.eclipse.elk.core.math.KVector) CompareFuzzy(org.eclipse.elk.alg.common.compaction.oned.CompareFuzzy) Set(java.util.Set) Maps(com.google.common.collect.Maps) Sets(com.google.common.collect.Sets) CNode(org.eclipse.elk.alg.common.compaction.oned.CNode) Objects(java.util.Objects) List(java.util.List) Quadruplet(org.eclipse.elk.alg.common.compaction.oned.Quadruplet) LGraph(org.eclipse.elk.alg.layered.graph.LGraph) Direction(org.eclipse.elk.core.options.Direction) Entry(java.util.Map.Entry) LPort(org.eclipse.elk.alg.layered.graph.LPort) EdgeRouting(org.eclipse.elk.core.options.EdgeRouting) LNode(org.eclipse.elk.alg.layered.graph.LNode) SplineSegment(org.eclipse.elk.alg.layered.p5edges.splines.SplineSegment) Collections(java.util.Collections) CNode(org.eclipse.elk.alg.common.compaction.oned.CNode) LNode(org.eclipse.elk.alg.layered.graph.LNode) KVector(org.eclipse.elk.core.math.KVector)

Example 4 with CNode

use of org.eclipse.elk.alg.common.compaction.oned.CNode in project elk by eclipse.

the class LGraphToCGraphTransformer method transformNodes.

private void transformNodes() {
    for (Layer layer : layeredGraph) {
        for (LNode node : layer) {
            // of other nodes overlapping them after compaction
            if (node.getProperty(LayeredOptions.COMMENT_BOX)) {
                if (!Iterables.isEmpty(node.getConnectedEdges())) {
                    LEdge e = Iterables.get(node.getConnectedEdges(), 0);
                    LNode other = e.getSource().getNode();
                    if (other == node) {
                        other = e.getTarget().getNode();
                    }
                    Pair<LNode, KVector> p = Pair.of(other, node.getPosition().clone().sub(other.getPosition()));
                    commentOffsets.put(node, p);
                    continue;
                }
            }
            ElkRectangle hitbox = new ElkRectangle(node.getPosition().x - node.getMargin().left, node.getPosition().y - node.getMargin().top, node.getSize().x + node.getMargin().left + node.getMargin().right, node.getSize().y + node.getMargin().top + node.getMargin().bottom);
            // create the node in the compaction graph
            CNode cNode = CNode.of().origin(node).hitbox(hitbox).toStringDelegate(NODE_TO_STRING_DELEGATE).create(cGraph);
            // the node lives in its own group
            CGroup.of().nodes(cNode).master(cNode).create(cGraph);
            Quadruplet nodeLock = new Quadruplet();
            lockMap.put(cNode, nodeLock);
            // locking the node for directions that fewer edges are connected in
            // (only used if LEFT_RIGHT_CONNECTION_LOCKING is used)
            int difference = Iterables.size(node.getIncomingEdges()) - Iterables.size(node.getOutgoingEdges());
            if (difference < 0) {
                nodeLock.set(true, Direction.LEFT);
            } else if (difference > 0) {
                nodeLock.set(true, Direction.RIGHT);
            }
            // excluding external port dummies
            if (node.getType() == NodeType.EXTERNAL_PORT) {
                nodeLock.set(false, false, false, false);
            }
            nodesMap.put(node, cNode);
        }
    }
}
Also used : CNode(org.eclipse.elk.alg.common.compaction.oned.CNode) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) Quadruplet(org.eclipse.elk.alg.common.compaction.oned.Quadruplet) LNode(org.eclipse.elk.alg.layered.graph.LNode) KVector(org.eclipse.elk.core.math.KVector) ElkRectangle(org.eclipse.elk.core.math.ElkRectangle) Layer(org.eclipse.elk.alg.layered.graph.Layer)

Example 5 with CNode

use of org.eclipse.elk.alg.common.compaction.oned.CNode in project elk by eclipse.

the class LGraphToCGraphTransformer method collectVerticalSegmentsOrthogonal.

private List<VerticalSegment> collectVerticalSegmentsOrthogonal() {
    List<VerticalSegment> verticalSegments = Lists.newArrayList();
    for (Layer layer : layeredGraph) {
        for (LNode node : layer) {
            final CNode cNode = nodesMap.get(node);
            // add vertical edge segments
            for (LEdge edge : node.getOutgoingEdges()) {
                Iterator<KVector> bends = edge.getBendPoints().iterator();
                boolean first = true;
                VerticalSegment lastSegment = null;
                // infer vertical segments from positions of bendpoints
                if (bends.hasNext()) {
                    KVector bend1 = bends.next();
                    KVector bend2 = null;
                    // get segment of source n/s port of outgoing segment
                    if (edge.getSource().getSide() == PortSide.NORTH) {
                        VerticalSegment vs = new VerticalSegment(bend1, new KVector(bend1.x, cNode.hitbox.y), cNode, edge);
                        vs.ignoreSpacing.down = true;
                        vs.aPort = edge.getSource();
                        verticalSegments.add(vs);
                    }
                    if (edge.getSource().getSide() == PortSide.SOUTH) {
                        VerticalSegment vs = new VerticalSegment(bend1, new KVector(bend1.x, cNode.hitbox.y + cNode.hitbox.height), cNode, edge);
                        vs.ignoreSpacing.up = true;
                        vs.aPort = edge.getSource();
                        verticalSegments.add(vs);
                    }
                    // get regular segments
                    while (bends.hasNext()) {
                        bend2 = bends.next();
                        if (!CompareFuzzy.eq(bend1.y, bend2.y)) {
                            lastSegment = new VerticalSegment(bend1, bend2, null, edge);
                            verticalSegments.add(lastSegment);
                            // the first vertical segment of an outgoing edge
                            if (first) {
                                first = false;
                                // to route the edges away from the nodes, does not become an issue
                                if (bend2.y < cNode.hitbox.y) {
                                    lastSegment.ignoreSpacing.down = true;
                                } else if (bend2.y > cNode.hitbox.y + cNode.hitbox.height) {
                                    lastSegment.ignoreSpacing.up = true;
                                } else {
                                    // completely surrounded
                                    lastSegment.ignoreSpacing.up = true;
                                    lastSegment.ignoreSpacing.down = true;
                                }
                            }
                        }
                        if (bends.hasNext()) {
                            bend1 = bend2;
                        }
                    }
                    // handle last vertical segment
                    if (lastSegment != null) {
                        CNode cTargetNode = nodesMap.get(edge.getTarget().getNode());
                        if (bend1.y < cTargetNode.hitbox.y) {
                            lastSegment.ignoreSpacing.down = true;
                        } else if (bend1.y > cTargetNode.hitbox.y + cTargetNode.hitbox.height) {
                            lastSegment.ignoreSpacing.up = true;
                        } else {
                            // completely surrounded
                            lastSegment.ignoreSpacing.up = true;
                            lastSegment.ignoreSpacing.down = true;
                        }
                    }
                }
            }
            // same for incoming edges to get north/south segments on target side
            for (LEdge edge : node.getIncomingEdges()) {
                if (!edge.getBendPoints().isEmpty()) {
                    // get segment of target n/s port
                    KVector bend1 = edge.getBendPoints().getLast();
                    if (edge.getTarget().getSide() == PortSide.NORTH) {
                        VerticalSegment vs = new VerticalSegment(bend1, new KVector(bend1.x, cNode.hitbox.y), cNode, edge);
                        vs.ignoreSpacing.down = true;
                        vs.aPort = edge.getTarget();
                        verticalSegments.add(vs);
                    }
                    if (edge.getTarget().getSide() == PortSide.SOUTH) {
                        VerticalSegment vs = new VerticalSegment(bend1, new KVector(bend1.x, cNode.hitbox.y + cNode.hitbox.height), cNode, edge);
                        vs.ignoreSpacing.up = true;
                        vs.aPort = edge.getTarget();
                        verticalSegments.add(vs);
                    }
                }
            }
        }
    }
    return verticalSegments;
}
Also used : CNode(org.eclipse.elk.alg.common.compaction.oned.CNode) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) LNode(org.eclipse.elk.alg.layered.graph.LNode) KVector(org.eclipse.elk.core.math.KVector) Layer(org.eclipse.elk.alg.layered.graph.Layer)

Aggregations

CNode (org.eclipse.elk.alg.common.compaction.oned.CNode)11 LEdge (org.eclipse.elk.alg.layered.graph.LEdge)5 LNode (org.eclipse.elk.alg.layered.graph.LNode)5 LPort (org.eclipse.elk.alg.layered.graph.LPort)4 KVector (org.eclipse.elk.core.math.KVector)4 Quadruplet (org.eclipse.elk.alg.common.compaction.oned.Quadruplet)3 NNode (org.eclipse.elk.alg.common.networksimplex.NNode)3 Layer (org.eclipse.elk.alg.layered.graph.Layer)3 ElkRectangle (org.eclipse.elk.core.math.ElkRectangle)3 CGroup (org.eclipse.elk.alg.common.compaction.oned.CGroup)2 SplineSegment (org.eclipse.elk.alg.layered.p5edges.splines.SplineSegment)2 EdgeRouting (org.eclipse.elk.core.options.EdgeRouting)2 Iterables (com.google.common.collect.Iterables)1 Lists (com.google.common.collect.Lists)1 Maps (com.google.common.collect.Maps)1 Sets (com.google.common.collect.Sets)1 FileWriter (java.io.FileWriter)1 IOException (java.io.IOException)1 PrintWriter (java.io.PrintWriter)1 Collections (java.util.Collections)1