Search in sources :

Example 1 with FNode

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);
            }
        }
    }
}
Also used : FNode(org.eclipse.elk.alg.force.graph.FNode) FEdge(org.eclipse.elk.alg.force.graph.FEdge) PriorityQueue(java.util.PriorityQueue)

Example 2 with FNode

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));
}
Also used : FNode(org.eclipse.elk.alg.force.graph.FNode) KVector(org.eclipse.elk.core.math.KVector)

Example 3 with FNode

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;
        }
    }
}
Also used : FNode(org.eclipse.elk.alg.force.graph.FNode) FEdge(org.eclipse.elk.alg.force.graph.FEdge)

Example 4 with FNode

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);
    }
}
Also used : FNode(org.eclipse.elk.alg.force.graph.FNode) KVector(org.eclipse.elk.core.math.KVector)

Example 5 with FNode

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();
        }
    }
}
Also used : FBendpoint(org.eclipse.elk.alg.force.graph.FBendpoint) FNode(org.eclipse.elk.alg.force.graph.FNode) FEdge(org.eclipse.elk.alg.force.graph.FEdge) KVector(org.eclipse.elk.core.math.KVector) FBendpoint(org.eclipse.elk.alg.force.graph.FBendpoint)

Aggregations

FNode (org.eclipse.elk.alg.force.graph.FNode)15 KVector (org.eclipse.elk.core.math.KVector)7 FBendpoint (org.eclipse.elk.alg.force.graph.FBendpoint)6 FEdge (org.eclipse.elk.alg.force.graph.FEdge)6 FGraph (org.eclipse.elk.alg.force.graph.FGraph)3 ElkNode (org.eclipse.elk.graph.ElkNode)3 LinkedList (java.util.LinkedList)2 List (java.util.List)2 FLabel (org.eclipse.elk.alg.force.graph.FLabel)2 HashMap (java.util.HashMap)1 PriorityQueue (java.util.PriorityQueue)1 FParticle (org.eclipse.elk.alg.force.graph.FParticle)1 ElkPadding (org.eclipse.elk.core.math.ElkPadding)1 PortConstraints (org.eclipse.elk.core.options.PortConstraints)1 ElkEdge (org.eclipse.elk.graph.ElkEdge)1 ElkEdgeSection (org.eclipse.elk.graph.ElkEdgeSection)1 ElkLabel (org.eclipse.elk.graph.ElkLabel)1