use of org.eclipse.elk.graph.ElkEdge in project elk by eclipse.
the class RandomLayoutProvider method randomize.
/**
* Randomize the given graph.
*
* @param parent the parent node of the graph
* @param random the random number generator
* @param aspectRatio desired aspect ratio (must not be 0)
* @param spacing desired object spacing
* @param offset offset to the border
*/
private void randomize(final ElkNode parent, final Random random, final double aspectRatio, final double spacing, final ElkPadding padding) {
// determine width and height of the drawing and count the number of edges
double nodesArea = 0.0f, maxWidth = 0.0f, maxHeight = 0.0f;
int m = 1;
for (ElkNode node : parent.getChildren()) {
m += Iterables.size(ElkGraphUtil.allOutgoingEdges(node));
double width = node.getWidth();
maxWidth = Math.max(maxWidth, width);
double height = node.getHeight();
maxHeight = Math.max(maxHeight, height);
nodesArea += width * height;
}
int n = parent.getChildren().size();
// a heuristic formula that determines an area in which nodes are randomly distributed
double drawArea = nodesArea + 2 * spacing * spacing * m * n;
double areaSqrt = (double) Math.sqrt(drawArea);
double drawWidth = Math.max(areaSqrt * aspectRatio, maxWidth);
double drawHeight = Math.max(areaSqrt / aspectRatio, maxHeight);
// randomize node positions
for (ElkNode node : parent.getChildren()) {
double x = padding.getLeft() + random.nextDouble() * (drawWidth - node.getWidth());
double y = padding.getLeft() + random.nextDouble() * (drawHeight - node.getHeight());
node.setLocation(x, y);
}
// randomize edge positions
double totalWidth = drawWidth + padding.getHorizontal();
double totalHeight = drawHeight + padding.getVertical();
for (ElkNode source : parent.getChildren()) {
for (ElkEdge edge : ElkGraphUtil.allOutgoingEdges(source)) {
if (!edge.isHierarchical()) {
randomize(edge, random, totalWidth, totalHeight);
}
}
}
totalWidth += padding.getLeft() + padding.getRight();
totalHeight += padding.getTop() + padding.getBottom();
ElkUtil.resizeNode(parent, totalWidth, totalHeight, false, true);
}
use of org.eclipse.elk.graph.ElkEdge in project elk by eclipse.
the class GmfLayoutEditPolicy method addLabelLayout.
/**
* Adds an edge label layout to the given command.
*
* @param command
* command to which the edge label layout shall be added
* @param klabel
* label with layout data
* @param labelEditPart
* edit part to which layout is applied
* @param scale
* scale factor for coordinates
*/
private void addLabelLayout(final GmfLayoutCommand command, final ElkLabel klabel, final GraphicalEditPart labelEditPart, final double scale) {
ElkGraphElement parent = klabel.getParent();
// node and port labels are processed separately
if (parent instanceof ElkNode || parent instanceof ElkPort) {
View view = (View) labelEditPart.getModel();
int xpos = (int) (klabel.getX() * scale);
int ypos = (int) (klabel.getY() * scale);
Object oldx = ViewUtil.getStructuralFeatureValue(view, NotationPackage.eINSTANCE.getLocation_X());
Object oldy = ViewUtil.getStructuralFeatureValue(view, NotationPackage.eINSTANCE.getLocation_Y());
if (oldx == null || oldy == null || xpos != (Integer) oldx || ypos != (Integer) oldy) {
command.addShapeLayout(view, new Point(xpos, ypos), null);
}
return;
} else if (parent instanceof ElkEdge) {
// calculate direct new location of the label
Rectangle targetBounds = new Rectangle(labelEditPart.getFigure().getBounds());
targetBounds.x = (int) (klabel.getX() * scale);
targetBounds.y = (int) (klabel.getY() * scale);
ConnectionEditPart connectionEditPart = (ConnectionEditPart) labelEditPart.getParent();
PointList bendPoints = getBendPoints((ElkEdge) parent, connectionEditPart.getFigure(), scale);
EObject modelElement = connectionEditPart.getNotationView().getElement();
EdgeLabelPlacement labelPlacement = klabel.getProperty(CoreOptions.EDGE_LABELS_PLACEMENT);
// the list of bend points must be reversed
if (modelElement instanceof EReference && labelPlacement == EdgeLabelPlacement.TAIL) {
bendPoints = bendPoints.getCopy();
bendPoints.reverse();
}
// get the referencePoint for the label
int fromEnd, keyPoint = ConnectionLocator.MIDDLE;
if (labelEditPart instanceof LabelEditPart) {
keyPoint = ((LabelEditPart) labelEditPart).getKeyPoint();
}
switch(keyPoint) {
case ConnectionLocator.SOURCE:
fromEnd = SOURCE_LOCATION;
break;
case ConnectionLocator.TARGET:
fromEnd = TARGET_LOCATION;
break;
default:
fromEnd = MIDDLE_LOCATION;
break;
}
Point refPoint = PointListUtilities.calculatePointRelativeToLine(bendPoints, 0, fromEnd, true);
// get the new relative location
Point normalPoint = offsetFromRelativeCoordinate(targetBounds, bendPoints, refPoint);
if (normalPoint != null) {
command.addShapeLayout((View) labelEditPart.getModel(), normalPoint, null);
}
}
}
use of org.eclipse.elk.graph.ElkEdge in project elk by eclipse.
the class RandomGraphGenerator method connect.
/**
* Connects two nodes with an edge.
*
* @param source
* the source node
* @param target
* the target node
* @param directed
* whether the edge should be directed or undirected
* @return the edge
*/
private ElkEdge connect(final ElkConnectableShape source, final ElkConnectableShape target) {
ElkNode sourceNode = null;
ElkNode targetNode = null;
ElkPort sourcePort = null;
ElkPort targetPort = null;
if (source instanceof ElkNode) {
sourceNode = (ElkNode) source;
}
if (source instanceof ElkPort) {
sourcePort = (ElkPort) source;
sourceNode = sourcePort.getParent();
}
if (target instanceof ElkPort) {
targetPort = (ElkPort) target;
targetNode = targetPort.getParent();
}
if (target instanceof ElkNode) {
targetNode = (ElkNode) target;
}
ElkEdge edge = ElkGraphUtil.createEdge(null);
if (get(GeneratorOptions.ENABLE_PORTS)) {
if (source instanceof ElkNode) {
sourcePort = retrievePort(sourceNode, true);
}
if (!isHypernode(sourceNode)) {
// remove node
if (edge.getSources().contains(sourceNode)) {
edge.getSources().remove(sourceNode);
}
edge.getSources().add(sourcePort);
// edge.setSourcePort(sourcePort);
}
if (!isHypernode(targetNode)) {
if (targetPort == null) {
targetPort = retrievePort(targetNode, false);
}
if (edge.getTargets().contains(targetNode)) {
edge.getTargets().remove(targetNode);
}
edge.getTargets().remove(target);
edge.getTargets().add(targetPort);
// edge.setTargetPort(targetPort);
}
} else {
edge.getSources().add(sourceNode);
edge.getTargets().add(targetNode);
}
if (get(GeneratorOptions.EDGE_LABELS)) {
addEdgeLabel(edge);
}
ElkGraphUtil.updateContainment(edge);
return edge;
}
use of org.eclipse.elk.graph.ElkEdge in project elk by eclipse.
the class RandomGraphGenerator method findNodeWithDFS.
/**
* Returns whether a node can be reached from another node. PRECONDITION: the graph containing
* the nodes has to be acyclic! If that condition is not met the method is likely to loop
* infinitely!
*
* @param start
* the start node
* @param end
* the end node
* @return whether the end node can be reached from the start node
*/
private static boolean findNodeWithDFS(final ElkNode start, final ElkNode end) {
Queue<ElkNode> nodes = new LinkedList<ElkNode>();
nodes.add(start);
do {
ElkNode node = nodes.poll();
if (node == end) {
return true;
}
for (ElkEdge edge : node.getOutgoingEdges()) {
for (ElkConnectableShape target : edge.getTargets()) {
if (target instanceof ElkNode) {
nodes.add((ElkNode) target);
} else if (target instanceof ElkPort) {
ElkPort port = (ElkPort) target;
nodes.add(port.getParent());
}
}
}
} while (!nodes.isEmpty());
return false;
}
use of org.eclipse.elk.graph.ElkEdge in project elk by eclipse.
the class RandomGraphGenerator method generateTriconnectedGraph.
// CHECKSTYLEON MagicNumber
/**
* Generates a triconnected graph. The implementation is based upon the one used in the OGDF
* library.
*
* @param parent
* the parent node
* @param n
* the number of nodes
* @param p1
* the probability for the first additional edge to be added
* @param p2
* the probability for the second additional edge to be added
* @param hierarchyLevel
* the current hierarchy level
*/
// CHECKSTYLEOFF MagicNumber
private void generateTriconnectedGraph(final ElkNode parent, final int n, final float p1, final float p2, final int hierarchyLevel) {
int realN = Math.max(n, 4);
// start with a clique of size 4
List<ElkNode> cliqueNodes = createClique(parent, 4);
// array of all nodes
ElkNode[] nodes = new ElkNode[realN];
int i = 0;
for (ElkNode node : cliqueNodes) {
nodes[i++] = node;
}
// array of neighbors
ElkEdge[] neighbors = new ElkEdge[realN];
// neighbor markings
// 0 = not marked
// 1 = marked left
// 2 = marked right
// 3 = marked both
int[] marks = new int[n];
// generate the graph
for (; i < n; ++i) {
ElkNode node = nodes[randomInt(0, i - 1)];
// create a new node to split 'node' in two
ElkNode newNode = createNode(parent);
nodes[i] = newNode;
// build array of all neighbors
int d = node.getOutgoingEdges().size() + node.getIncomingEdges().size();
int j = 0;
for (ElkEdge edge : node.getOutgoingEdges()) {
neighbors[j++] = edge;
}
for (ElkEdge edge : node.getIncomingEdges()) {
neighbors[j++] = edge;
}
// mark two distinct neighbors for left
for (j = 2; j > 0; ) {
int r = randomInt(0, d - 1);
if ((marks[r] & 1) == 0) {
marks[r] |= 1;
--j;
}
}
// mark two distinct neighbors for right
for (j = 2; j > 0; ) {
int r = randomInt(0, d - 1);
if ((marks[r] & 2) == 0) {
marks[r] |= 2;
--j;
}
}
// perform the node-split
for (j = 0; j < d; ++j) {
int mark = marks[j];
marks[j] = 0;
// decide to with which node each neighbor is connected
double x = random.nextDouble();
switch(mark) {
case 0:
if (x < p1) {
mark = 1;
} else if (x < p1 + p2) {
mark = 2;
} else {
mark = 3;
}
break;
case 1:
case 2:
if (x >= p1 + p2) {
mark = 3;
}
break;
}
// move edge or create new one if necessary
ElkEdge edge = neighbors[j];
switch(mark) {
case 2:
if (edge.getSources().contains(node)) {
moveSource(edge, node, newNode);
} else {
moveTarget(edge, node, newNode);
}
break;
case 3:
if (edge.getSources().contains(node)) {
connect(newNode, edge.getTargets().get(0));
} else {
connect(newNode, edge.getSources().get(0));
}
break;
}
}
connect(node, newNode);
}
// recursively create hierarchy if applicable
float hierarchyChance = get(GeneratorOptions.HIERARCHY_CHANCE);
if (hierarchyChance > 0.0f && hierarchyLevel < maxHierarchyLevel) {
for (ElkNode node : parent.getChildren()) {
if (!isHypernode(node) && random.nextFloat() < hierarchyChance) {
// determine the number of nodes in the compound node
float hierarchyNodesFactor = get(GeneratorOptions.HIERARCHY_NODES_FACTOR);
int cn = randomInt(1, (int) (hierarchyNodesFactor * n));
generateTriconnectedGraph(node, cn, p1, p2, hierarchyLevel + 1);
}
}
}
}
Aggregations