use of org.eclipse.elk.core.math.ElkRectangle in project elk by eclipse.
the class NodeMarginCalculator method processNode.
/**
* Calculates the margin of the given node.
*
* @param node the node whose margin to calculate.
* @param labelSpacing label spacing set on the layered graph.
*/
private void processNode(final NodeAdapter<?> node, final double labelSpacing) {
// This will be our bounding box. We'll start with one that's the same size
// as our node, and at the same position.
ElkRectangle boundingBox = new ElkRectangle(node.getPosition().x, node.getPosition().y, node.getSize().x, node.getSize().y);
// We'll reuse this rectangle as our box for elements to add to the bounding box
ElkRectangle elementBox = new ElkRectangle();
// Put the node's labels into the bounding box
if (includeLabels) {
for (LabelAdapter<?> label : node.getLabels()) {
elementBox.x = label.getPosition().x + node.getPosition().x;
elementBox.y = label.getPosition().y + node.getPosition().y;
elementBox.width = label.getSize().x;
elementBox.height = label.getSize().y;
boundingBox.union(elementBox);
}
}
// Do the same for ports and their labels
for (PortAdapter<?> port : node.getPorts()) {
// Calculate the port's upper left corner's x and y coordinate
double portX = port.getPosition().x + node.getPosition().x;
double portY = port.getPosition().y + node.getPosition().y;
// The port itself
if (includePorts) {
elementBox.x = portX;
elementBox.y = portY;
elementBox.width = port.getSize().x;
elementBox.height = port.getSize().y;
boundingBox.union(elementBox);
}
// The port's labels
if (includePortLabels) {
for (LabelAdapter<?> label : port.getLabels()) {
elementBox.x = label.getPosition().x + portX;
elementBox.y = label.getPosition().y + portY;
elementBox.width = label.getSize().x;
elementBox.height = label.getSize().y;
boundingBox.union(elementBox);
}
}
// End labels of edges connected to the port
if (includeEdgeHeadTailLabels) {
KVector requiredPortLabelSpace = new KVector(-labelSpacing, -labelSpacing);
// TODO: maybe leave space for manually placed ports
if (node.getProperty(CoreOptions.PORT_LABELS_PLACEMENT).contains(PortLabelPlacement.OUTSIDE)) {
for (LabelAdapter<?> label : port.getLabels()) {
requiredPortLabelSpace.x += label.getSize().x + labelSpacing;
requiredPortLabelSpace.y += label.getSize().y + labelSpacing;
}
}
requiredPortLabelSpace.x = Math.max(requiredPortLabelSpace.x, 0.0);
requiredPortLabelSpace.y = Math.max(requiredPortLabelSpace.y, 0.0);
processEdgeHeadTailLabels(boundingBox, port.getOutgoingEdges(), port.getIncomingEdges(), node, port, requiredPortLabelSpace, labelSpacing);
}
}
// Process end labels of edges directly connected to the node
if (includeEdgeHeadTailLabels) {
processEdgeHeadTailLabels(boundingBox, node.getOutgoingEdges(), node.getIncomingEdges(), node, null, null, labelSpacing);
}
// Reset the margin (guard against very small double precision errors which can cause the results to be small
// negative values, which doesn't make sense -- see #616)
ElkMargin margin = new ElkMargin(node.getMargin());
margin.top = Math.max(0, node.getPosition().y - boundingBox.y);
margin.bottom = Math.max(0, boundingBox.y + boundingBox.height - (node.getPosition().y + node.getSize().y));
margin.left = Math.max(0, node.getPosition().x - boundingBox.x);
margin.right = Math.max(0, boundingBox.x + boundingBox.width - (node.getPosition().x + node.getSize().x));
node.setMargin(margin);
}
use of org.eclipse.elk.core.math.ElkRectangle in project elk by eclipse.
the class NodeMarginCalculator method processEdgeHeadTailLabels.
/**
* Adds the bounding boxes of the head or tail labels of the given sets of outgoing and incoming
* edges to the given bounding box.
*
* @param boundingBox the bounding box that should be enlarged to include head and tail labels.
* @param outgoingEdges set of outgoing edges whose tail labels should be included.
* @param incomingEdges set of incoming edges whose head labels should be included.
* @param node the node we're processing labels for.
* @param port the port if the edges are connected to one.
* @param portLabelSpace if the edges are connected to a port, this is the space required to
* place the port's labels.
* @param labelSpacing label spacing.
*/
private void processEdgeHeadTailLabels(final ElkRectangle boundingBox, final Iterable<EdgeAdapter<?>> outgoingEdges, final Iterable<EdgeAdapter<?>> incomingEdges, final NodeAdapter<?> node, final PortAdapter<?> port, final KVector portLabelSpace, final double labelSpacing) {
ElkRectangle labelBox = new ElkRectangle();
// For each edge, the tail labels of outgoing edges ...
for (EdgeAdapter<?> edge : outgoingEdges) {
for (LabelAdapter<?> label : edge.getLabels()) {
if (label.getProperty(CoreOptions.EDGE_LABELS_PLACEMENT) == EdgeLabelPlacement.TAIL) {
computeLabelBox(labelBox, label, false, node, port, portLabelSpace, labelSpacing);
boundingBox.union(labelBox);
}
}
}
// ... and the head label of incoming edges shall be considered
for (EdgeAdapter<?> edge : incomingEdges) {
for (LabelAdapter<?> label : edge.getLabels()) {
if (label.getProperty(CoreOptions.EDGE_LABELS_PLACEMENT) == EdgeLabelPlacement.HEAD) {
computeLabelBox(labelBox, label, true, node, port, portLabelSpace, labelSpacing);
boundingBox.union(labelBox);
}
}
}
}
use of org.eclipse.elk.core.math.ElkRectangle in project elk by eclipse.
the class DepthFirstCompaction method compactTree.
/**
* Recursive function to compact a tree depth-first.
* @param tree root of a tree
*/
private static void compactTree(final Tree<Node> tree) {
// first compact the children of the current node
tree.children.forEach(DepthFirstCompaction::compactTree);
// remove underlap between root and its children
for (Tree<Node> child : tree.children) {
// find the direction and distance the subtree has to be moved to close the gap to the root node
KVector compactionVector = tree.node.vertex.clone().sub(child.node.vertex);
if (orthogonalCompaction) {
ElkRectangle rt = tree.node.rect;
ElkRectangle rc = child.node.rect;
// restrict the compaction vector to its larger coordinate
if (Math.abs(compactionVector.x) >= Math.abs(compactionVector.y)) {
compactionVector.y = 0;
// scale compaction vector to orthogonal distance between tree and child
if (rc.y + rc.height > rt.y && rc.y < rt.y + rt.height) {
// overlap in vertical dimension
compactionVector.scaleToLength(Math.max(rt.x - (rc.x + rc.width), rc.x - (rt.x + rt.width)));
}
} else {
compactionVector.x = 0;
// scale compaction vector to orthogonal distance between tree and child
if (rc.x + rc.width > rt.x && rc.x < rt.x + rt.width) {
// overlap in horizontal dimension
compactionVector.scaleToLength(Math.max(rt.y - (rc.y + rc.height), rc.y - (rt.y + rt.height)));
}
}
} else {
compactionVector.scaleToLength(tree.node.underlap(child.node));
}
// determine the maximum distance the subtree can be moved without collision, i.e. the minimum underlap
double minUnderlap = compactionVector.length();
// find minimum underlap between any node in the child and any other node in the rest of the
// tree in compaction direction
minUnderlap = getMinUnderlap(root, child, minUnderlap, compactionVector);
// use the minimum underlap to move whole subtree
compactionVector.scaleToLength(minUnderlap);
translateSubtree(child, compactionVector);
debugOut(tree, child);
}
}
use of org.eclipse.elk.core.math.ElkRectangle in project elk by eclipse.
the class ContainerCell method applyHorizontalLayout.
/**
* Applies the given horizontal layout information to the given cell if it's not {@code null}.
*
* @param cell
* the cell to apply the layout information to.
* @param x
* the cell's new x coordinate.
* @param width
* the cell's new width.
*/
protected void applyHorizontalLayout(final Cell cell, final double x, final double width) {
if (cell != null) {
ElkRectangle cellRect = cell.getCellRectangle();
cellRect.x = x;
cellRect.width = width;
}
}
use of org.eclipse.elk.core.math.ElkRectangle in project elk by eclipse.
the class ContainerCell method applyVerticalLayout.
/**
* Applies the given vertical layout information to the given cell if it's not {@code null}.
*
* @param cell
* the cell to apply the layout information to.
* @param y
* the cell's new y coordinate.
* @param height
* the cell's new height.
*/
protected void applyVerticalLayout(final Cell cell, final double y, final double height) {
if (cell != null) {
ElkRectangle cellRect = cell.getCellRectangle();
cellRect.y = y;
cellRect.height = height;
}
}
Aggregations