use of org.eclipse.elk.alg.layered.graph.LPort in project elk by eclipse.
the class LayerSweepCrossingMinimizer method countModelOrderPortChanges.
/**
* Compares all ports in a each layer and counts how often they are not in model order.
* This requires that the {@code SortByInputModelProcessor} ran previously.
* @param layers layers to check
* @return The number of model order conflicts
*/
private int countModelOrderPortChanges(final LNode[][] layers) {
int previousLayer = -1;
int wrongModelOrder = 0;
for (LNode[] layer : layers) {
for (LNode lNode : layer) {
Comparator<LPort> comp = new ModelOrderPortComparator(previousLayer == -1 ? layers[0] : layers[previousLayer], SortByInputModelProcessor.longEdgeTargetNodePreprocessing(lNode));
for (int i = 0; i < lNode.getPorts().size(); i++) {
for (int j = i + 1; j < lNode.getPorts().size(); j++) {
if (comp.compare(lNode.getPorts().get(i), lNode.getPorts().get(j)) > 0) {
wrongModelOrder++;
}
}
}
}
previousLayer++;
}
return wrongModelOrder;
}
use of org.eclipse.elk.alg.layered.graph.LPort in project elk by eclipse.
the class LayerSweepCrossingMinimizer method sortPortsByDummyPositionsInLastLayer.
private void sortPortsByDummyPositionsInLastLayer(final LNode[][] nodeOrder, final LNode parent, final boolean onRightMostLayer) {
int endIndex = endIndex(onRightMostLayer, nodeOrder.length);
LNode[] lastLayer = nodeOrder[endIndex];
if (!isExternalPortDummy(lastLayer[0])) {
return;
}
int j = firstIndex(onRightMostLayer, lastLayer.length);
List<LPort> ports = parent.getPorts();
for (int i = 0; i < ports.size(); i++) {
LPort port = ports.get(i);
if (isOnEndOfSweepSide(port, onRightMostLayer) && isHierarchical(port)) {
ports.set(i, originPort(lastLayer[j]));
j += next(onRightMostLayer);
}
}
}
use of org.eclipse.elk.alg.layered.graph.LPort in project elk by eclipse.
the class LayerSweepTypeDecider method useBottomUp.
/**
* Decide whether to use bottom up or cross-hierarchical sweep method.
*
* @return decision
*/
public boolean useBottomUp() {
double boundary = graphData.lGraph().getProperty(LayeredOptions.CROSSING_MINIMIZATION_HIERARCHICAL_SWEEPINESS);
if (bottomUpForced(boundary) || rootNode() || fixedPortOrder() || fewerThanTwoInOutEdges()) {
return true;
}
if (graphData.crossMinDeterministic()) {
return false;
}
int pathsToRandom = 0;
int pathsToHierarchical = 0;
List<LNode> nsPortDummies = new ArrayList<>();
for (LNode[] layer : graphData.currentNodeOrder()) {
for (LNode node : layer) {
// We must visit all sources of edges first, so we collect north south dummies for later.
if (isNorthSouthDummy(node)) {
nsPortDummies.add(node);
continue;
}
NodeInfo currentNode = nodeInfoFor(node);
// Check for hierarchical port dummies or random influence.
if (isExternalPortDummy(node)) {
currentNode.hierarchicalInfluence = 1;
if (isEasternDummy(node)) {
pathsToHierarchical += currentNode.connectedEdges;
}
} else if (hasNoWesternPorts(node)) {
currentNode.randomInfluence = 1;
} else if (hasNoEasternPorts(node)) {
pathsToRandom += currentNode.connectedEdges;
}
// and transfer information to targets.
for (LEdge edge : node.getOutgoingEdges()) {
pathsToRandom += currentNode.randomInfluence;
pathsToHierarchical += currentNode.hierarchicalInfluence;
transferInfoToTarget(currentNode, edge);
}
// Do the same for north/south dummies: Increase counts of paths by the number outgoing edges times the
// influence and transfer information to dummies.
Iterable<LPort> northSouthPorts = Iterables.concat(node.getPortSideView(PortSide.NORTH), node.getPortSideView(PortSide.SOUTH));
for (LPort port : northSouthPorts) {
LNode nsDummy = port.getProperty(InternalProperties.PORT_DUMMY);
if (nsDummy != null) {
pathsToRandom += currentNode.randomInfluence;
pathsToHierarchical += currentNode.hierarchicalInfluence;
transferInfoTo(currentNode, nsDummy);
}
}
}
// Now process nsPortDummies
for (LNode node : nsPortDummies) {
NodeInfo currentNode = nodeInfoFor(node);
for (LEdge edge : node.getOutgoingEdges()) {
pathsToRandom += currentNode.randomInfluence;
pathsToHierarchical += currentNode.hierarchicalInfluence;
transferInfoToTarget(currentNode, edge);
}
}
nsPortDummies.clear();
}
double allPaths = pathsToRandom + pathsToHierarchical;
double normalized = allPaths == 0 ? Double.POSITIVE_INFINITY : (pathsToRandom - pathsToHierarchical) / allPaths;
return normalized >= boundary;
}
use of org.eclipse.elk.alg.layered.graph.LPort in project elk by eclipse.
the class LongestPathLayerer method visit.
/**
* Visit a node: if not already visited, find the longest path to a sink.
*
* @param node node to visit
* @return height of the given node in the layered graph
*/
private int visit(final LNode node) {
int height = nodeHeights[node.id];
if (height >= 0) {
// the node was already visited (the case height == 0 should never occur)
return height;
} else {
int maxHeight = 1;
for (LPort port : node.getPorts()) {
for (LEdge edge : port.getOutgoingEdges()) {
LNode targetNode = edge.getTarget().getNode();
// ignore self-loops
if (node != targetNode) {
int targetHeight = visit(targetNode);
maxHeight = Math.max(maxHeight, targetHeight + 1);
}
}
}
putNode(node, maxHeight);
return maxHeight;
}
}
use of org.eclipse.elk.alg.layered.graph.LPort in project elk by eclipse.
the class NetworkSimplexPlacer method prepare.
// ------------------------------------------------------------------------------------------------
// Preparation
// ------------------------------------------------------------------------------------------------
private void prepare() {
this.nGraph = new NGraph();
// "integerify" port anchor and port positions
// note that margin.top and margin.bottom are not required to be integral
// since they do not influence the offset calculation for the edges
// ... while we're at it, we assign ids to the nodes and edges
int nodeIdx = 0;
int edgeIdx = 0;
for (Layer l : lGraph) {
for (LNode lNode : l) {
lNode.id = nodeIdx++;
for (LEdge e : lNode.getOutgoingEdges()) {
e.id = edgeIdx++;
}
// if a node is flexible, an edge attaches to the port itself within
// the auxiliary graph, thus the anchor must be integer
// otherwise the port position can be altered such that it accounts for the anchor's position as well
boolean anchorMustBeInteger = isFlexibleNode(lNode);
for (LPort p : lNode.getPorts()) {
if (anchorMustBeInteger) {
// anchor
double y = p.getAnchor().y;
if (y != Math.floor(y)) {
double offset = y - Math.round(y);
p.getAnchor().y -= offset;
}
}
// port + anchor
double y = p.getPosition().y + p.getAnchor().y;
if (y != Math.floor(y)) {
double offset = y - Math.round(y);
p.getPosition().y -= offset;
}
}
}
}
this.nodeCount = nodeIdx;
this.edgeCount = edgeIdx;
this.nodeReps = new NodeRep[nodeIdx];
this.edgeReps = new EdgeRep[edgeIdx];
this.flexibleWhereSpacePermitsEdges.clear();
}
Aggregations