use of org.eclipse.elk.alg.common.overlaps.RectangleStripOverlapRemover in project elk by eclipse.
the class PortLabelPlacementCalculator method constrainedOutsidePortLabelPlacement.
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Constrained Outside Port Labels
/**
* Place the port label cells outside of the node in the knowledge that there might not be enough space to place
* them without overlaps.
*/
private static void constrainedOutsidePortLabelPlacement(final NodeContext nodeContext, final PortSide portSide) {
Collection<PortContext> portContexts = nodeContext.portContexts.get(portSide);
// simply revert to simple port label placement
if (portContexts.size() <= 2 || portSide == PortSide.EAST || portSide == PortSide.WEST) {
simpleOutsidePortLabelPlacement(nodeContext, portSide);
return;
}
// If space-efficient port labels are active, the leftmost / topmost port's label must be placed to its left /
// above it
boolean portWithSpecialNeeds = nodeContext.portLabelsPlacement.contains(PortLabelPlacement.SPACE_EFFICIENT);
// Prepare things
OverlapRemovalDirection overlapRemovalDirection = portSide == PortSide.NORTH ? OverlapRemovalDirection.UP : OverlapRemovalDirection.DOWN;
VerticalLabelAlignment verticalLabelAlignment = portSide == PortSide.NORTH ? VerticalLabelAlignment.BOTTOM : VerticalLabelAlignment.TOP;
// Obtain a rectangle strip overlap remover, which will actually do most of the work
RectangleStripOverlapRemover overlapRemover = RectangleStripOverlapRemover.createForDirection(overlapRemovalDirection).withGap(nodeContext.portLabelSpacing);
// Iterate over our ports and add rectangles to the overlap remover. Also, calculate the start coordinate
double startCoordinate = portSide == PortSide.NORTH ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY;
for (PortContext portContext : portContexts) {
if (portContext.portLabelCell == null || !portContext.portLabelCell.hasLabels()) {
continue;
}
KVector portSize = portContext.port.getSize();
KVector portPosition = portContext.portPosition;
LabelCell portLabelCell = portContext.portLabelCell;
ElkRectangle portLabelCellRect = portLabelCell.getCellRectangle();
// Setup the label cell's cell rectangle
portLabelCellRect.width = portLabelCell.getMinimumWidth();
portLabelCellRect.height = portLabelCell.getMinimumHeight();
if (portWithSpecialNeeds) {
portLabelCellRect.x = portPosition.x - portLabelCell.getMinimumWidth() - nodeContext.portLabelSpacing;
portWithSpecialNeeds = false;
} else {
portLabelCellRect.x = portPosition.x + portSize.x + nodeContext.portLabelSpacing;
}
portLabelCell.setVerticalAlignment(verticalLabelAlignment);
portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.RIGHT);
// Add the rectangle to the overlap remover
overlapRemover.addRectangle(portLabelCellRect);
// Update start coordinate
startCoordinate = portSide == PortSide.NORTH ? Math.min(startCoordinate, portPosition.y) : Math.max(startCoordinate, portPosition.y + portContext.port.getSize().y);
}
// The start coordinate needs to be offset by the port-label space
startCoordinate += portSide == PortSide.NORTH ? -nodeContext.portLabelSpacing : nodeContext.portLabelSpacing;
// Invoke the overlap remover
overlapRemover.withStartCoordinate(startCoordinate).removeOverlaps();
// We need to update the label cell's coordinates to be relative to the ports
for (PortContext portContext : portContexts) {
if (portContext.portLabelCell == null || !portContext.portLabelCell.hasLabels()) {
continue;
}
ElkRectangle portLabelCellRect = portContext.portLabelCell.getCellRectangle();
// Setup the label cell's cell rectangle
portLabelCellRect.x -= portContext.portPosition.x;
portLabelCellRect.y -= portContext.portPosition.y;
}
}
use of org.eclipse.elk.alg.common.overlaps.RectangleStripOverlapRemover in project elk by eclipse.
the class EndLabelPreprocessor method removeLabelOverlaps.
/**
* Calls the rectangle overlap removal code to remove overlaps between end labels of edges connected to ports on
* the given sides.
*/
private void removeLabelOverlaps(final LNode node, final LabelCell[] portLabelCells, final PortSide portSide, final double labelLabelSpacing, final double edgeLabelSpacing) {
RectangleStripOverlapRemover overlapRemover = RectangleStripOverlapRemover.createForDirection(portSideToOverlapRemovalDirection(portSide)).withGap(labelLabelSpacing).withStartCoordinate(calculateOverlapStartCoordinate(node, portSide, edgeLabelSpacing));
// Gather the rectangles
for (LPort port : node.getPorts(portSide)) {
if (portLabelCells[port.id] != null) {
ElkRectangle labelCellRect = portLabelCells[port.id].getCellRectangle();
assert labelCellRect.height > 0 && labelCellRect.width > 0;
overlapRemover.addRectangle(labelCellRect);
}
}
// Remove overlaps. Since we have stuffed the original label cell rectangles into this thing, we won't evern
// have to apply or post-process anything. The marvels of modern technology.
overlapRemover.removeOverlaps();
}
use of org.eclipse.elk.alg.common.overlaps.RectangleStripOverlapRemover in project elk by eclipse.
the class PortLabelPlacementCalculator method constrainedInsidePortLabelPlacement.
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Constrained Inside Port Labels
/**
* Place the port label cells outside of the node in the knowledge that there might not be enough space to place
* them without overlaps.
*/
private static void constrainedInsidePortLabelPlacement(final NodeContext nodeContext, final PortSide portSide) {
Collection<PortContext> portContexts = nodeContext.portContexts.get(portSide);
// If it's neither the northern nor the southern side, simply revert to simple port label placement
if (portSide == PortSide.EAST || portSide == PortSide.WEST) {
simpleInsidePortLabelPlacement(nodeContext, portSide);
return;
}
// Prepare things
OverlapRemovalDirection overlapRemovalDirection = portSide == PortSide.NORTH ? OverlapRemovalDirection.DOWN : OverlapRemovalDirection.UP;
VerticalLabelAlignment verticalLabelAlignment = portSide == PortSide.NORTH ? VerticalLabelAlignment.TOP : VerticalLabelAlignment.BOTTOM;
// To keep labels from extending over the content area of the inside port label container, we need to know
// where its content area's left and right boundaries are. We also make sure to always keep a bit of space to
// the node border
AtomicCell insidePortLabelContainer = nodeContext.insidePortLabelCells.get(portSide);
ElkRectangle labelContainerRect = insidePortLabelContainer.getCellRectangle();
double leftBorder = labelContainerRect.x + ElkMath.maxd(insidePortLabelContainer.getPadding().left, nodeContext.surroundingPortMargins.left, nodeContext.nodeLabelSpacing);
double rightBorder = labelContainerRect.x + labelContainerRect.width - ElkMath.maxd(insidePortLabelContainer.getPadding().right, nodeContext.surroundingPortMargins.right, nodeContext.nodeLabelSpacing);
// Obtain a rectangle strip overlap remover, which will actually do most of the work
RectangleStripOverlapRemover overlapRemover = RectangleStripOverlapRemover.createForDirection(overlapRemovalDirection).withGap(nodeContext.portLabelSpacing);
// Iterate over our ports and add rectangles to the overlap remover. Also, calculate the start coordinate
double startCoordinate = portSide == PortSide.NORTH ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
for (PortContext portContext : portContexts) {
if (portContext.portLabelCell == null || !portContext.portLabelCell.hasLabels()) {
continue;
}
KVector portSize = portContext.port.getSize();
KVector portPosition = portContext.portPosition;
LabelCell portLabelCell = portContext.portLabelCell;
ElkRectangle portLabelCellRect = portLabelCell.getCellRectangle();
// Setup the less interesting cell properties
portLabelCellRect.width = portLabelCell.getMinimumWidth();
portLabelCellRect.height = portLabelCell.getMinimumHeight();
portLabelCell.setVerticalAlignment(verticalLabelAlignment);
portLabelCell.setHorizontalAlignment(HorizontalLabelAlignment.RIGHT);
// Center the label, but make sure it doesn't hang over the node boundaries
centerPortLabel(portLabelCellRect, portPosition, portSize, leftBorder, rightBorder);
// Add the rectangle to the overlap remover
overlapRemover.addRectangle(portLabelCellRect);
// Update start coordinate
startCoordinate = portSide == PortSide.NORTH ? Math.max(startCoordinate, portPosition.y + portContext.port.getSize().y) : Math.min(startCoordinate, portPosition.y);
}
// The start coordinate needs to be offset by the port-label space
startCoordinate += portSide == PortSide.NORTH ? nodeContext.portLabelSpacing : -nodeContext.portLabelSpacing;
// Invoke the overlap remover
double stripHeight = overlapRemover.withStartCoordinate(startCoordinate).removeOverlaps();
if (stripHeight > 0) {
nodeContext.insidePortLabelCells.get(portSide).getMinimumContentAreaSize().y = stripHeight;
}
// We need to update the label cell's coordinates to be relative to the ports
for (PortContext portContext : portContexts) {
if (portContext.portLabelCell == null || !portContext.portLabelCell.hasLabels()) {
continue;
}
ElkRectangle portLabelCellRect = portContext.portLabelCell.getCellRectangle();
// Setup the label cell's cell rectangle
portLabelCellRect.x -= portContext.portPosition.x;
portLabelCellRect.y -= portContext.portPosition.y;
}
}
Aggregations