title: Create node cluster's focal points by data attribute in d3?
body: <p>I'm trying to force nodes into different clusters in force layout based on a certain attribute in the data like "group." I'm adapting the code from Mike Bostock's multi foci force layout example (<a href="https://gist.github.com/mbostock/1021953" rel="nofollow">code</a>, <a href="http://static.cybercommons.org/js/d3/examples/force/force-multi-foci.html" rel="nofollow">example</a>) and I've been successful in adding in my own data but I haven't been able to specify how many clusters there are and how to assign a node to a cluster.</p>
  
  <p>I'm relatively new to d3 and JavaScript and I haven't been able to find many examples of multi foci applications. Here's my d3 code, any help or input is appreciated:</p>
  
  <pre><code>    var width = 960,
      height = 500;
  
      var fill = d3.scale.category10();
  
  
      d3.json("test.json" , function(error, json){
  
         var root = json.nodes[0];
  
         root.radius = 0;
         root.fixed = true;  
  
        var force = d3.layout.force()
           .nodes(json.nodes)
           .size([width, height])
           .gravity(0.06)
           .charge(function(d, i) { return i ? 0 : -2000; })
           .on("tick", tick)
           .start();
  
        var svg = d3.select("body").append("svg")
           .attr("width", width)
           .attr("height", height);
  
        var elem = svg.selectAll(".elem")
           .data(json.nodes)
           .enter()
           .append("g")
           .attr("class", "elem");
  
    elem.append("circle")
    .attr("cx", function(d) { return d.x; })
    .attr("cy", function(d) { return d.y; })
    .attr("r", 40)
    .style("fill", function(d, i) { return fill(i &amp; 3); })
    .style("stroke", function(d, i) { return d3.rgb(fill(i &amp; 3)).darker(2); })
    .call(force.drag)
    .on("mousedown", function() { d3.event.stopPropagation(); });
  
    elem.append("text")
    .text(function(d){ return d.name; });
  
    svg.style("opacity", 1e-6)
      .transition()
      .duration(1000)
      .style("opacity", 1);
  
    d3.select("body")
      .on("mousedown", mousedown);
  </code></pre>
  
  <p>I've specifically been trying to figure out how this tick function is working. I did some research and found that the "&amp;" is a bitwise operator and I noticed that changing the number after it is what is changing how many clusters there are and which nodes are in each. But preferably I would like to be able to point to something like d.group here to specify the cluster. </p>
  
  <pre><code> function tick(e) {
  
      // Push different nodes in different directions for clustering.
      var k = 6 * e.alpha;
      json.nodes.forEach(function(o, i) {
  
          o.y += i &amp; 3 ? k : -k;
          o.x += i &amp; 2 ? k : -k;      
      });
  
   var q = d3.geom.quadtree(json.nodes),
        i = 0,
        n = json.nodes.length;
  
   while (++i &lt; n) q.visit(collide(json.nodes[i]));
  
   svg.selectAll("circle")
       .attr("cx", function(d) { return d.x; })
       .attr("cy", function(d) { return d.y; });
  
   svg.selectAll("text")
       .attr("x", function(d) { return d.x; })
       .attr("y", function(d) { return d.y; });
   }
  
    function collide(node) {
    var r = node.radius + 16,
        nx1 = node.x - r,
        nx2 = node.x + r,
        ny1 = node.y - r,
        ny2 = node.y + r;
    return function(quad, x1, y1, x2, y2) {
      if (quad.point &amp;&amp; (quad.point !== node)) {
        var x = node.x - quad.point.x,
            y = node.y - quad.point.y,
            l = Math.sqrt(x * x + y * y),
            r = node.radius + quad.point.radius;
        if (l &lt; r) {
          l = (l - r) / l * .5;
          node.x -= x *= l;
          node.y -= y *= l;
          quad.point.x += x;
          quad.point.y += y;
        }
      }
      return x1 &gt; nx2 || x2 &lt; nx1 || y1 &gt; ny2 || y2 &lt; ny1;
    };
  }
  
  svg.on("mousemove", function() {
    var p1 = d3.mouse(this);
    root.px = p1[0];
    root.py = p1[1];
    force.resume();
  }); 
  
  function mousedown() {
    json.nodes.forEach(function(o, i) {
    o.x += (Math.random() - .5) * 40;
    o.y += (Math.random() - .5) * 40;
  });
  
  force.resume();
  }
  });
  </code></pre>
  
  <p>*Note that I have also implemented collision detection to repel nodes but I don't think this is affecting the clusters at the moment.</p>
  
  <p>My data is currently stored in a json file called test.json:</p>
  
  <pre><code> {
    "nodes":[
      {
          "name":     "Null",
          "radius":   40,
          "color":    "#ff0000",
          "gravity": 0.05,
          "group": 1
          },
          {
          "name":     "One",
          "radius":   40,
          "color":    "#ffff00",
          "gravity": 0.05,
          "group": 1
          },
          {
          "name":     "Two",
          "radius":   40,
          "color":    "#33cc33",
          "gravity": 0.2,
          "group": 1
          },
          {
          "name":     "Three",
          "radius":   40,
          "color":    "#3399ff",
          "gravity": 0.9,
          "group": 1
          },
          {
          "name":     "Four",
          "radius":   40,
          "color":    "#ffff00",
          "gravity": 0.05,
          "group": 6
          },
          {
          "name":     "Five",
          "radius":   40,
          "color":    "#33cc33",
          "gravity": 0.2,
          "group": 6
          },
          {
          "name":     "Six",
          "radius":   40,
          "color":    "#3399ff",
          "gravity": 0.9,
          "group": 6
          }             
  
    ]
  }
  </code></pre>