diff --git a/modules/LayoutPlugin/src/main/java/org/gephi/layout/plugin/forceAtlas2/ForceAtlas2.java b/modules/LayoutPlugin/src/main/java/org/gephi/layout/plugin/forceAtlas2/ForceAtlas2.java index 2f63a2ff2f4833508f54151484b2f34ff7a2294c..bdd62d8704bf4799cbda16feb120cede187d188a 100644 --- a/modules/LayoutPlugin/src/main/java/org/gephi/layout/plugin/forceAtlas2/ForceAtlas2.java +++ b/modules/LayoutPlugin/src/main/java/org/gephi/layout/plugin/forceAtlas2/ForceAtlas2.java @@ -83,6 +83,7 @@ public class ForceAtlas2 implements Layout { private boolean barnesHutOptimize; private double barnesHutTheta; private boolean linLogMode; + private boolean normalizeEdgeWeights; private boolean strongGravityMode; private int threadCount; private int currentThreadCount; @@ -216,13 +217,56 @@ public class ForceAtlas2 implements Layout { Attraction.apply(e.getSource(), e.getTarget(), 1); } } else if (getEdgeWeightInfluence() == 1) { - for (Edge e : edges) { - Attraction.apply(e.getSource(), e.getTarget(), getEdgeWeight(e, isDynamicWeight, interval)); + if (isNormalizeEdgeWeights()) { + Double w; + Double edgeWeightMin = Double.MAX_VALUE; + Double edgeWeightMax = Double.MIN_VALUE; + for (Edge e : edges) { + w = getEdgeWeight(e, isDynamicWeight, interval); + edgeWeightMin = Math.min(w, edgeWeightMin); + edgeWeightMax = Math.max(w, edgeWeightMax); + } + if (edgeWeightMin < edgeWeightMax) { + for (Edge e : edges) { + w = (getEdgeWeight(e, isDynamicWeight, interval) - edgeWeightMin) / (edgeWeightMax - edgeWeightMin); + Attraction.apply(e.getSource(), e.getTarget(), w); + } + } else { + for (Edge e : edges) { + Attraction.apply(e.getSource(), e.getTarget(), 1.); + } + } + } else { + for (Edge e : edges) { + Attraction.apply(e.getSource(), e.getTarget(), getEdgeWeight(e, isDynamicWeight, interval)); + } } } else { - for (Edge e : edges) { - Attraction.apply(e.getSource(), e.getTarget(), - Math.pow(getEdgeWeight(e, isDynamicWeight, interval), getEdgeWeightInfluence())); + if (isNormalizeEdgeWeights()) { + Double w; + Double edgeWeightMin = Double.MAX_VALUE; + Double edgeWeightMax = Double.MIN_VALUE; + for (Edge e : edges) { + w = getEdgeWeight(e, isDynamicWeight, interval); + edgeWeightMin = Math.min(w, edgeWeightMin); + edgeWeightMax = Math.max(w, edgeWeightMax); + } + if (edgeWeightMin < edgeWeightMax) { + for (Edge e : edges) { + w = (getEdgeWeight(e, isDynamicWeight, interval) - edgeWeightMin) / (edgeWeightMax - edgeWeightMin); + Attraction.apply(e.getSource(), e.getTarget(), + Math.pow(w, getEdgeWeightInfluence())); + } + } else { + for (Edge e : edges) { + Attraction.apply(e.getSource(), e.getTarget(), 1.); + } + } + } else { + for (Edge e : edges) { + Attraction.apply(e.getSource(), e.getTarget(), + Math.pow(getEdgeWeight(e, isDynamicWeight, interval), getEdgeWeightInfluence())); + } } } @@ -409,6 +453,14 @@ public class ForceAtlas2 implements Layout { NbBundle.getMessage(getClass(), "ForceAtlas2.edgeWeightInfluence.desc"), "getEdgeWeightInfluence", "setEdgeWeightInfluence")); + properties.add(LayoutProperty.createProperty( + this, Boolean.class, + NbBundle.getMessage(getClass(), "ForceAtlas2.normalizeEdgeWeights.name"), + FORCEATLAS2_BEHAVIOR, + "ForceAtlas2.normalizeEdgeWeights.name", + NbBundle.getMessage(getClass(), "ForceAtlas2.normalizeEdgeWeights.desc"), + "isNormalizeEdgeWeights", "setNormalizeEdgeWeights")); + properties.add(LayoutProperty.createProperty( this, Double.class, NbBundle.getMessage(getClass(), "ForceAtlas2.jitterTolerance.name"), @@ -470,6 +522,7 @@ public class ForceAtlas2 implements Layout { setLinLogMode(false); setAdjustSizes(false); setEdgeWeightInfluence(1.); + setNormalizeEdgeWeights(true); // Performance setJitterTolerance(1d); @@ -522,6 +575,14 @@ public class ForceAtlas2 implements Layout { this.linLogMode = linLogMode; } + public Boolean isNormalizeEdgeWeights() { + return normalizeEdgeWeights; + } + + public void setNormalizeEdgeWeights(Boolean normalizeEdgeWeights) { + this.normalizeEdgeWeights = normalizeEdgeWeights; + } + public Double getScalingRatio() { return scalingRatio; } diff --git a/modules/LayoutPlugin/src/main/resources/org/gephi/layout/plugin/forceAtlas2/Bundle.properties b/modules/LayoutPlugin/src/main/resources/org/gephi/layout/plugin/forceAtlas2/Bundle.properties index 7eaf6ca7b21ef3d404a919ab7bc886b300564c7f..6cd72af88cb2aef959130df8b278631d535668d6 100644 --- a/modules/LayoutPlugin/src/main/resources/org/gephi/layout/plugin/forceAtlas2/Bundle.properties +++ b/modules/LayoutPlugin/src/main/resources/org/gephi/layout/plugin/forceAtlas2/Bundle.properties @@ -16,6 +16,8 @@ ForceAtlas2.distributedAttraction.name=Dissuade Hubs ForceAtlas2.distributedAttraction.desc=Distributes attraction along outbound edges. Hubs attract less and thus are pushed to the borders. ForceAtlas2.linLogMode.name=LinLog mode ForceAtlas2.linLogMode.desc=Switch ForceAtlas' model from lin-lin to lin-log (tribute to Andreas Noack). Makes clusters more tight. +ForceAtlas2.normalizeEdgeWeights.name=Normalize edge weights +ForceAtlas2.normalizeEdgeWeights.desc=Puts edge weights between 0 and 1. ForceAtlas2.adjustSizes.name=Prevent Overlap ForceAtlas2.adjustSizes.desc=Use only when spatialized. Should not be used with "Approximate Repulsion" ForceAtlas2.jitterTolerance.name=Tolerance (speed) diff --git a/modules/LayoutPlugin/src/main/resources/org/gephi/layout/plugin/forceAtlas2/Bundle_fr.properties b/modules/LayoutPlugin/src/main/resources/org/gephi/layout/plugin/forceAtlas2/Bundle_fr.properties index 2bb2f73627d38493b0f8401029ca3ebb3cff1514..88b7e143458985d2c3b165ff679b449342a355d3 100644 --- a/modules/LayoutPlugin/src/main/resources/org/gephi/layout/plugin/forceAtlas2/Bundle_fr.properties +++ b/modules/LayoutPlugin/src/main/resources/org/gephi/layout/plugin/forceAtlas2/Bundle_fr.properties @@ -14,6 +14,8 @@ ForceAtlas2.distributedAttraction.name=Dissuader les Hubs ForceAtlas2.distributedAttraction.desc=Distribue l'attraction le long des liens sortants. Les hubs attirent moins et sont ainsi poussés vers les bords. ForceAtlas2.linLogMode.name=Mode LinLog ForceAtlas2.linLogMode.desc=Bascule le modèle de lin-lin à lin-log (en hommage à Andreas Noack). Rend les clusters plus resserrés. +ForceAtlas2.normalizeEdgeWeights.name=Normalise le poids des liens +ForceAtlas2.normalizeEdgeWeights.desc=Fait comme si le poids des liens était compris entre 0 et 1 ForceAtlas2.adjustSizes.name=Empêcher le Recouvrement ForceAtlas2.adjustSizes.desc=Utiliser seulement une fois spatialisé. Ne devrait pas être utilisé avec "Répulsion approximative" ForceAtlas2.jitterTolerance.name=Tolérance (vitesse)