use of org.eclipse.elk.graph.ElkNode in project elk by eclipse.
the class Calculations method calculateXforLPB.
/**
* Calculates the x-coordinate after shift of the rectangle to be placed below the last placed rectangle.
*
* @param placedRects A list of already placed rectangles.
* @param y The y-coordinate of the rectangle to be placed.
* @param lastPlaced The most recently placed rectangle.
* @return The x-coordinate after shift of the rectangle to be placed below lastPlaced.
*/
protected static double calculateXforLPB(final double y, final List<ElkNode> placedRects, final ElkNode lastPlaced, final double nodeNodeSpacing) {
ElkNode closestLeftNeighbour = null;
double closestNeighborRightBorder = 0;
// Find neighbors that lay in between the height of the rectangle to be placed.
for (ElkNode placedRect : placedRects) {
double placedRectRightBorder = placedRect.getX() + placedRect.getWidth();
if (horizontalOrderConstraint(placedRect, y, nodeNodeSpacing)) {
// Is closest neighbor?
if (closestLeftNeighbour == null) {
closestLeftNeighbour = placedRect;
} else if (lastPlaced.getX() - placedRectRightBorder < lastPlaced.getX() - closestNeighborRightBorder) {
closestLeftNeighbour = placedRect;
}
closestNeighborRightBorder = closestLeftNeighbour.getX() + closestLeftNeighbour.getWidth();
}
}
// No neighbor yet.
if (closestLeftNeighbour == null) {
return 0;
} else {
// Else, choose closest neighbors right border
return closestNeighborRightBorder + nodeNodeSpacing;
}
}
use of org.eclipse.elk.graph.ElkNode in project elk by eclipse.
the class ElkGraphImporter method updateGraph.
@Override
public void updateGraph(final Graph g) {
Map<KVector, Pair<Node, ElkNode>> updatedNodeMap = Maps.newHashMap();
// reset graph
g.tEdges = null;
g.tree = null;
// update nodes
for (Node n : g.vertices) {
Pair<Node, ElkNode> original = nodeMap.get(n.originalVertex);
n.originalVertex = n.rect.getCenter();
updatedNodeMap.put(n.originalVertex, original);
}
nodeMap = updatedNodeMap;
}
use of org.eclipse.elk.graph.ElkNode in project elk by eclipse.
the class ElkGraphImporter method importGraph.
@Override
public Graph importGraph(final ElkNode inputGraph) {
elkGraph = inputGraph;
nodeMap = Maps.newHashMap();
// calculate margins
ElkGraphAdapter adapter = ElkGraphAdapters.adapt(elkGraph);
NodeDimensionCalculation.calculateNodeMargins(adapter);
// retrieve layout options
String preferredRootID = elkGraph.getProperty(SporeCompactionOptions.PROCESSING_ORDER_PREFERRED_ROOT);
SpanningTreeCostFunction costFunctionID = elkGraph.getProperty(SporeCompactionOptions.PROCESSING_ORDER_SPANNING_TREE_COST_FUNCTION);
TreeConstructionStrategy treeConstructionStrategy = elkGraph.getProperty(SporeCompactionOptions.PROCESSING_ORDER_TREE_CONSTRUCTION);
CompactionStrategy compactionStrategy = elkGraph.getProperty(SporeCompactionOptions.COMPACTION_COMPACTION_STRATEGY);
RootSelection rootSelection = elkGraph.getProperty(SporeCompactionOptions.PROCESSING_ORDER_ROOT_SELECTION);
spacingNodeNode = elkGraph.getProperty(SporeCompactionOptions.SPACING_NODE_NODE);
ICostFunction costFunction = centerDistance;
switch(costFunctionID) {
case CENTER_DISTANCE:
costFunction = centerDistance;
break;
case CIRCLE_UNDERLAP:
costFunction = circleUnderlap;
break;
case RECTANGLE_UNDERLAP:
costFunction = rectangleUnderlap;
break;
case INVERTED_OVERLAP:
costFunction = invertedOverlap;
break;
case MINIMUM_ROOT_DISTANCE:
costFunction = minimumRootDistance;
break;
default:
throw new IllegalArgumentException("No implementation available for " + costFunctionID.toString());
}
// instantiate Graph
graph = new Graph(costFunction, treeConstructionStrategy, compactionStrategy);
graph.setProperty(InternalProperties.DEBUG_SVG, elkGraph.getProperty(SporeCompactionOptions.DEBUG_MODE));
graph.orthogonalCompaction = elkGraph.getProperty(SporeCompactionOptions.COMPACTION_ORTHOGONAL);
if (elkGraph.getChildren().isEmpty()) {
// don't bother
return graph;
}
// create Nodes representing the ElkNodes
for (ElkNode elkNode : elkGraph.getChildren()) {
double halfWidth = elkNode.getWidth() / 2;
double halfHeight = elkNode.getHeight() / 2;
KVector vertex = new KVector(elkNode.getX() + halfWidth, elkNode.getY() + halfHeight);
// randomly shift identical points a tiny bit to make them unique
while (nodeMap.containsKey(vertex)) {
// SUPPRESS CHECKSTYLE NEXT 1 MagicNumber
vertex.add((Math.random() - 0.5) * 0.001, (Math.random() - 0.5) * 0.001);
// If two positions were identical, their corresponding edge in the spanning tree would be
// of zero length, had no direction, and couldn't be scaled by anything.
}
ElkMargin margin = elkNode.getProperty(CoreOptions.MARGINS);
Node node = new Node(vertex, new ElkRectangle(vertex.x - halfWidth - spacingNodeNode / 2 - margin.left, vertex.y - halfHeight - spacingNodeNode / 2 - margin.top, elkNode.getWidth() + spacingNodeNode + margin.getHorizontal(), elkNode.getHeight() + spacingNodeNode + margin.getVertical()));
graph.vertices.add(node);
nodeMap.put(vertex, Pair.of(node, elkNode));
}
// spanning tree root selection method
switch(rootSelection) {
case FIXED:
if (preferredRootID == null) {
// get first Node in list if no ID specified
graph.preferredRoot = graph.vertices.get(0);
} else {
// find Node associated with the ElkNode containing the ID
for (Node node : graph.vertices) {
String id = nodeMap.get(node.originalVertex).getSecond().getIdentifier();
if (id != null && id.equals(preferredRootID)) {
graph.preferredRoot = node;
}
}
}
break;
case CENTER_NODE:
// find node that is most central in the drawing
KVector center = new KVector(elkGraph.getWidth(), elkGraph.getHeight());
// CHECKSTYLEOFF MagicNumber
center.scale(0.5);
center.add(elkGraph.getX(), elkGraph.getY());
double closest = Double.POSITIVE_INFINITY;
for (Node node : graph.vertices) {
double distance = node.originalVertex.distance(center);
if (distance < closest) {
closest = distance;
graph.preferredRoot = node;
}
}
break;
default:
throw new IllegalArgumentException("No implementation available for " + rootSelection.toString());
}
return graph;
}
use of org.eclipse.elk.graph.ElkNode in project elk by eclipse.
the class InitialPlacement method place.
// ////////////////////////////////////////////////////////////////
// Static methods.
/**
* Simply places the rectangles as {@link RectRow}s onto the drawing area, bounded by the calculated bounding box
* width.
*
* @param rectangles The rectangles to be placed.
* @param boundingWidthThe width of the bounding box.
* @param nodeNodeSpacing The spacing between two nodes.
* @return returns the rows in which the rectangles were placed.
*/
protected static List<RectRow> place(final List<ElkNode> rectangles, final double boundingWidth, final double nodeNodeSpacing) {
List<RectRow> rows = new ArrayList<RectRow>();
RectRow row = new RectRow(0, nodeNodeSpacing);
double drawingHeight = 0;
row.addBlock(new Block(0, 0, row, nodeNodeSpacing));
double currentWidth = 0;
for (ElkNode rect : rectangles) {
// Check whether current rectangle can be added to the last block
Block block = row.getLastBlock();
double potentialRowWidth = currentWidth + rect.getWidth() + (row.getChildren().get(0).getChildren().isEmpty() ? 0 : nodeNodeSpacing);
if (potentialRowWidth > boundingWidth) {
// Add rect in new block in new row.
currentWidth = 0;
drawingHeight += row.getHeight() + nodeNodeSpacing;
rows.add(row);
row = new RectRow(drawingHeight, nodeNodeSpacing);
block = new Block(0, row.getY(), row, nodeNodeSpacing);
row.addBlock(block);
currentWidth = 0;
}
if (block.getChildren().isEmpty() || isSimilarHeight(block, rect, nodeNodeSpacing)) {
// Case add rect in current block to the right of last rect in block.
block.addChild(rect);
} else {
// Case rect does not fit in block. Add new block to the right of it.
Block newBlock = new Block(block.getX() + block.getWidth() + nodeNodeSpacing, row.getY(), row, nodeNodeSpacing);
row.addBlock(newBlock);
newBlock.addChild(rect);
}
currentWidth = rect.getX() + rect.getWidth();
}
rows.add(row);
return rows;
}
use of org.eclipse.elk.graph.ElkNode in project elk by eclipse.
the class Block method adjustSizeAfterRemove.
/**
* Adjusts size of stack after the removal of a rectangle. Notifies parent.
*/
private void adjustSizeAfterRemove() {
// Calculate new width and height
double newWidth = 0;
double newHeight = 0;
// Delete empty rows and calculate new width and height.
List<BlockRow> rowsToDelete = new LinkedList<>();
int index = 0;
for (BlockRow row : this.rows) {
if (row.getNodes().isEmpty()) {
rowsToDelete.add(row);
} else {
newWidth = Math.max(newWidth, row.getWidth());
newHeight += row.getHeight() + (index > 0 ? nodeNodeSpacing : 0);
}
index++;
}
rows.removeAll(rowsToDelete);
this.height = newHeight;
this.width = newWidth;
// Calculate new smallest/biggest rectangle, minimum/maximum width/height.
this.minWidth = 0;
this.minHeight = 0;
this.maxHeight = 0;
this.smallestRectHeight = Double.POSITIVE_INFINITY;
this.smallestRectWidth = Double.POSITIVE_INFINITY;
for (ElkNode rect : children) {
this.smallestRectWidth = Math.min(smallestRectWidth, rect.getWidth());
this.minWidth = Math.max(minWidth, rect.getWidth());
this.minHeight = Math.max(minHeight, rect.getHeight());
this.smallestRectHeight = Math.min(smallestRectHeight, rect.getHeight());
this.maxHeight += rect.getHeight() + nodeNodeSpacing;
}
this.averageHeight = maxHeight / this.children.size() - nodeNodeSpacing * ((double) (this.children.size() - 1) / ((double) this.children.size()));
this.parentRow.notifyAboutNodeChange();
}
Aggregations