title: D3.js how do I arrange nodes of a force layout to be on a circle
body: <p>I have developed a force layout to represent relationships between social groups. Now I would like to get the nodes to be distributed in a circle with links joining them. What is the best way to do this? </p>
  
  <p>The complete version of the code (without data) is here <a href="http://jsfiddle.net/PatriciaW/zZSJT/" rel="nofollow">http://jsfiddle.net/PatriciaW/zZSJT/</a>
  (Why do I have to include code here too? Here is the main portion)</p>
  
  <pre><code>d3.json("/relationships?nocache=" + (new Date()).getTime(),function(error,members){
     var links=members.organizations.map(function(members) {
        return members.member;
        });
  
  var nodes = {};
  
  links.forEach(function(link) {
    link.source = nodes[link.xsource] || (nodes[link.xsource] = {source: link.xsource, name: link.xsource, category: link.categorysource, path: link.pathsource, desc: link.descsource, title: link.titlesource});
    link.target = nodes[link.xtarget] || (nodes[link.xtarget] = {target: link.xtarget, name: link.xtarget, category: link.categorytarget, path: link.pathtarget, desc: link.desctarget, title: link.titletarget});
  });
  
  force = d3.layout.force()
  .nodes(d3.values(nodes))
  .links(links)
  .size([width, height])
  .charge(-120)
  .linkDistance(function() {return (Math.random() * 200) + 100;})
  .linkStrength(0.5)
  .on("tick", tick)
  .start();
  
  var link = svg.selectAll(".link")
  .data(force.links())
  .enter().append("line")
  .attr("class", "link");
  
  var node_drag = d3.behavior.drag()
      .on("dragstart", dragstart)
      .on("drag", dragmove)
      .on("dragend", dragend);
  
  var loading = svg.append("text")
  .attr("x", width / 2)
  .attr("y", height / 2)
  .attr("dy", ".35em")
  .style("text-anchor", "middle")
  .text("Simulating. One moment please…");
  
  function dragstart(d, i) {
      force.stop() // stops the force auto positioning before you start dragging
  }
  
  function dragmove(d, i) {
      d.px += d3.event.dx;
      d.py += d3.event.dy;
      d.x += d3.event.dx;
      d.y += d3.event.dy; 
      tick(); // this is the key to make it work together with updating both px,py,x,y on d !
  }
  
  function dragend(d, i) {
      d.fixed = true; // of course set the node to fixed so the force doesn't include the node in its auto positioning stuff
      tick();
      force.resume();
  };
  
  var node = svg.selectAll(".node")
  .data(force.nodes())
  .enter().append("g")
  .attr("class", "node")
  .on("mouseover", mouseover)
  .on("mouseout", mouseout)
  .on("click", clickAlert)
  .call(node_drag);
  
  node.append("circle")
  .attr("r", 8)
  .style("fill", function(d) { 
     return categoryColour [d.category];
     })  
  
  // add an image marker
  node.append("image")
    .attr("x",-8)
    .attr("y",-8)
    .attr("width", 16)
    .attr("height", 16)
    .attr("xlink:href", function(d) {
        return categoryImage [d.category]
     })
    .on("click", clickAlert)
    .style("cursor", "pointer")
  
  node.append("text")
    .attr("x", 12)
    .attr("dy", ".35em")
    .text(function(d) { 
        return d.name; 
        });
  // Use a timeout to allow the rest of the page to load first.
  setTimeout(function() {
  
  // Run the layout a fixed number of times.
  // The ideal number of times scales with graph complexity.
  force.start();
  for (var i = n * n; i &gt; 0; --i) force.tick();
  force.stop();
  
  svg.selectAll("line")
  .data(links)
  .enter().append("line")
  .attr("x1", function(d) { return d.source.x; })
  .attr("y1", function(d) { return d.source.y; })
  .attr("x2", function(d) { return d.target.x; })
  .attr("y2", function(d) { return d.target.y; });
  
  svg.selectAll("circle")
  .data(nodes)
  .enter().append("circle")
  .attr("cx", function(d) { return d.x; })
  .attr("cy", function(d) { return d.y; })
  .attr("r", 4.5);
  
  loading.remove();
  }, 10);
  
  function tick() {
  link
    .attr("x1", function(d) { 
         return d.source.x + xadj; })
    .attr("y1", function(d) { 
         return d.source.y + yadj; })
    .attr("x2", function(d) { 
         return d.target.x +xadj; })
    .attr("y2", function(d) { 
         return d.target.y +yadj; });
  node
    .attr("transform", function(d) { 
         return "translate(" + (d.x + xadj) + "," + (d.y + yadj) + ")"; 
    });
  };
  
  function mouseover() {
   d3.select(this).select("circle").transition()
    .duration(750)
    .attr("r", 16);
  d3.select(this).select("text")
     .attr("font-size","34px")
     .style("font-weight", "bold");
  };
  
  function mouseout() {
  d3.select(this).select("circle").transition()
   .duration(750)
   .attr("r", 8);
  d3.select(this).select("text")
    .attr("font-size","12px")
    .style("font-weight", "normal");
  };
  }) // end json
  </code></pre>