use of org.gephi.layout.plugin.ForceVectorNodeLayoutData in project gephi by gephi.
the class FruchtermanReingold method goAlgo.
@Override
public void goAlgo() {
this.graph = graphModel.getGraphVisible();
graph.readLock();
try {
Node[] nodes = graph.getNodes().toArray();
Edge[] edges = graph.getEdges().toArray();
for (Node n : nodes) {
if (n.getLayoutData() == null || !(n.getLayoutData() instanceof ForceVectorNodeLayoutData)) {
n.setLayoutData(new ForceVectorNodeLayoutData());
}
ForceVectorNodeLayoutData layoutData = n.getLayoutData();
layoutData.dx = 0;
layoutData.dy = 0;
}
// Déplacement limite : on peut le calibrer...
float maxDisplace = (float) (Math.sqrt(AREA_MULTIPLICATOR * area) / 10f);
// La variable k, l'idée principale du layout.
float k = (float) Math.sqrt((AREA_MULTIPLICATOR * area) / (1f + nodes.length));
for (Node N1 : nodes) {
for (Node N2 : nodes) {
// On fait toutes les paires de noeuds
if (N1 != N2) {
// distance en x entre les deux noeuds
float xDist = N1.x() - N2.x();
float yDist = N1.y() - N2.y();
// distance tout court
float dist = (float) Math.sqrt(xDist * xDist + yDist * yDist);
if (dist > 0) {
// Force de répulsion
float repulsiveF = k * k / dist;
ForceVectorNodeLayoutData layoutData = N1.getLayoutData();
// on l'applique...
layoutData.dx += xDist / dist * repulsiveF;
layoutData.dy += yDist / dist * repulsiveF;
}
}
}
}
for (Edge E : edges) {
// Idem, pour tous les noeuds on applique la force d'attraction
Node Nf = E.getSource();
Node Nt = E.getTarget();
float xDist = Nf.x() - Nt.x();
float yDist = Nf.y() - Nt.y();
float dist = (float) Math.sqrt(xDist * xDist + yDist * yDist);
float attractiveF = dist * dist / k;
if (dist > 0) {
ForceVectorNodeLayoutData sourceLayoutData = Nf.getLayoutData();
ForceVectorNodeLayoutData targetLayoutData = Nt.getLayoutData();
sourceLayoutData.dx -= xDist / dist * attractiveF;
sourceLayoutData.dy -= yDist / dist * attractiveF;
targetLayoutData.dx += xDist / dist * attractiveF;
targetLayoutData.dy += yDist / dist * attractiveF;
}
}
// gravity
for (Node n : nodes) {
ForceVectorNodeLayoutData layoutData = n.getLayoutData();
float d = (float) Math.sqrt(n.x() * n.x() + n.y() * n.y());
float gf = 0.01f * k * (float) gravity * d;
layoutData.dx -= gf * n.x() / d;
layoutData.dy -= gf * n.y() / d;
}
// speed
for (Node n : nodes) {
ForceVectorNodeLayoutData layoutData = n.getLayoutData();
layoutData.dx *= speed / SPEED_DIVISOR;
layoutData.dy *= speed / SPEED_DIVISOR;
}
for (Node n : nodes) {
// Maintenant on applique le déplacement calculé sur les noeuds.
// nb : le déplacement à chaque passe "instantanné" correspond à la force : c'est une sorte d'accélération.
ForceVectorNodeLayoutData layoutData = n.getLayoutData();
float xDist = layoutData.dx;
float yDist = layoutData.dy;
float dist = (float) Math.sqrt(layoutData.dx * layoutData.dx + layoutData.dy * layoutData.dy);
if (dist > 0 && !n.isFixed()) {
float limitedDist = Math.min(maxDisplace * ((float) speed / SPEED_DIVISOR), dist);
n.setX(n.x() + xDist / dist * limitedDist);
n.setY(n.y() + yDist / dist * limitedDist);
}
}
} finally {
graph.readUnlockAll();
}
}
use of org.gephi.layout.plugin.ForceVectorNodeLayoutData in project gephi by gephi.
the class ForceAtlasLayout method goAlgo.
@Override
public void goAlgo() {
this.graph = graphModel.getGraphVisible();
graph.readLock();
boolean isDynamicWeight = graphModel.getEdgeTable().getColumn("weight").isDynamic();
Interval interval = graph.getView().getTimeInterval();
try {
Node[] nodes = graph.getNodes().toArray();
Edge[] edges = graph.getEdges().toArray();
for (Node n : nodes) {
if (n.getLayoutData() == null || !(n.getLayoutData() instanceof ForceVectorNodeLayoutData)) {
n.setLayoutData(new ForceVectorNodeLayoutData());
}
}
for (Node n : nodes) {
ForceVectorNodeLayoutData layoutData = n.getLayoutData();
layoutData.old_dx = layoutData.dx;
layoutData.old_dy = layoutData.dy;
layoutData.dx *= inertia;
layoutData.dy *= inertia;
}
// repulsion
if (isAdjustSizes()) {
for (Node n1 : nodes) {
for (Node n2 : nodes) {
if (n1 != n2) {
ForceVectorUtils.fcBiRepulsor_noCollide(n1, n2, getRepulsionStrength() * (1 + graph.getDegree(n1)) * (1 + graph.getDegree(n2)));
}
}
}
} else {
for (Node n1 : nodes) {
for (Node n2 : nodes) {
if (n1 != n2) {
ForceVectorUtils.fcBiRepulsor(n1, n2, getRepulsionStrength() * (1 + graph.getDegree(n1)) * (1 + graph.getDegree(n2)));
}
}
}
}
// attraction
if (isAdjustSizes()) {
if (isOutboundAttractionDistribution()) {
for (Edge e : edges) {
Node nf = e.getSource();
Node nt = e.getTarget();
double bonus = (nf.isFixed() || nt.isFixed()) ? (100) : (1);
bonus *= getEdgeWeight(e, isDynamicWeight, interval);
ForceVectorUtils.fcBiAttractor_noCollide(nf, nt, bonus * getAttractionStrength() / (1 + graph.getDegree(nf)));
}
} else {
for (Edge e : edges) {
Node nf = e.getSource();
Node nt = e.getTarget();
double bonus = (nf.isFixed() || nt.isFixed()) ? (100) : (1);
bonus *= getEdgeWeight(e, isDynamicWeight, interval);
ForceVectorUtils.fcBiAttractor_noCollide(nf, nt, bonus * getAttractionStrength());
}
}
} else {
if (isOutboundAttractionDistribution()) {
for (Edge e : edges) {
Node nf = e.getSource();
Node nt = e.getTarget();
double bonus = (nf.isFixed() || nt.isFixed()) ? (100) : (1);
bonus *= getEdgeWeight(e, isDynamicWeight, interval);
ForceVectorUtils.fcBiAttractor(nf, nt, bonus * getAttractionStrength() / (1 + graph.getDegree(nf)));
}
} else {
for (Edge e : edges) {
Node nf = e.getSource();
Node nt = e.getTarget();
double bonus = (nf.isFixed() || nt.isFixed()) ? (100) : (1);
bonus *= getEdgeWeight(e, isDynamicWeight, interval);
ForceVectorUtils.fcBiAttractor(nf, nt, bonus * getAttractionStrength());
}
}
}
// gravity
for (Node n : nodes) {
float nx = n.x();
float ny = n.y();
double d = 0.0001 + Math.sqrt(nx * nx + ny * ny);
double gf = 0.0001 * getGravity() * d;
ForceVectorNodeLayoutData layoutData = n.getLayoutData();
layoutData.dx -= gf * nx / d;
layoutData.dy -= gf * ny / d;
}
// speed
if (isFreezeBalance()) {
for (Node n : nodes) {
ForceVectorNodeLayoutData layoutData = n.getLayoutData();
layoutData.dx *= getSpeed() * 10f;
layoutData.dy *= getSpeed() * 10f;
}
} else {
for (Node n : nodes) {
ForceVectorNodeLayoutData layoutData = n.getLayoutData();
layoutData.dx *= getSpeed();
layoutData.dy *= getSpeed();
}
}
// apply forces
for (Node n : nodes) {
ForceVectorNodeLayoutData nLayout = n.getLayoutData();
if (!n.isFixed()) {
double d = 0.0001 + Math.sqrt(nLayout.dx * nLayout.dx + nLayout.dy * nLayout.dy);
float ratio;
if (isFreezeBalance()) {
nLayout.freeze = (float) (getFreezeInertia() * nLayout.freeze + (1 - getFreezeInertia()) * 0.1 * getFreezeStrength() * (Math.sqrt(Math.sqrt((nLayout.old_dx - nLayout.dx) * (nLayout.old_dx - nLayout.dx) + (nLayout.old_dy - nLayout.dy) * (nLayout.old_dy - nLayout.dy)))));
ratio = (float) Math.min((d / (d * (1f + nLayout.freeze))), getMaxDisplacement() / d);
} else {
ratio = (float) Math.min(1, getMaxDisplacement() / d);
}
nLayout.dx *= ratio / getCooling();
nLayout.dy *= ratio / getCooling();
float x = n.x() + nLayout.dx;
float y = n.y() + nLayout.dy;
n.setX(x);
n.setY(y);
}
}
} finally {
graph.readUnlockAll();
}
}
Aggregations