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);
}
}
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;
}
}
}
}
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);
}
}
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;
}
}
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;
}
Aggregations