Search in sources :

Example 1 with SplineSegment

use of org.eclipse.elk.alg.layered.p5edges.splines.SplineSegment in project elk by eclipse.

the class FinalSplineBendpointsCalculator method process.

@Override
public void process(final LGraph graph, final IElkProgressMonitor progressMonitor) {
    this.edgeEdgeSpacing = graph.getProperty(LayeredOptions.SPACING_EDGE_EDGE_BETWEEN_LAYERS);
    this.edgeNodeSpacing = graph.getProperty(LayeredOptions.SPACING_EDGE_NODE_BETWEEN_LAYERS);
    this.splineRoutingMode = graph.getProperty(LayeredOptions.EDGE_ROUTING_SPLINES_MODE);
    this.compactionStrategy = graph.getProperty(LayeredOptions.COMPACTION_POST_COMPACTION_STRATEGY);
    // assign indices to nodes to efficiently query neighbors within the same layer
    indexNodesPerLayer(graph);
    // collect all edges that represent the first segment of a spline
    List<LEdge> startEdges = graph.getLayers().stream().flatMap(l -> l.getNodes().stream()).flatMap(n -> StreamSupport.stream(n.getOutgoingEdges().spliterator(), false)).filter(e -> !e.isSelfLoop()).filter(e -> e.hasProperty(InternalProperties.SPLINE_ROUTE_START)).collect(Collectors.toList());
    // first determine the NUB control points
    for (LEdge e : startEdges) {
        List<SplineSegment> spline = e.getProperty(InternalProperties.SPLINE_ROUTE_START);
        spline.forEach(s -> calculateControlPoints(s));
        e.setProperty(InternalProperties.SPLINE_ROUTE_START, null);
    }
    // ... then convert them to bezier splines
    for (LEdge e : startEdges) {
        // may be null
        LEdge survivingEdge = e.getProperty(InternalProperties.SPLINE_SURVIVING_EDGE);
        List<LEdge> edgeChain = e.getProperty(InternalProperties.SPLINE_EDGE_CHAIN);
        calculateBezierBendPoints(edgeChain, survivingEdge);
        // clear property
        e.setProperty(InternalProperties.SPLINE_EDGE_CHAIN, null);
    }
}
Also used : Layer(org.eclipse.elk.alg.layered.graph.Layer) SplinesMath(org.eclipse.elk.alg.layered.p5edges.splines.SplinesMath) PortSide(org.eclipse.elk.core.options.PortSide) IElkProgressMonitor(org.eclipse.elk.core.util.IElkProgressMonitor) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) ILayoutProcessor(org.eclipse.elk.core.alg.ILayoutProcessor) LayeredOptions(org.eclipse.elk.alg.layered.options.LayeredOptions) KVectorChain(org.eclipse.elk.core.math.KVectorChain) NubSpline(org.eclipse.elk.alg.layered.p5edges.splines.NubSpline) ElkRectangle(org.eclipse.elk.core.math.ElkRectangle) InternalProperties(org.eclipse.elk.alg.layered.options.InternalProperties) StreamSupport(java.util.stream.StreamSupport) Iterator(java.util.Iterator) EdgeInformation(org.eclipse.elk.alg.layered.p5edges.splines.SplineSegment.EdgeInformation) KVector(org.eclipse.elk.core.math.KVector) Collectors(java.util.stream.Collectors) LMargin(org.eclipse.elk.alg.layered.graph.LMargin) GraphCompactionStrategy(org.eclipse.elk.alg.layered.options.GraphCompactionStrategy) HorizontalGraphCompactor(org.eclipse.elk.alg.layered.intermediate.compaction.HorizontalGraphCompactor) ElkMath(org.eclipse.elk.core.math.ElkMath) SplineRoutingMode(org.eclipse.elk.alg.layered.options.SplineRoutingMode) List(java.util.List) SplineEdgeRouter(org.eclipse.elk.alg.layered.p5edges.splines.SplineEdgeRouter) LGraph(org.eclipse.elk.alg.layered.graph.LGraph) LPort(org.eclipse.elk.alg.layered.graph.LPort) LNode(org.eclipse.elk.alg.layered.graph.LNode) SplineSegment(org.eclipse.elk.alg.layered.p5edges.splines.SplineSegment) Collections(java.util.Collections) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) SplineSegment(org.eclipse.elk.alg.layered.p5edges.splines.SplineSegment)

Example 2 with SplineSegment

use of org.eclipse.elk.alg.layered.p5edges.splines.SplineSegment in project elk by eclipse.

the class LGraphToCGraphTransformer method adjustSplineControlPoints.

/**
 * Adjust the control points of the straight segments of the passed spline. The control points of non-straight
 * segments are directly represented by {@link CNode}s during compaction and thus adjusted during the compaction
 * process.
 */
private void adjustSplineControlPoints(final List<SplineSegment> spline) {
    if (spline.isEmpty()) {
        return;
    }
    SplineSegment lastSeg = spline.get(0);
    // first case: a signle segment
    if (spline.size() == 1) {
        // the two indexes are selected such that the method's loop runs exactly once
        adjustControlPointBetweenSegments(lastSeg, lastSeg, 1, 0, spline);
        return;
    }
    // ... more than one segment
    int i = 1;
    while (i < spline.size()) {
        if (lastSeg.initialSegment || !lastSeg.isStraight) {
            // find the next non-straight segment (or the very last segment of this spline)
            Pair<Integer, SplineSegment> needle = firstNonStraightSegment(spline, i);
            if (needle != null) {
                int j = needle.getFirst();
                SplineSegment nextSeg = needle.getSecond();
                adjustControlPointBetweenSegments(lastSeg, nextSeg, i, j, spline);
                i = j + 1;
                lastSeg = nextSeg;
            }
        }
    }
}
Also used : SplineSegment(org.eclipse.elk.alg.layered.p5edges.splines.SplineSegment)

Example 3 with SplineSegment

use of org.eclipse.elk.alg.layered.p5edges.splines.SplineSegment in project elk by eclipse.

the class BreakingPointRemover method remove.

private void remove(final LGraph graph, final BPInfo bpi) {
    // assemble the new edge route
    KVectorChain newBends = new KVectorChain();
    // depending on the edge routing style we have to act differently
    switch(edgeRouting) {
        // so far, only the intermediate nubsplines have been attached via properties
        case SPLINES:
            // gather the computed spline information
            List<SplineSegment> s1 = bpi.nodeStartEdge.getProperty(InternalProperties.SPLINE_ROUTE_START);
            List<SplineSegment> s2 = bpi.startEndEdge.getProperty(InternalProperties.SPLINE_ROUTE_START);
            List<SplineSegment> s3 = bpi.originalEdge.getProperty(InternalProperties.SPLINE_ROUTE_START);
            List<LEdge> e1 = bpi.nodeStartEdge.getProperty(InternalProperties.SPLINE_EDGE_CHAIN);
            List<LEdge> e2 = bpi.startEndEdge.getProperty(InternalProperties.SPLINE_EDGE_CHAIN);
            List<LEdge> e3 = bpi.originalEdge.getProperty(InternalProperties.SPLINE_EDGE_CHAIN);
            // join them (... and remember to reverse some of the segments)
            List<SplineSegment> joinedSegments = Lists.newArrayList();
            joinedSegments.addAll(s1);
            s2.forEach(s -> s.inverseOrder = true);
            joinedSegments.addAll(Lists.reverse(s2));
            joinedSegments.addAll(s3);
            List<LEdge> joinedEdges = Lists.newArrayList();
            joinedEdges.addAll(e1);
            joinedEdges.addAll(Lists.reverse(e2));
            joinedEdges.addAll(e3);
            // transfer the information to the original edge
            bpi.originalEdge.setProperty(InternalProperties.SPLINE_ROUTE_START, joinedSegments);
            bpi.originalEdge.setProperty(InternalProperties.SPLINE_EDGE_CHAIN, joinedEdges);
            bpi.originalEdge.setProperty(InternalProperties.SPLINE_SURVIVING_EDGE, bpi.originalEdge);
            // cleanup
            bpi.nodeStartEdge.setProperty(InternalProperties.SPLINE_ROUTE_START, null);
            bpi.nodeStartEdge.setProperty(InternalProperties.SPLINE_EDGE_CHAIN, null);
            bpi.startEndEdge.setProperty(InternalProperties.SPLINE_ROUTE_START, null);
            bpi.startEndEdge.setProperty(InternalProperties.SPLINE_EDGE_CHAIN, null);
            break;
        // note that the positions of bpi.start and bpi.end must be added as bend points
        case POLYLINE:
            newBends.addAll(bpi.nodeStartEdge.getBendPoints());
            newBends.add(bpi.start.getPosition());
            newBends.addAll(Lists.reverse(bpi.startEndEdge.getBendPoints()));
            newBends.add(bpi.end.getPosition());
            newBends.addAll(bpi.originalEdge.getBendPoints());
            break;
        // of bpi.start and bpi.end can be dropped since they lie on a straight line
        default:
            // ORTHOGONAL
            newBends.addAll(bpi.nodeStartEdge.getBendPoints());
            newBends.addAll(Lists.reverse(bpi.startEndEdge.getBendPoints()));
            newBends.addAll(bpi.originalEdge.getBendPoints());
    }
    // restore original edge
    bpi.originalEdge.getBendPoints().clear();
    bpi.originalEdge.getBendPoints().addAll(newBends);
    bpi.originalEdge.setSource(bpi.nodeStartEdge.getSource());
    // collect any created junction points (order can be arbitrary)
    KVectorChain junctionPointsOne = bpi.nodeStartEdge.getProperty(LayeredOptions.JUNCTION_POINTS);
    KVectorChain junctionPointsTwo = bpi.startEndEdge.getProperty(LayeredOptions.JUNCTION_POINTS);
    KVectorChain junctionPointsThree = bpi.originalEdge.getProperty(LayeredOptions.JUNCTION_POINTS);
    if (junctionPointsOne != null || junctionPointsTwo != null || junctionPointsThree != null) {
        KVectorChain newJunctionPoints = new KVectorChain();
        addNullSafe(newJunctionPoints, junctionPointsThree);
        addNullSafe(newJunctionPoints, junctionPointsTwo);
        addNullSafe(newJunctionPoints, junctionPointsOne);
        bpi.originalEdge.setProperty(LayeredOptions.JUNCTION_POINTS, newJunctionPoints);
    }
    // remove all the dummy stuff
    bpi.startEndEdge.setSource(null);
    bpi.startEndEdge.setTarget(null);
    bpi.nodeStartEdge.setSource(null);
    bpi.nodeStartEdge.setTarget(null);
    bpi.end.setLayer(null);
    bpi.start.setLayer(null);
    if (bpi.prev != null) {
        remove(graph, bpi.prev);
    }
}
Also used : KVectorChain(org.eclipse.elk.core.math.KVectorChain) LEdge(org.eclipse.elk.alg.layered.graph.LEdge) SplineSegment(org.eclipse.elk.alg.layered.p5edges.splines.SplineSegment)

Example 4 with SplineSegment

use of org.eclipse.elk.alg.layered.p5edges.splines.SplineSegment in project elk by eclipse.

the class LGraphToCGraphTransformer method adjustControlPointBetweenSegments.

/**
 * Adjust the control points of the sequence of spline segments {@code left, ..., right}. The {@code left} and
 * {@code right} segments do not have to be straight in which case they are dropped from the sequence and their
 * positions remain unaltered. For the remaining sequence of length {@code n}, the left-most and right-most
 * coordinate of the straight path are determined. The center control points of the sequence's segments are then
 * distributed equidistantly on this path.
 */
private void adjustControlPointBetweenSegments(final SplineSegment left, final SplineSegment right, final int leftIdx, final int rightIdx, final List<SplineSegment> spline) {
    // check if the initial segment of the spline is a straight one
    double startX;
    int idx1 = leftIdx;
    if (left.initialSegment && left.isStraight) {
        CNode n = nodesMap.get(left.sourceNode);
        startX = n.hitbox.x + n.hitbox.width;
        idx1--;
    } else {
        startX = left.boundingBox.x + left.boundingBox.width;
    }
    // ... the same for the last segment
    double endX;
    int idx2 = rightIdx;
    if (right.lastSegment && right.isStraight) {
        CNode n = nodesMap.get(right.targetNode);
        endX = n.hitbox.x;
        idx2++;
    } else {
        endX = right.boundingBox.x;
    }
    // divide the available space into equidistant chunks
    double strip = endX - startX;
    int chunks = Math.max(2, idx2 - idx1);
    double chunk = strip / chunks;
    // apply new positions to the control points
    double newPos = startX + chunk;
    for (int k = idx1; k < idx2; ++k) {
        SplineSegment adjust = spline.get(k);
        double width = adjust.boundingBox.width;
        adjust.boundingBox.x = newPos - width / 2;
        newPos += chunk;
    }
}
Also used : CNode(org.eclipse.elk.alg.common.compaction.oned.CNode) SplineSegment(org.eclipse.elk.alg.layered.p5edges.splines.SplineSegment)

Example 5 with SplineSegment

use of org.eclipse.elk.alg.layered.p5edges.splines.SplineSegment in project elk by eclipse.

the class LGraphToCGraphTransformer method collectVerticalSegmentsSplines.

private List<VerticalSegment> collectVerticalSegmentsSplines() {
    List<VerticalSegment> verticalSegments = Lists.newArrayList();
    layeredGraph.getLayers().stream().flatMap(l -> l.getNodes().stream()).flatMap(n -> StreamSupport.stream(n.getOutgoingEdges().spliterator(), false)).map(out -> out.getProperty(InternalProperties.SPLINE_ROUTE_START)).filter(Objects::nonNull).forEach(spline -> {
        VerticalSegment lastVs = null;
        for (SplineSegment s : spline) {
            if (s.isStraight) {
                continue;
            }
            KVector leftTop = s.boundingBox.getTopLeft();
            KVector rightBottom = s.boundingBox.getBottomRight();
            VerticalSegment vs = new VerticalSegment(leftTop, rightBottom, null, s.edges.iterator().next());
            vs.affectedBoundingBoxes.add(s.boundingBox);
            verticalSegments.add(vs);
            // remember that there has to be a constraint between the two (non-straight) segments
            if (lastVs != null) {
                lastVs.constraints.add(vs);
            }
            lastVs = vs;
        }
    });
    return verticalSegments;
}
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) SplineSegment(org.eclipse.elk.alg.layered.p5edges.splines.SplineSegment) KVector(org.eclipse.elk.core.math.KVector)

Aggregations

SplineSegment (org.eclipse.elk.alg.layered.p5edges.splines.SplineSegment)5 LEdge (org.eclipse.elk.alg.layered.graph.LEdge)3 Collections (java.util.Collections)2 Iterator (java.util.Iterator)2 List (java.util.List)2 StreamSupport (java.util.stream.StreamSupport)2 CNode (org.eclipse.elk.alg.common.compaction.oned.CNode)2 LGraph (org.eclipse.elk.alg.layered.graph.LGraph)2 LNode (org.eclipse.elk.alg.layered.graph.LNode)2 LPort (org.eclipse.elk.alg.layered.graph.LPort)2 Layer (org.eclipse.elk.alg.layered.graph.Layer)2 InternalProperties (org.eclipse.elk.alg.layered.options.InternalProperties)2 LayeredOptions (org.eclipse.elk.alg.layered.options.LayeredOptions)2 ElkRectangle (org.eclipse.elk.core.math.ElkRectangle)2 KVector (org.eclipse.elk.core.math.KVector)2 KVectorChain (org.eclipse.elk.core.math.KVectorChain)2 PortSide (org.eclipse.elk.core.options.PortSide)2 Iterables (com.google.common.collect.Iterables)1 Lists (com.google.common.collect.Lists)1 Maps (com.google.common.collect.Maps)1