Merge lp:~mathieu-jacomy/gephi/forceatlas2-multithread into lp:~gephi.team/gephi/0.8

Proposed by Mathieu Bastian
Status: Needs review
Proposed branch: lp:~mathieu-jacomy/gephi/forceatlas2-multithread
Merge into: lp:~gephi.team/gephi/0.8
Diff against target: 628 lines (+345/-32)
11 files modified
LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/Bundle.properties (+5/-0)
LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/Bundle_fr.properties (+5/-0)
LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/ForceAtlas2.java (+88/-27)
LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/ForceFactory.java (+46/-3)
LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/NodesThread.java (+64/-0)
LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/Operation.java (+13/-0)
LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/OperationNodeNodeAttract.java (+32/-0)
LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/OperationNodeNodeRepulse.java (+29/-0)
LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/OperationNodeRegionRepulse.java (+32/-0)
LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/OperationNodeRepulse.java (+29/-0)
LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/Region.java (+2/-2)
To merge this branch: bzr merge lp:~mathieu-jacomy/gephi/forceatlas2-multithread
Reviewer Review Type Date Requested Status
Mathieu Bastian Pending
Review via email: mp+69478@code.launchpad.net

Description of the change

Multithread version of ForceAtlas2

To post a comment you must log in.
2260. By Mathieu Jacomy

ForceAtlas2 Multithread - better strategy. Tested and working.

2261. By Mathieu Jacomy

Better ThreadPool implementation, added strong gravity

Unmerged revisions

2261. By Mathieu Jacomy

Better ThreadPool implementation, added strong gravity

2260. By Mathieu Jacomy

ForceAtlas2 Multithread - better strategy. Tested and working.

2259. By Mathieu Jacomy

ForceAtlas2 Multithreading (basic implementation: consumer-producer paradigm)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/Bundle.properties'
--- LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/Bundle.properties 2011-06-05 21:30:01 +0000
+++ LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/Bundle.properties 2011-08-30 14:28:25 +0000
@@ -4,11 +4,14 @@
4ForceAtlas2.tuning=Tuning4ForceAtlas2.tuning=Tuning
5ForceAtlas2.behavior=Behavior Alternatives5ForceAtlas2.behavior=Behavior Alternatives
6ForceAtlas2.performance=Performance6ForceAtlas2.performance=Performance
7ForceAtlas2.threads=Threads
78
8ForceAtlas2.scalingRatio.name=Scaling9ForceAtlas2.scalingRatio.name=Scaling
9ForceAtlas2.scalingRatio.desc=How much repulsion you want. More makes a more sparse graph.10ForceAtlas2.scalingRatio.desc=How much repulsion you want. More makes a more sparse graph.
10ForceAtlas2.gravity.name=Gravity11ForceAtlas2.gravity.name=Gravity
11ForceAtlas2.gravity.desc=Attracts nodes to the center. Prevents islands from drifting away.12ForceAtlas2.gravity.desc=Attracts nodes to the center. Prevents islands from drifting away.
13ForceAtlas2.strongGravityMode.name=Stronger Gravity
14ForceAtlas2.strongGravityMode.desc=A stronger gravity law
12ForceAtlas2.distributedAttraction.name=Dissuade Hubs15ForceAtlas2.distributedAttraction.name=Dissuade Hubs
13ForceAtlas2.distributedAttraction.desc=Distributes attraction along outbound edges. Hubs attract less and thus are pushed to the borders.16ForceAtlas2.distributedAttraction.desc=Distributes attraction along outbound edges. Hubs attract less and thus are pushed to the borders.
14ForceAtlas2.linLogMode.name=LinLog mode17ForceAtlas2.linLogMode.name=LinLog mode
@@ -23,3 +26,5 @@
23ForceAtlas2.barnesHutTheta.desc=Theta of the Barnes Hut optimization.26ForceAtlas2.barnesHutTheta.desc=Theta of the Barnes Hut optimization.
24ForceAtlas2.edgeWeightInfluence.name=Edge Weight Influence27ForceAtlas2.edgeWeightInfluence.name=Edge Weight Influence
25ForceAtlas2.edgeWeightInfluence.desc=How much influence you give to the edges weight. 0 is "no influence" and 1 is "normal".28ForceAtlas2.edgeWeightInfluence.desc=How much influence you give to the edges weight. 0 is "no influence" and 1 is "normal".
29ForceAtlas2.threads.name=Threads number
30ForceAtlas2.threads.desc=More threads means more speed if your cores can handle it.
2631
=== modified file 'LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/Bundle_fr.properties'
--- LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/Bundle_fr.properties 2011-06-05 21:30:01 +0000
+++ LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/Bundle_fr.properties 2011-08-30 14:28:25 +0000
@@ -4,11 +4,14 @@
4ForceAtlas2.tuning=R\u00e9glages fins4ForceAtlas2.tuning=R\u00e9glages fins
5ForceAtlas2.behavior=Options de comportement5ForceAtlas2.behavior=Options de comportement
6ForceAtlas2.performance=Performances6ForceAtlas2.performance=Performances
7ForceAtlas2.threads=Processus
78
8ForceAtlas2.scalingRatio.name=Dimensionnement9ForceAtlas2.scalingRatio.name=Dimensionnement
9ForceAtlas2.scalingRatio.desc=Quantit\u00e9 de r\u00e9pulsion, par rapport \u00e0 l'attraction. Rend le graphe plus \u00e9tal\u00e9.10ForceAtlas2.scalingRatio.desc=Quantit\u00e9 de r\u00e9pulsion, par rapport \u00e0 l'attraction. Rend le graphe plus \u00e9tal\u00e9.
10ForceAtlas2.gravity.name=Gravit\u00e911ForceAtlas2.gravity.name=Gravit\u00e9
11ForceAtlas2.gravity.desc=Attire les noeuds vers le centre. Emp\u00eache les \u00eelots de d\u00e9river \u00e0 l'infini.12ForceAtlas2.gravity.desc=Attire les noeuds vers le centre. Emp\u00eache les \u00eelots de d\u00e9river \u00e0 l'infini.
13ForceAtlas2.strongGravityMode.name=Forte Gravit\u00e9
14ForceAtlas2.strongGravityMode.desc=Une loi de gravit\u00e9 plus forte
12ForceAtlas2.distributedAttraction.name=Dissuader les Hubs15ForceAtlas2.distributedAttraction.name=Dissuader les Hubs
13ForceAtlas2.distributedAttraction.desc=Distribue l'attraction dans les liens sortants. Les Hubs attirent moins et sont donc repouss\u00e9s en p\u00e9riph\u00e9rie.16ForceAtlas2.distributedAttraction.desc=Distribue l'attraction dans les liens sortants. Les Hubs attirent moins et sont donc repouss\u00e9s en p\u00e9riph\u00e9rie.
14ForceAtlas2.linLogMode.name=Mode LinLog17ForceAtlas2.linLogMode.name=Mode LinLog
@@ -23,3 +26,5 @@
23ForceAtlas2.barnesHutTheta.desc=param\u00e8tre Theta de l'optimisation de Barnes Hut.26ForceAtlas2.barnesHutTheta.desc=param\u00e8tre Theta de l'optimisation de Barnes Hut.
24ForceAtlas2.edgeWeightInfluence.name=Influence Poids des liens27ForceAtlas2.edgeWeightInfluence.name=Influence Poids des liens
25ForceAtlas2.edgeWeightInfluence.desc=L'influence du poides des liens. 0 c'est aucune influence, 1 c'est une influence normale et au-del\u00e0 \u00e7a accentue l'importance du poids des liens dans la spatialisation.28ForceAtlas2.edgeWeightInfluence.desc=L'influence du poides des liens. 0 c'est aucune influence, 1 c'est une influence normale et au-del\u00e0 \u00e7a accentue l'importance du poids des liens dans la spatialisation.
29ForceAtlas2.threads.name=Nb. processus
30ForceAtlas2.threads.desc=Plus de processus multiplient les performances si vos processeurs peuvent les supporter.
2631
=== modified file 'LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/ForceAtlas2.java'
--- LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/ForceAtlas2.java 2011-06-05 21:30:01 +0000
+++ LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/ForceAtlas2.java 2011-08-30 14:28:25 +0000
@@ -22,6 +22,10 @@
2222
23import java.util.ArrayList;23import java.util.ArrayList;
24import java.util.List;24import java.util.List;
25import java.util.concurrent.ExecutionException;
26import java.util.concurrent.ExecutorService;
27import java.util.concurrent.Executors;
28import java.util.concurrent.Future;
25import org.gephi.data.attributes.type.TimeInterval;29import org.gephi.data.attributes.type.TimeInterval;
26import org.gephi.dynamic.DynamicUtilities;30import org.gephi.dynamic.DynamicUtilities;
27import org.gephi.dynamic.api.DynamicController;31import org.gephi.dynamic.api.DynamicController;
@@ -37,6 +41,7 @@
37import org.gephi.layout.spi.LayoutBuilder;41import org.gephi.layout.spi.LayoutBuilder;
38import org.gephi.layout.spi.LayoutProperty;42import org.gephi.layout.spi.LayoutProperty;
39import org.gephi.project.api.Workspace;43import org.gephi.project.api.Workspace;
44import org.openide.util.Exceptions;
40import org.openide.util.Lookup;45import org.openide.util.Lookup;
41import org.openide.util.NbBundle;46import org.openide.util.NbBundle;
4247
@@ -60,10 +65,13 @@
60 private boolean barnesHutOptimize;65 private boolean barnesHutOptimize;
61 private double barnesHutTheta;66 private double barnesHutTheta;
62 private boolean linLogMode;67 private boolean linLogMode;
68 private boolean strongGravityMode;
69 private int threadCount;
63 private Region rootRegion;70 private Region rootRegion;
64 double outboundAttCompensation = 1;71 double outboundAttCompensation = 1;
65 //Dynamic Weight72 //Dynamic Weight
66 private TimeInterval timeInterval;73 private TimeInterval timeInterval;
74 private ExecutorService pool;
6775
68 public ForceAtlas2(ForceAtlas2Builder layoutBuilder) {76 public ForceAtlas2(ForceAtlas2Builder layoutBuilder) {
69 this.layoutBuilder = layoutBuilder;77 this.layoutBuilder = layoutBuilder;
@@ -93,6 +101,9 @@
93 nLayout.dx = 0;101 nLayout.dx = 0;
94 nLayout.dy = 0;102 nLayout.dy = 0;
95 }103 }
104
105 pool = Executors.newFixedThreadPool(threadCount);
106
96 }107 }
97108
98 @Override109 @Override
@@ -140,33 +151,45 @@
140 outboundAttCompensation /= nodes.length;151 outboundAttCompensation /= nodes.length;
141 }152 }
142153
143 // Repulsion154 // Repulsion (and gravity)
155 // NB: Muti-threaded
144 RepulsionForce Repulsion = ForceFactory.builder.buildRepulsion(isAdjustSizes(), getScalingRatio());156 RepulsionForce Repulsion = ForceFactory.builder.buildRepulsion(isAdjustSizes(), getScalingRatio());
145 if (isBarnesHutOptimize()) {157
146 for (Node n : nodes) {158 int taskCount = 8*threadCount; // The threadPool Executor Service will manage the fetching of tasks and threads.
147 rootRegion.applyForce(n, Repulsion, getBarnesHutTheta());159 // We make more tasks than threads because some tasks may need more time to compute.
148 }160 ArrayList<Future> threads = new ArrayList();
149 } else {161 for(int t=taskCount; t>0; t--){
150 for (int n1Index = 0; n1Index < nodes.length; n1Index++) {162 int from = (int) Math.floor(nodes.length*(t-1)/taskCount);
151 Node n1 = nodes[n1Index];163 int to = (int) Math.floor(nodes.length*t/taskCount);
152 for (int n2Index = 0; n2Index < n1Index; n2Index++) {164 Future future = pool.submit(new NodesThread(nodes, from, to, isBarnesHutOptimize(), getBarnesHutTheta(), getGravity(), (isStrongGravityMode())?(ForceFactory.builder.getStrongGravity(getScalingRatio())):(Repulsion), getScalingRatio(), rootRegion, Repulsion));
153 Node n2 = nodes[n2Index];165 threads.add(future);
154 Repulsion.apply(n1, n2);166 }
155 }167 for(Future future : threads) {
156 }168 try {
157 }169 future.get();
158170 } catch (InterruptedException ex) {
171 Exceptions.printStackTrace(ex);
172 } catch (ExecutionException ex) {
173 Exceptions.printStackTrace(ex);
174 }
175 }
176
159 // Attraction177 // Attraction
160 AttractionForce Attraction = ForceFactory.builder.buildAttraction(isLinLogMode(), isOutboundAttractionDistribution(), isAdjustSizes(), 1 * ((isOutboundAttractionDistribution()) ? (outboundAttCompensation) : (1)));178 AttractionForce Attraction = ForceFactory.builder.buildAttraction(isLinLogMode(), isOutboundAttractionDistribution(), isAdjustSizes(), 1 * ((isOutboundAttractionDistribution()) ? (outboundAttCompensation) : (1)));
161 for (Edge e : edges) {179 if(getEdgeWeightInfluence()==0){
162 Attraction.apply(e.getSource(), e.getTarget(), Math.pow(getWeight(e), getEdgeWeightInfluence()));180 for (Edge e : edges) {
163 }181 Attraction.apply(e.getSource(), e.getTarget(), 1);
164182 }
165 // Gravity183 } else if(getEdgeWeightInfluence()==1){
166 for (Node n : nodes) {184 for (Edge e : edges) {
167 Repulsion.apply(n, getGravity() / getScalingRatio());185 Attraction.apply(e.getSource(), e.getTarget(), getWeight(e));
168 }186 }
169187 } else {
188 for (Edge e : edges) {
189 Attraction.apply(e.getSource(), e.getTarget(), Math.pow(getWeight(e), getEdgeWeightInfluence()));
190 }
191 }
192
170 // Auto adjust speed193 // Auto adjust speed
171 double totalSwinging = 0d; // How much irregular movement194 double totalSwinging = 0d; // How much irregular movement
172 double totalEffectiveTraction = 0d; // Hom much useful movement195 double totalEffectiveTraction = 0d; // Hom much useful movement
@@ -198,10 +221,10 @@
198 // when the node swings.221 // when the node swings.
199 double swinging = Math.sqrt((nLayout.old_dx - nLayout.dx) * (nLayout.old_dx - nLayout.dx) + (nLayout.old_dy - nLayout.dy) * (nLayout.old_dy - nLayout.dy));222 double swinging = Math.sqrt((nLayout.old_dx - nLayout.dx) * (nLayout.old_dx - nLayout.dx) + (nLayout.old_dy - nLayout.dy) * (nLayout.old_dy - nLayout.dy));
200 double factor = 0.1 * speed / (1f + speed * Math.sqrt(swinging));223 double factor = 0.1 * speed / (1f + speed * Math.sqrt(swinging));
201224
202 double df = Math.sqrt(Math.pow(nLayout.dx, 2) + Math.pow(nLayout.dy, 2));225 double df = Math.sqrt(Math.pow(nLayout.dx, 2) + Math.pow(nLayout.dy, 2));
203 factor = Math.min(factor * df, 10.) / df;226 factor = Math.min(factor * df, 10.) / df;
204227
205 double x = nData.x() + nLayout.dx * factor;228 double x = nData.x() + nLayout.dx * factor;
206 double y = nData.y() + nLayout.dy * factor;229 double y = nData.y() + nLayout.dy * factor;
207230
@@ -220,7 +243,7 @@
220 double swinging = Math.sqrt((nLayout.old_dx - nLayout.dx) * (nLayout.old_dx - nLayout.dx) + (nLayout.old_dy - nLayout.dy) * (nLayout.old_dy - nLayout.dy));243 double swinging = Math.sqrt((nLayout.old_dx - nLayout.dx) * (nLayout.old_dx - nLayout.dx) + (nLayout.old_dy - nLayout.dy) * (nLayout.old_dy - nLayout.dy));
221 //double factor = speed / (1f + Math.sqrt(speed * swinging));244 //double factor = speed / (1f + Math.sqrt(speed * swinging));
222 double factor = speed / (1f + speed * Math.sqrt(swinging));245 double factor = speed / (1f + speed * Math.sqrt(swinging));
223246
224 double x = nData.x() + nLayout.dx * factor;247 double x = nData.x() + nLayout.dx * factor;
225 double y = nData.y() + nLayout.dy * factor;248 double y = nData.y() + nLayout.dy * factor;
226249
@@ -242,6 +265,7 @@
242 for (Node n : graph.getNodes()) {265 for (Node n : graph.getNodes()) {
243 n.getNodeData().setLayoutData(null);266 n.getNodeData().setLayoutData(null);
244 }267 }
268 pool.shutdown();
245 graph.readUnlockAll();269 graph.readUnlockAll();
246 }270 }
247271
@@ -251,6 +275,7 @@
251 final String FORCEATLAS2_TUNING = NbBundle.getMessage(getClass(), "ForceAtlas2.tuning");275 final String FORCEATLAS2_TUNING = NbBundle.getMessage(getClass(), "ForceAtlas2.tuning");
252 final String FORCEATLAS2_BEHAVIOR = NbBundle.getMessage(getClass(), "ForceAtlas2.behavior");276 final String FORCEATLAS2_BEHAVIOR = NbBundle.getMessage(getClass(), "ForceAtlas2.behavior");
253 final String FORCEATLAS2_PERFORMANCE = NbBundle.getMessage(getClass(), "ForceAtlas2.performance");277 final String FORCEATLAS2_PERFORMANCE = NbBundle.getMessage(getClass(), "ForceAtlas2.performance");
278 final String FORCEATLAS2_THREADS = NbBundle.getMessage(getClass(), "ForceAtlas2.threads");
254279
255 try {280 try {
256 properties.add(LayoutProperty.createProperty(281 properties.add(LayoutProperty.createProperty(
@@ -261,6 +286,13 @@
261 "getScalingRatio", "setScalingRatio"));286 "getScalingRatio", "setScalingRatio"));
262287
263 properties.add(LayoutProperty.createProperty(288 properties.add(LayoutProperty.createProperty(
289 this, Boolean.class,
290 NbBundle.getMessage(getClass(), "ForceAtlas2.strongGravityMode.name"),
291 FORCEATLAS2_TUNING,
292 NbBundle.getMessage(getClass(), "ForceAtlas2.strongGravityMode.desc"),
293 "isStrongGravityMode", "setStrongGravityMode"));
294
295 properties.add(LayoutProperty.createProperty(
264 this, Double.class,296 this, Double.class,
265 NbBundle.getMessage(getClass(), "ForceAtlas2.gravity.name"),297 NbBundle.getMessage(getClass(), "ForceAtlas2.gravity.name"),
266 FORCEATLAS2_TUNING,298 FORCEATLAS2_TUNING,
@@ -315,6 +347,13 @@
315 FORCEATLAS2_PERFORMANCE,347 FORCEATLAS2_PERFORMANCE,
316 NbBundle.getMessage(getClass(), "ForceAtlas2.barnesHutTheta.desc"),348 NbBundle.getMessage(getClass(), "ForceAtlas2.barnesHutTheta.desc"),
317 "getBarnesHutTheta", "setBarnesHutTheta"));349 "getBarnesHutTheta", "setBarnesHutTheta"));
350
351 properties.add(LayoutProperty.createProperty(
352 this, Integer.class,
353 NbBundle.getMessage(getClass(), "ForceAtlas2.threads.name"),
354 FORCEATLAS2_THREADS,
355 NbBundle.getMessage(getClass(), "ForceAtlas2.threads.desc"),
356 "getThreadsCount", "setThreadsCount"));
318357
319 } catch (Exception e) {358 } catch (Exception e) {
320 e.printStackTrace();359 e.printStackTrace();
@@ -337,6 +376,7 @@
337 } else {376 } else {
338 setScalingRatio(10.0);377 setScalingRatio(10.0);
339 }378 }
379 setStrongGravityMode(false);
340 setGravity(1.);380 setGravity(1.);
341381
342 // Behavior382 // Behavior
@@ -359,6 +399,7 @@
359 setBarnesHutOptimize(false);399 setBarnesHutOptimize(false);
360 }400 }
361 setBarnesHutTheta(1.2);401 setBarnesHutTheta(1.2);
402 setThreadsCount(2);
362 }403 }
363404
364 @Override405 @Override
@@ -418,6 +459,14 @@
418 this.scalingRatio = scalingRatio;459 this.scalingRatio = scalingRatio;
419 }460 }
420461
462 public Boolean isStrongGravityMode() {
463 return strongGravityMode;
464 }
465
466 public void setStrongGravityMode(Boolean strongGravityMode) {
467 this.strongGravityMode = strongGravityMode;
468 }
469
421 public Double getGravity() {470 public Double getGravity() {
422 return gravity;471 return gravity;
423 }472 }
@@ -425,6 +474,18 @@
425 public void setGravity(Double gravity) {474 public void setGravity(Double gravity) {
426 this.gravity = gravity;475 this.gravity = gravity;
427 }476 }
477
478 public Integer getThreadsCount() {
479 return threadCount;
480 }
481
482 public void setThreadsCount(Integer threadCount) {
483 if(threadCount<1){
484 setThreadsCount(1);
485 } else {
486 this.threadCount = threadCount;
487 }
488 }
428489
429 public Boolean isOutboundAttractionDistribution() {490 public Boolean isOutboundAttractionDistribution() {
430 return outboundAttractionDistribution;491 return outboundAttractionDistribution;
431492
=== modified file 'LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/ForceFactory.java'
--- LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/ForceFactory.java 2011-06-05 21:30:01 +0000
+++ LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/ForceFactory.java 2011-08-30 14:28:25 +0000
@@ -22,6 +22,7 @@
2222
23import org.gephi.graph.api.Node;23import org.gephi.graph.api.Node;
24import org.gephi.graph.api.NodeData;24import org.gephi.graph.api.NodeData;
25import org.openide.util.Exceptions;
2526
26/**27/**
27 * Generates the forces on demand, here are all the formulas for attraction and repulsion.28 * Generates the forces on demand, here are all the formulas for attraction and repulsion.
@@ -43,6 +44,10 @@
43 return new linRepulsion(coefficient);44 return new linRepulsion(coefficient);
44 }45 }
45 }46 }
47
48 public RepulsionForce getStrongGravity(double coefficient){
49 return new strongGravity(coefficient);
50 }
4651
47 public AttractionForce buildAttraction(boolean logAttraction, boolean distributedAttraction, boolean adjustBySize, double coefficient) {52 public AttractionForce buildAttraction(boolean logAttraction, boolean distributedAttraction, boolean adjustBySize, double coefficient) {
48 if (adjustBySize) {53 if (adjustBySize) {
@@ -75,7 +80,7 @@
75 }80 }
76 }81 }
77 }82 }
7883
79 public abstract class AttractionForce {84 public abstract class AttractionForce {
8085
81 public abstract void apply(Node n1, Node n2, double e); // Model for node-node attraction (e is for edge weight if needed)86 public abstract void apply(Node n1, Node n2, double e); // Model for node-node attraction (e is for edge weight if needed)
@@ -141,7 +146,7 @@
141146
142 nLayout.dx += xDist * factor;147 nLayout.dx += xDist * factor;
143 nLayout.dy += yDist * factor;148 nLayout.dy += yDist * factor;
144 }149 }
145 }150 }
146151
147 @Override152 @Override
@@ -165,7 +170,7 @@
165 }170 }
166171
167 /*172 /*
168 * Repulsion force: Linear with Anti-collision173 * Repulsion force: Strong Gravity (as a Repulsion Force because it is easier)
169 */174 */
170 private class linRepulsion_antiCollision extends RepulsionForce {175 private class linRepulsion_antiCollision extends RepulsionForce {
171176
@@ -252,6 +257,44 @@
252 }257 }
253 }258 }
254259
260 private class strongGravity extends RepulsionForce {
261
262 private double coefficient;
263
264 public strongGravity(double c) {
265 coefficient = c;
266 }
267
268 @Override
269 public void apply(Node n1, Node n2) {
270 // Not Relevant
271 }
272
273 @Override
274 public void apply(Node n, Region r) {
275 // Not Relevant
276 }
277
278 @Override
279 public void apply(Node n, double g) {
280 NodeData nData = n.getNodeData();
281 ForceAtlas2LayoutData nLayout = nData.getLayoutData();
282
283 // Get the distance
284 double xDist = nData.x();
285 double yDist = nData.y();
286 double distance = (float) Math.sqrt(xDist * xDist + yDist * yDist);
287
288 if (distance > 0) {
289 // NB: factor = force / distance
290 double factor = coefficient * nLayout.mass * g;
291
292 nLayout.dx -= xDist * factor;
293 nLayout.dy -= yDist * factor;
294 }
295 }
296 }
297
255 /*298 /*
256 * Attraction force: Linear299 * Attraction force: Linear
257 */300 */
258301
=== added file 'LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/NodesThread.java'
--- LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/NodesThread.java 1970-01-01 00:00:00 +0000
+++ LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/NodesThread.java 2011-08-30 14:28:25 +0000
@@ -0,0 +1,64 @@
1/*
2 * To change this template, choose Tools | Templates
3 * and open the template in the editor.
4 */
5package org.gephi.layout.plugin.forceAtlas2;
6
7import org.gephi.graph.api.Node;
8import org.gephi.layout.plugin.forceAtlas2.ForceFactory.RepulsionForce;
9
10/**
11 *
12 * @author Mathieu
13 */
14public class NodesThread implements Runnable{
15 private Node[] nodes;
16 private int from;
17 private int to;
18 private Region rootRegion;
19 private boolean barnesHutOptimize;
20 private RepulsionForce Repulsion;
21 private double barnesHutTheta;
22 private double gravity;
23 private RepulsionForce GravityForce;
24 private double scaling;
25
26 public NodesThread(Node[] nodes, int from, int to, boolean barnesHutOptimize, double barnesHutTheta, double gravity, RepulsionForce GravityForce, double scaling, Region rootRegion, RepulsionForce Repulsion){
27 this.nodes = nodes;
28 this.from = from;
29 this.to = to;
30 this.rootRegion = rootRegion;
31 this.barnesHutOptimize = barnesHutOptimize;
32 this.Repulsion = Repulsion;
33 this.barnesHutTheta = barnesHutTheta;
34 this.gravity = gravity;
35 this.GravityForce = GravityForce;
36 this.scaling = scaling;
37 }
38
39 @Override
40 public void run() {
41 // Repulsion
42 if (barnesHutOptimize) {
43 for (int nIndex = from; nIndex < to; nIndex++) {
44 Node n = nodes[nIndex];
45 rootRegion.applyForce(n, Repulsion, barnesHutTheta);
46 }
47 } else {
48 for (int n1Index = from; n1Index < to; n1Index++) {
49 Node n1 = nodes[n1Index];
50 for (int n2Index = 0; n2Index < n1Index; n2Index++) {
51 Node n2 = nodes[n2Index];
52 Repulsion.apply(n1, n2);
53 }
54 }
55 }
56
57 // Gravity
58 for (int nIndex = from; nIndex < to; nIndex++) {
59 Node n = nodes[nIndex];
60 GravityForce.apply(n, gravity / scaling);
61 }
62 }
63
64}
065
=== added file 'LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/Operation.java'
--- LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/Operation.java 1970-01-01 00:00:00 +0000
+++ LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/Operation.java 2011-08-30 14:28:25 +0000
@@ -0,0 +1,13 @@
1/*
2 * To change this template, choose Tools | Templates
3 * and open the template in the editor.
4 */
5package org.gephi.layout.plugin.forceAtlas2;
6
7/**
8 *
9 * @author Mathieu
10 */
11public abstract class Operation {
12 public abstract void execute();
13}
014
=== added file 'LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/OperationNodeNodeAttract.java'
--- LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/OperationNodeNodeAttract.java 1970-01-01 00:00:00 +0000
+++ LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/OperationNodeNodeAttract.java 2011-08-30 14:28:25 +0000
@@ -0,0 +1,32 @@
1/*
2 * To change this template, choose Tools | Templates
3 * and open the template in the editor.
4 */
5package org.gephi.layout.plugin.forceAtlas2;
6
7import org.gephi.graph.api.Node;
8import org.gephi.layout.plugin.forceAtlas2.ForceFactory.AttractionForce;
9
10/**
11 *
12 * @author Mathieu
13 */
14public class OperationNodeNodeAttract extends Operation{
15 private Node n1;
16 private Node n2;
17 private AttractionForce f;
18 private double coefficient;
19
20 public OperationNodeNodeAttract(Node n1, Node n2, AttractionForce f, double coefficient){
21 this.n1 = n1;
22 this.n2 = n2;
23 this.f = f;
24 this.coefficient = coefficient;
25 }
26
27 @Override
28 public void execute() {
29 f.apply(n1, n2, coefficient);
30 }
31
32}
033
=== added file 'LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/OperationNodeNodeRepulse.java'
--- LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/OperationNodeNodeRepulse.java 1970-01-01 00:00:00 +0000
+++ LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/OperationNodeNodeRepulse.java 2011-08-30 14:28:25 +0000
@@ -0,0 +1,29 @@
1/*
2 * To change this template, choose Tools | Templates
3 * and open the template in the editor.
4 */
5package org.gephi.layout.plugin.forceAtlas2;
6
7import org.gephi.graph.api.Node;
8import org.gephi.layout.plugin.forceAtlas2.ForceFactory.RepulsionForce;
9
10/**
11 *
12 * @author Mathieu
13 */
14public class OperationNodeNodeRepulse extends Operation{
15 private Node n1;
16 private Node n2;
17 private RepulsionForce f;
18
19 public OperationNodeNodeRepulse(Node n1, Node n2, RepulsionForce f){
20 this.n1 = n1;
21 this.n2 = n2;
22 this.f = f;
23 }
24
25 @Override
26 public void execute() {
27 f.apply(n1, n2);
28 }
29}
030
=== added file 'LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/OperationNodeRegionRepulse.java'
--- LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/OperationNodeRegionRepulse.java 1970-01-01 00:00:00 +0000
+++ LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/OperationNodeRegionRepulse.java 2011-08-30 14:28:25 +0000
@@ -0,0 +1,32 @@
1/*
2 * To change this template, choose Tools | Templates
3 * and open the template in the editor.
4 */
5package org.gephi.layout.plugin.forceAtlas2;
6
7import org.gephi.graph.api.Node;
8import org.gephi.layout.plugin.forceAtlas2.ForceFactory.RepulsionForce;
9
10/**
11 *
12 * @author Mathieu
13 */
14public class OperationNodeRegionRepulse extends Operation{
15 private Node n;
16 private Region r;
17 private RepulsionForce f;
18 private double theta;
19
20 public OperationNodeRegionRepulse(Node n, Region r, RepulsionForce f, double theta){
21 this.n = n;
22 this.f = f;
23 this.r = r;
24 this.theta = theta;
25 }
26
27 @Override
28 public void execute() {
29 r.applyForce(n, f, theta);
30 }
31
32}
033
=== added file 'LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/OperationNodeRepulse.java'
--- LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/OperationNodeRepulse.java 1970-01-01 00:00:00 +0000
+++ LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/OperationNodeRepulse.java 2011-08-30 14:28:25 +0000
@@ -0,0 +1,29 @@
1/*
2 * To change this template, choose Tools | Templates
3 * and open the template in the editor.
4 */
5package org.gephi.layout.plugin.forceAtlas2;
6
7import org.gephi.graph.api.Node;
8import org.gephi.layout.plugin.forceAtlas2.ForceFactory.RepulsionForce;
9
10/**
11 *
12 * @author Mathieu
13 */
14public class OperationNodeRepulse extends Operation{
15 private Node n;
16 private RepulsionForce f;
17 private double coefficient;
18
19 public OperationNodeRepulse(Node n, RepulsionForce f, double coefficient){
20 this.n = n;
21 this.f = f;
22 this.coefficient = coefficient;
23 }
24
25 @Override
26 public void execute() {
27 f.apply(n, coefficient);
28 }
29}
030
=== modified file 'LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/Region.java'
--- LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/Region.java 2011-06-05 21:30:01 +0000
+++ LayoutPlugin/src/org/gephi/layout/plugin/forceAtlas2/Region.java 2011-08-30 14:28:25 +0000
@@ -51,7 +51,7 @@
51 updateMassAndGeometry();51 updateMassAndGeometry();
52 }52 }
5353
54 public void updateMassAndGeometry() {54 private void updateMassAndGeometry() {
55 if (nodes.size() > 1) {55 if (nodes.size() > 1) {
56 // Compute Mass56 // Compute Mass
57 mass = 0;57 mass = 0;
@@ -77,7 +77,7 @@
77 }77 }
78 }78 }
7979
80 public void buildSubRegions() {80 public synchronized void buildSubRegions() {
81 if (nodes.size() > 1) {81 if (nodes.size() > 1) {
82 ArrayList<Node> leftNodes = new ArrayList<Node>();82 ArrayList<Node> leftNodes = new ArrayList<Node>();
83 ArrayList<Node> rightNodes = new ArrayList<Node>();83 ArrayList<Node> rightNodes = new ArrayList<Node>();

Subscribers

People subscribed via source and target branches