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