use of org.eclipse.elk.alg.force.graph.FNode in project elk by eclipse.
the class StressMajorization method dijkstra.
/**
* Performs Dijkstra's all pairs shortest path algorithm.
*/
private void dijkstra(final FNode source, final double[] dist) {
Queue<FNode> nodes = new PriorityQueue<FNode>((n1, n2) -> Double.compare(dist[n1.id], dist[n2.id]));
boolean[] mark = new boolean[graph.getNodes().size()];
// init
Arrays.fill(mark, false);
dist[source.id] = 0;
for (FNode n : graph.getNodes()) {
if (n.id != source.id) {
dist[n.id] = Integer.MAX_VALUE;
}
nodes.add(n);
}
// find shortest paths
while (!nodes.isEmpty()) {
FNode u = nodes.poll();
mark[u.id] = true;
for (FEdge e : connectedEdges.get(u)) {
FNode v = getOther(e, u);
if (mark[v.id]) {
continue;
}
// get e's desired length
double el;
if (e.hasProperty(StressOptions.DESIRED_EDGE_LENGTH)) {
el = e.getProperty(StressOptions.DESIRED_EDGE_LENGTH);
} else {
el = desiredEdgeLength;
}
double d = dist[u.id] + el;
if (d < dist[v.id]) {
dist[v.id] = d;
nodes.remove(v);
nodes.add(v);
}
}
}
}
use of org.eclipse.elk.alg.force.graph.FNode in project elk by eclipse.
the class StressMajorization method execute.
/**
* Execute the stress-minimizing iteration until a termination criterion is reached.
*/
public void execute() {
if (graph.getNodes().size() <= 1) {
return;
}
int count = 0;
double prevStress = computeStress();
double curStress = Double.POSITIVE_INFINITY;
do {
if (count > 0) {
prevStress = curStress;
}
for (FNode u : graph.getNodes()) {
// being excluded by the layout engine
if (u.getProperty(StressOptions.FIXED)) {
continue;
}
KVector newPos = computeNewPosition(u);
u.getPosition().reset().add(newPos);
}
curStress = computeStress();
} while (!done(count++, prevStress, curStress));
}
use of org.eclipse.elk.alg.force.graph.FNode in project elk by eclipse.
the class StressMajorization method initialize.
/**
* Initialize all internal structures that are required for the subsequent iterative procedure..
*
* @param fgraph the graph to be laid out.
*/
public void initialize(final FGraph fgraph) {
if (fgraph.getNodes().size() <= 1) {
return;
}
this.graph = fgraph;
this.dim = graph.getProperty(StressOptions.DIMENSION);
this.iterationLimit = graph.getProperty(StressOptions.ITERATION_LIMIT);
this.epsilon = graph.getProperty(StressOptions.EPSILON);
this.desiredEdgeLength = graph.getProperty(StressOptions.DESIRED_EDGE_LENGTH);
connectedEdges.clear();
for (FEdge edge : graph.getEdges()) {
connectedEdges.put(edge.getSource(), edge);
connectedEdges.put(edge.getTarget(), edge);
}
// all pairs shortest path
int n = graph.getNodes().size();
apsp = new double[n][n];
for (FNode source : graph.getNodes()) {
dijkstra(source, apsp[source.id]);
}
// init weight matrix
w = new double[n][n];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
double dij = apsp[i][j];
double wij = 1.0 / (dij * dij);
w[i][j] = wij;
}
}
}
use of org.eclipse.elk.alg.force.graph.FNode in project elk by eclipse.
the class StressMajorization method computeNewPosition.
/**
* Computes a new position for the passed node. The procedure is described in
* <em>Section 2.3 Localized optimization</em> of the paper.
*/
private KVector computeNewPosition(final FNode u) {
double weightSum = 0;
double xDisp = 0;
double yDisp = 0;
// we need at least two nodes here, otherwise we would divide by zero below
assert graph.getNodes().size() > 1;
for (FNode v : graph.getNodes()) {
if (u == v) {
continue;
}
double wij = w[u.id][v.id];
weightSum += wij;
double eucDist = u.getPosition().distance(v.getPosition());
if (eucDist > 0 && dim != Dimension.Y) {
xDisp += wij * (v.getPosition().x + apsp[u.id][v.id] * (u.getPosition().x - v.getPosition().x) / eucDist);
}
if (eucDist > 0 && dim != Dimension.X) {
yDisp += wij * (v.getPosition().y + apsp[u.id][v.id] * (u.getPosition().y - v.getPosition().y) / eucDist);
}
}
switch(dim) {
case X:
return new KVector(xDisp / weightSum, u.getPosition().y);
case Y:
return new KVector(u.getPosition().x, yDisp / weightSum);
default:
return new KVector(xDisp / weightSum, yDisp / weightSum);
}
}
use of org.eclipse.elk.alg.force.graph.FNode in project elk by eclipse.
the class AbstractForceModel method initialize.
/**
* Initialize the force model with the given graph. Subclasses that override this
* must call the superclass method first.
*
* @param fgraph a force graph
*/
protected void initialize(final FGraph fgraph) {
this.graph = fgraph;
this.random = fgraph.getProperty(InternalProperties.RANDOM);
// calculate the adjacency matrix for the graph
fgraph.calcAdjacency();
// calculate an upper bound for particle displacement
dispBound = Math.max(fgraph.getNodes().size() * DISP_BOUND_FACTOR + fgraph.getEdges().size(), DISP_BOUND_FACTOR * DISP_BOUND_FACTOR);
// if interactive mode is off, randomize the layout
if (!fgraph.getProperty(ForceOptions.INTERACTIVE)) {
double posScale = graph.getNodes().size();
for (FNode node : fgraph.getNodes()) {
KVector pos = node.getPosition();
pos.x = random.nextDouble() * posScale;
pos.y = random.nextDouble() * posScale;
}
}
// create bend points for node repulsion
List<FBendpoint> bends = fgraph.getBendpoints();
for (FEdge edge : fgraph.getEdges()) {
int count = edge.getProperty(ForceOptions.REPULSIVE_POWER);
if (count > 0) {
for (int i = 0; i < count; i++) {
bends.add(new FBendpoint(edge));
}
edge.distributeBendpoints();
}
}
}
Aggregations