use of org.eclipse.elk.alg.layered.graph.LPort in project elk by eclipse.
the class DotDebugUtil method writeLayer.
/**
* Writes the given list of nodes and their edges.
*
* @param writer writer to write to.
* @param layerNumber the layer number. {@code -1} for layerless nodes.
* @param nodes the nodes in the layer.
*/
private static void writeLayer(final StringWriter writer, final int layerNumber, final List<LNode> nodes) {
if (nodes.isEmpty()) {
return;
}
// Go through the layer's nodes
int nodeNumber = -1;
for (LNode node : nodes) {
nodeNumber++;
// The node's name in the output is its hash code (unique!)
writer.write(" " + node.hashCode());
// Options time!
StringBuffer options = new StringBuffer();
// Label
options.append("label=\"");
if (node.getType() == NodeType.NORMAL) {
// Normal nodes display their name, if any
if (node.getDesignation() != null) {
options.append(node.getDesignation().replace("\"", "\\\"") + " ");
}
} else {
// Dummy nodes show their name (if set), or their node ID
if (node.getDesignation() != null) {
options.append(node.getDesignation().replace("\"", "\\\"") + " ");
} else {
options.append("n_" + node.id + " ");
}
if (node.getType() == NodeType.NORTH_SOUTH_PORT) {
Object origin = node.getProperty(InternalProperties.ORIGIN);
if (origin instanceof LNode) {
options.append("(" + ((LNode) origin).toString() + ")");
}
}
}
options.append("(" + layerNumber + "," + nodeNumber + ")\",");
// Node type
if (node.getType() == NodeType.NORMAL) {
options.append("shape=box,");
} else {
options.append("style=\"rounded,filled\",");
String color = node.getType().getColor();
if (color != null) {
options.append("color=\"" + color + "\",");
}
}
// Print options, if any
options.deleteCharAt(options.length() - 1);
if (options.length() > 0) {
writer.write("[" + options + "]");
}
// End the node line
writer.write(";\n");
}
// Write the edges
for (LNode node : nodes) {
// Go through all edges and output those that have this node as their source
for (LPort port : node.getPorts()) {
for (LEdge edge : port.getOutgoingEdges()) {
writer.write(" " + node.hashCode() + " -> " + edge.getTarget().getNode().hashCode());
writer.write(";\n");
}
}
}
}
use of org.eclipse.elk.alg.layered.graph.LPort in project elk by eclipse.
the class JsonDebugUtil method calculateMinMaxPositions.
/**
* Inspects the given node, its outgoing edges and its ports for minimal and maximal coordinates
* and adjusts the given vectors {@code min} and {@code max} if necessary.
*
* @param min
* the minimal coordinates used by the graph.
* @param max
* the maximal coordinates used by the graph.
* @param node
* the current node to inspect.
*/
private static void calculateMinMaxPositions(final KVector min, final KVector max, final LNode node) {
min.x = Math.min(min.x, node.getPosition().x - node.getMargin().left);
max.x = Math.max(max.x, node.getPosition().x + node.getSize().x + node.getMargin().right);
min.y = Math.min(min.y, node.getPosition().y - node.getMargin().top);
max.y = Math.max(max.y, node.getPosition().y + node.getSize().y + node.getMargin().bottom);
for (LPort port : node.getPorts()) {
min.x = Math.min(min.x, node.getPosition().x + port.getPosition().x - port.getMargin().left);
max.x = Math.max(max.x, node.getPosition().x + port.getPosition().x + port.getSize().x + port.getMargin().right);
min.y = Math.min(min.y, node.getPosition().y + port.getPosition().y - port.getMargin().top);
max.y = Math.max(max.y, node.getPosition().y + port.getPosition().y + port.getSize().y + port.getMargin().bottom);
}
for (LEdge edge : node.getOutgoingEdges()) {
for (KVector bendpoint : edge.getBendPoints()) {
min.x = Math.min(min.x, bendpoint.x);
max.x = Math.max(max.x, bendpoint.x);
min.y = Math.min(min.y, bendpoint.y);
max.y = Math.max(max.y, bendpoint.y);
}
}
}
use of org.eclipse.elk.alg.layered.graph.LPort in project elk by eclipse.
the class JsonDebugUtil method writeLayer.
/**
* Writes the given list of nodes and collects their edges.
*
* @param writer
* writer to write to.
* @param layerNumber
* the layer number. {@code -1} for layerless nodes.
* @param nodes
* the nodes in the layer.
* @param indentation
* the indentation level to use.
* @param offset
* the combined offset of the containing LGraph.
* @return list of edges that need to be added to the graph.
*/
private static List<LEdge> writeLayer(final StringWriter writer, final int layerNumber, final List<LNode> nodes, final int indentation, final KVector offset) {
if (nodes.isEmpty()) {
return Lists.newLinkedList();
}
writeNodes(writer, nodes, indentation, layerNumber, offset);
List<LEdge> edges = Lists.newLinkedList();
// Collect the edges
for (LNode node : nodes) {
// Go through all edges and collect those that have this node as their source
for (LPort port : node.getPorts()) {
edges.addAll(port.getOutgoingEdges());
}
}
return edges;
}
use of org.eclipse.elk.alg.layered.graph.LPort in project elk by eclipse.
the class InteractiveCrossingMinimizer method getPos.
/**
* Determine a vertical position for the given node.
*
* @param node a node
* @param horizPos the horizontal position at which to measure (relevant for edges)
* @return the vertical position used for sorting
*/
private double getPos(final LNode node, final double horizPos) {
switch(node.getType()) {
case LONG_EDGE:
LEdge edge = (LEdge) node.getProperty(InternalProperties.ORIGIN);
// reconstruct the original bend points from the node annotations
KVectorChain bendpoints = edge.getProperty(InternalProperties.ORIGINAL_BENDPOINTS);
if (bendpoints == null) {
bendpoints = new KVectorChain();
} else if (edge.getProperty(InternalProperties.REVERSED)) {
bendpoints = KVectorChain.reverse(bendpoints);
}
// Check if we can determine the position just by using the source point, if we can determine it
LPort source = node.getProperty(InternalProperties.LONG_EDGE_SOURCE);
if (source != null) {
KVector sourcePoint = source.getAbsoluteAnchor();
if (horizPos <= sourcePoint.x) {
return sourcePoint.y;
}
bendpoints.addFirst(sourcePoint);
}
// Check if we can determine the position just by using the target point
LPort target = node.getProperty(InternalProperties.LONG_EDGE_TARGET);
if (target != null) {
KVector targetPoint = target.getAbsoluteAnchor();
if (targetPoint.x <= horizPos) {
return targetPoint.y;
}
bendpoints.addLast(targetPoint);
}
// Find the two points along the edge that the horizontal point lies between
if (bendpoints.size() >= 2) {
Iterator<KVector> pointIter = bendpoints.iterator();
KVector point1 = pointIter.next();
KVector point2 = pointIter.next();
while (point2.x < horizPos && pointIter.hasNext()) {
point1 = point2;
point2 = pointIter.next();
}
return point1.y + (horizPos - point1.x) / (point2.x - point1.x) * (point2.y - point1.y);
}
break;
case NORTH_SOUTH_PORT:
// Get one of the ports the dummy node was created for, and its original node
LPort originPort = (LPort) node.getPorts().get(0).getProperty(InternalProperties.ORIGIN);
LNode originNode = originPort.getNode();
switch(originPort.getSide()) {
case NORTH:
// by respecting node successor constraints.
return originNode.getPosition().y;
case SOUTH:
// Use the position of the node's southern side
return originNode.getPosition().y + originNode.getSize().y;
}
break;
}
// the fallback solution is to take the previous position of the node's anchor point
return node.getInteractiveReferencePoint().y;
}
use of org.eclipse.elk.alg.layered.graph.LPort in project elk by eclipse.
the class InteractiveCrossingMinimizer method process.
@Override
public void process(final LGraph layeredGraph, final IElkProgressMonitor monitor) {
monitor.begin("Interactive crossing minimization", 1);
// Set ID's for each layer since they will be used by the port distribution code to index into arrays
int layerIndex = 0;
for (Layer layer : layeredGraph.getLayers()) {
layer.id = layerIndex++;
}
LNode[][] nodeOrder = layeredGraph.toNodeArray();
AbstractBarycenterPortDistributor portDistributor = new NodeRelativePortDistributor(nodeOrder.length);
IInitializable.init(Arrays.asList(portDistributor), nodeOrder);
int portCount = 0;
layerIndex = 0;
for (Layer layer : layeredGraph) {
// determine a horizontal position for edge bend points comparison
double horizPos = 0;
int nodeCount = 0;
for (LNode node : layer.getNodes()) {
if (node.getPosition().x > 0) {
horizPos += node.getPosition().x + node.getSize().x / 2;
nodeCount++;
}
for (LPort port : node.getPorts()) {
port.id = portCount++;
}
}
if (nodeCount > 0) {
horizPos /= nodeCount;
}
// create an array of vertical node positions
final double[] pos = new double[layer.getNodes().size()];
int nextIndex = 0;
for (LNode node : layer) {
node.id = nextIndex++;
pos[node.id] = getPos(node, horizPos);
// dummies, we haven't calculated meaningful positions)
if (node.getType() == NodeType.LONG_EDGE) {
node.setProperty(InternalProperties.ORIGINAL_DUMMY_NODE_POSITION, pos[node.id]);
}
}
// sort the nodes using the position array
Collections.sort(layer.getNodes(), new Comparator<LNode>() {
public int compare(final LNode node1, final LNode node2) {
int compare = Double.compare(pos[node1.id], pos[node2.id]);
if (compare == 0) {
// The two nodes have the same y coordinate. Check for node successor
// constraints
List<LNode> node1Successors = node1.getProperty(InternalProperties.IN_LAYER_SUCCESSOR_CONSTRAINTS);
List<LNode> node2Successors = node2.getProperty(InternalProperties.IN_LAYER_SUCCESSOR_CONSTRAINTS);
if (node1Successors.contains(node2)) {
return -1;
} else if (node2Successors.contains(node1)) {
return 1;
}
}
return compare;
}
});
portDistributor.distributePortsWhileSweeping(nodeOrder, layerIndex, true);
layerIndex++;
}
monitor.done();
}
Aggregations