title: Optimize d3 force directed layout, via charge/gravity properties, based on number of nodes
body: <p>I've been working on a network topology visualization using the force-directed algorithm built into D3. Everything is working well but having troubles with one important detail... I can't seem to get the graph to layout in an ideal way for graphs with a varying number of nodes. By ideal, i mean the nodes are nicely spaced out from each (no overlap) and nodes cluster wherever it makes sense. I've been trying to do this by adjusting the 'charge' and 'gravity' properties of the force layout, but no matter what i try, it seems to always work for one scenario (ie. large number of nodes), but not for another scenario (ie. small number of nodes). For example, if i have the layout working for a large graph, then when i look at small graph using the same formula for charge/gravity, ill have a few nodes that are way way out of site from the rest of the nodes. Here's an example of a formula i was using based on another SO question <a href="https://stackoverflow.com/questions/9901565/charge-based-on-size-d3-force-layout">post</a>:</p>
  
  <pre><code>var k = Math.sqrt(json.nodes.length / (dim.w * dim.h));
  var charge = -10 / k;
  var gravity = 100 * k;
  </code></pre>
  
  <p>This works for a graph with 14 nodes, but if i try the same with a graph of 5 nodes, some of those nodes are completely off the screen. Note that the width/height used in the calculation of 'k' is not changing between these two scenarios. Now maybe i shouldn't have these properties based on the width/height of visible area of graph. To be honest, this is not a requirement. I don't need the graph to render and fit within the viewport of graph. I just need the graph to lay itself out sensibly, so it's fine if some of it may be outside of visible area, especially in a large graph. I've also tried the following with some success, but i still find nodes are being rendered too far away from the rest of the graph for small graphs:</p>
  
  <pre><code>var charge = -1 * Math.pow(json.nodes.length, 3);
  var gravity = 1 / json.nodes.length;
  </code></pre>
  
  <p>Can anyone out there help me out with this ? Would be greatly appreciated as i feel kind of stuck on this atm.</p>