title: How to keep d3.forceSimulation() nodes evenly spread without overlapping
body: <p>I am trying to make a graph, where certain nodes should be on the left side, and certain nodes should be on the right side from the "genesis node" which should be in the center of my svg.</p>
  
  <p><strong>Setting up the force:</strong></p>
  
  <ul>
  <li>d3.forceManyBody() so the nodes should repel each other</li>
  <li>d3.forceLink().distance(60).strength(1) so the links will maintain
  their length </li>
  <li>d3.forceCenter(width / 2, height / 2) to position the
  main node in the center. I have also tried removing this but only makes the graph appear in the top left corner with only a tiny bit of a node visible</li>
  </ul>
  
  <p>So at the end it looks like this:</p>
  
  <pre><code>var simulation = d3.forceSimulation()
         .force("link", d3.forceLink().id(function (d) {
                return d.id;}).distance(60).strength(1))
         .force("charge", d3.forceManyBody())
         .force("center", d3.forceCenter(width / 2, height / 2));
  </code></pre>
  
  <p><strong>Setting up the nodes:</strong>
  I have also tried setting the attr <code>x</code> and <code>y</code>, instead of <code>cx</code> and <code>cy</code>, but nothing changes. <code>xCenter</code> and <code>yCenter</code> are the center of the svg where the graph is displayed.</p>
  
  <pre><code>node = svg.selectAll(".node")
      .data(nodes)
      .enter()
      .append("g")
      .attr("class", "node");
  
  node.append("circle")
      .attr("r", 6)
      .attr("cx", function (d) {
         return colors(d.position*20 + xCenter);})
      .attr("cy", function (d) {return colors(yCenter);})
      .style("fill", function (d) {return colors(d.group);})
  </code></pre>
  
  <p><strong>Updating the simulation</strong></p>
  
  <pre><code>function ticked() {
     node
         .attr("transform", function (d) {
              return "translate(" + d.x + ", " + d.y + ")";});
  }
  </code></pre>
  
  <p>I have also tried this, but not luck:</p>
  
  <pre><code>function ticked() {
         node
             .attr("cx", function(d) { return d.cx; })
             .attr("cy", function(d) { return d.cy; });
      }
  </code></pre>
  
  <p>This is what I get :(
  <a href="https://i.stack.imgur.com/NkmYL.png" rel="noreferrer"><img src="https://i.stack.imgur.com/NkmYL.png" alt="enter image description here"></a></p>
  
  <p>And this is more what I was looking for (I can set it up by dragging myself I just want it to appear like this directly)
  <a href="https://i.stack.imgur.com/AWQOU.png" rel="noreferrer"><img src="https://i.stack.imgur.com/AWQOU.png" alt="enter image description here"></a></p>
  
  <p><strong>Data source structure:</strong>
  The position 0 means in the center, negative positions mean to go to the left, positive positions mean to go to the right</p>
  
  <pre><code>{
    "graphNodes": [
      {
        "id": "Q20514253",
        "label": "label",
        "description": "description",
        "group": 0,
        "position": 0
      }],
    "graphLinks": [
     {
        "source": "Q8513",
        "target": "Q20514253",
        "type": "instanceOf"
     }],
   }
  </code></pre>
  
  <hr>
  
  <p><strong>=============================== EDIT ==================================</strong></p>
  
  <p><strong>POSITION CALCULATION:</strong></p>
  
  <p>Each node has a position number, negative means to the left, positive means to the right.
  1 level to the left is -1, 2 levels to the left is -2.
  1 level to the right is 1, 2 levels to the right is 2.</p>
  
  <p><em>X position is like this:</em>
  X = d.position*20 + xCenter  // so each level is 20 pixeles apart </p>
  
  <p><em>Y position</em> I just put = yCenter, so they are all vertically centered, and then I hoped because the nodes where charged to repel each other they would distribute evenly and vertically</p>
  
  <p><strong>Full working code:</strong></p>
  
  <pre><code>var nodeDescription = document.querySelector(".node-description")
  var colors = d3.scaleOrdinal(d3.schemeCategory10);
  
      var svg = d3.select("svg"),
          width = +svg.attr("width"),
          height = +svg.attr("height"),
          node,
          link;
  
      svg.append('defs').append('marker')
          .attrs({'id':'arrowhead',
              'viewBox':'-0 -5 10 10',
              'refX':13,
              'refY':0,
              'orient':'auto',
              'markerWidth':13,
              'markerHeight':8,
              'xoverflow':'visible'})
          .append('svg:path')
          .attr('d', 'M 0,-5 L 10 ,0 L 0,5')
          .attr('fill', '#999')
          .style('stroke','none');
  
      var simulation = d3.forceSimulation()
          .force("link", d3.forceLink().id(function (d) {return d.id;}).distance(60).strength(1))
          .force("charge", d3.forceManyBody())
          .force("center", d3.forceCenter(width / 2, height / 2));
  
  
  
  function update(links, nodes) {
  
          var graphPlaceholder = document.querySelector(".graph-placeholder")
          width = graphPlaceholder.offsetWidth
          var xCenter = width/2
          height = graphPlaceholder.offsetHeight
          var yCenter = height/2
  
          svg
            .attr("width", width)
            .attr("height", height)
  
          simulation.force("center", d3.forceCenter(xCenter, yCenter));
  
          link = svg.selectAll(".link")
              .data(links)
              .enter()
              .append("line")
              .attr("class", "link")
              .attr('marker-end','url(#arrowhead)')
  
          link.append("title")
              .text(function (d) {return d.type;});
  
          edgepaths = svg.selectAll(".edgepath")
              .data(links)
              .enter()
              .append('path')
              .attrs({
                  'class': 'edgepath',
                  'fill-opacity': 0,
                  'stroke-opacity': 0,
                  'id': function (d, i) {return 'edgepath' + i}
              })
              .style("pointer-events", "none");
  
          edgelabels = svg.selectAll(".edgelabel")
              .data(links)
              .enter()
              .append('text')
              .style("pointer-events", "none")
              .attrs({
                  'class': 'edgelabel',
                  'id': function (d, i) {return 'edgelabel' + i},
                  'font-size': 10,
                  'fill': '#aaa'
              });
  
          edgelabels.append('textPath')
              .attr('xlink:href', function (d, i) {return '#edgepath' + i})
              .style("text-anchor", "middle")
              .style("pointer-events", "none")
              .attr("startOffset", "50%")
              .text(function (d) {return d.type});
  
          node = svg.selectAll(".node")
              .data(nodes)
              .enter()
              .append("g")
              .attr("class", "node")
              .call(d3.drag()
                      .on("start", dragstarted)
                      .on("drag", dragged)
                      //.on("end", dragended)
              ).on("click", function(d){
                  nodeDescription.innerHTML =  d.label + ": " + d.description;
              });
  
  
  
          node.append("circle")
              .attr("r", 6)
              .attr("x", function (d) {return colors(d.position*20 + xCenter);})
              .attr("y", function (d) {return colors(yCenter);})
              .style("fill", function (d) {return colors(d.group);})
  
          node.append("title")
              .text(function (d) {return d.id;});
  
          node.append("text")
              .attr("dy", -9)
              .text(function (d) {return d.label;});
  
          simulation
              .nodes(nodes)
              .on("tick", ticked);
  
          simulation.force("link")
              .links(links);
      }
  
      function ticked() {
  
          link
              .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;});
  
          node
              .attr("transform", function (d) {return "translate(" + d.x + ", " + d.y + ")";});
  
          edgepaths.attr('d', function (d) {
              return 'M ' + d.source.x + ' ' + d.source.y + ' L ' + d.target.x + ' ' + d.target.y;
          });
  
          edgelabels.attr('transform', function (d) {
              if (d.target.x &lt; d.source.x) {
                  var bbox = this.getBBox();
  
                  rx = bbox.x + bbox.width / 2;
                  ry = bbox.y + bbox.height / 2;
                  return 'rotate(180 ' + rx + ' ' + ry + ')';
              }
              else {
                  return 'rotate(0)';
              }
          });
      }
  
      function dragstarted(d) {
          if (!d3.event.active) simulation.alphaTarget(0.3).restart()
          d.fx = d.x;
          d.fy = d.y;
      }
  
      function dragged(d) {
          d.fx = d3.event.x;
          d.fy = d3.event.y;
      }
  </code></pre>
  
  <p><strong>Full dataset</strong></p>
  
  <pre><code>{
    "graphNodes": [
      {
        "id": "http://www.wikidata.org/entity/Q395",
        "label": "mathematics",
        "description": "field of study (numbers, quantity, structure, relationships, space, change)",
        "group": 0,
        "position": 0
      },
      {
        "id": "http://www.wikidata.org/entity/Q41511",
        "label": "universal language",
        "description": "hypothetical language that is supposed to have been spoken by all or most of the world's population",
        "group": 6,
        "position": -1
      },
      {
        "id": "http://www.wikidata.org/entity/Q4671286",
        "label": "academic major",
        "description": "academic discipline to which a student formally commits",
        "group": 6,
        "position": -1
      },
      {
        "id": "http://www.wikidata.org/entity/Q11862829",
        "label": "academic discipline",
        "description": "concentration in one academic field of study or profession",
        "group": 6,
        "position": -1
      },
      {
        "id": "http://www.wikidata.org/entity/Q475023",
        "label": "exact science",
        "description": "",
        "group": 9,
        "position": -1
      },
      {
        "id": "http://www.wikidata.org/entity/Q816264",
        "label": "formal science",
        "description": "disciplines concerned with formal systems, such as logic, mathematics, and game theory",
        "group": 9,
        "position": -1
      },
      {
        "id": "Mathematics",
        "label": "Mathematics",
        "description": "",
        "group": 13,
        "position": -1
      },
      {
        "id": "http://www.wikidata.org/entity/Q30125896",
        "label": "scientific hypothesis",
        "description": "idea that proposes a tentative explanation about a phenomenon or a narrow set of phenomena observed in the natural world (primary features of a scientific hypothesis: falsifiability, testability)",
        "group": 6,
        "position": -2
      },
      {
        "id": "http://www.wikidata.org/entity/Q2623733",
        "label": "fictional language",
        "description": "language in fictional stories",
        "group": 9,
        "position": -2
      },
      {
        "id": "http://www.wikidata.org/entity/Q1047113",
        "label": "specialty",
        "description": "field limited to a specific area of ​​knowledge",
        "group": 9,
        "position": -2
      },
      {
        "id": "Academic disciplines",
        "label": "Academic disciplines",
        "description": "",
        "group": 13,
        "position": -2
      },
      {
        "id": "http://www.wikidata.org/entity/Q2465832",
        "label": "branch of science",
        "description": "field or discipline of science",
        "group": 6,
        "position": -2
      },
      {
        "id": "http://www.wikidata.org/entity/Q336",
        "label": "science",
        "description": "study and knowledge",
        "group": 9,
        "position": -2
      },
      {
        "id": "http://www.wikidata.org/entity/Q3968",
        "label": "algebra",
        "description": "topic in mathematics and definition is Algebra uses letters (like x or y) or other symbols in place of values, and plays with them using special rules.",
        "group": 1,
        "position": 1
      },
      {
        "id": "http://www.wikidata.org/entity/Q8087",
        "label": "geometry",
        "description": "branch of mathematics that measures the shape, size and position of objects",
        "group": 1,
        "position": 1
      },
      {
        "id": "http://www.wikidata.org/entity/Q12479",
        "label": "number theory",
        "description": "branch of pure mathematics devoted primarily to the study of the integers",
        "group": 1,
        "position": 1
      },
      {
        "id": "http://www.wikidata.org/entity/Q12482",
        "label": "set theory",
        "description": "branch of mathematics that studies sets, which are collections of objects",
        "group": 1,
        "position": 1
      },
      {
        "id": "http://www.wikidata.org/entity/Q12483",
        "label": "statistics",
        "description": "study of the collection, organization, analysis, interpretation, and presentation of data",
        "group": 1,
        "position": 1
      },
      {
        "id": "http://www.wikidata.org/entity/Q42989",
        "label": "topology",
        "description": "subfield of mathematics",
        "group": 1,
        "position": 1
      },
      {
        "id": "http://www.wikidata.org/entity/Q131476",
        "label": "graph theory",
        "description": "study of graphs, which are mathematical structures used to model pairwise relations between objects",
        "group": 1,
        "position": 1
      },
      {
        "id": "http://www.wikidata.org/entity/Q149972",
        "label": "calculus",
        "description": "branch of mathematics",
        "group": 1,
        "position": 1
      },
      {
        "id": "http://www.wikidata.org/entity/Q217413",
        "label": "category theory",
        "description": "logic and mathematics",
        "group": 1,
        "position": 1
      },
      {
        "id": "http://www.wikidata.org/entity/Q5862903",
        "label": "probability theory",
        "description": "branch of mathematics concerned with probability",
        "group": 1,
        "position": 1
      },
      {
        "id": "http://www.wikidata.org/entity/Q1192971",
        "label": "network theory",
        "description": "study of graphs as a representation of either symmetric relations or, more generally, of asymmetric relations between discrete objects",
        "group": 1,
        "position": 2
      },
      {
        "id": "http://www.wikidata.org/entity/Q149999",
        "label": "differential calculus",
        "description": "subfield of calculus",
        "group": 1,
        "position": 2
      },
      {
        "id": "http://www.wikidata.org/entity/Q150008",
        "label": "integral calculus",
        "description": "subfield of calculus",
        "group": 1,
        "position": 2
      }
    ],
    "graphLinks": [
      {
        "source": "http://www.wikidata.org/entity/Q41511",
        "target": "http://www.wikidata.org/entity/Q395",
        "type": "instanceOf"
      },
      {
        "source": "http://www.wikidata.org/entity/Q4671286",
        "target": "http://www.wikidata.org/entity/Q395",
        "type": "instanceOf"
      },
      {
        "source": "http://www.wikidata.org/entity/Q11862829",
        "target": "http://www.wikidata.org/entity/Q395",
        "type": "instanceOf"
      },
      {
        "source": "http://www.wikidata.org/entity/Q475023",
        "target": "http://www.wikidata.org/entity/Q395",
        "type": "subclassOf"
      },
      {
        "source": "http://www.wikidata.org/entity/Q816264",
        "target": "http://www.wikidata.org/entity/Q395",
        "type": "subclassOf"
      },
      {
        "source": "Mathematics",
        "target": "http://www.wikidata.org/entity/Q395",
        "type": "CommonCategory"
      },
      {
        "source": "http://www.wikidata.org/entity/Q30125896",
        "target": "http://www.wikidata.org/entity/Q41511",
        "type": "instanceOf"
      },
      {
        "source": "http://www.wikidata.org/entity/Q2623733",
        "target": "http://www.wikidata.org/entity/Q41511",
        "type": "subclassOf"
      },
      {
        "source": "http://www.wikidata.org/entity/Q11862829",
        "target": "http://www.wikidata.org/entity/Q4671286",
        "type": "subclassOf"
      },
      {
        "source": "http://www.wikidata.org/entity/Q1047113",
        "target": "http://www.wikidata.org/entity/Q11862829",
        "type": "subclassOf"
      },
      {
        "source": "Academic disciplines",
        "target": "http://www.wikidata.org/entity/Q11862829",
        "type": "CommonCategory"
      },
      {
        "source": "http://www.wikidata.org/entity/Q2465832",
        "target": "http://www.wikidata.org/entity/Q475023",
        "type": "instanceOf"
      },
      {
        "source": "http://www.wikidata.org/entity/Q336",
        "target": "http://www.wikidata.org/entity/Q475023",
        "type": "subclassOf"
      },
      {
        "source": "http://www.wikidata.org/entity/Q2465832",
        "target": "http://www.wikidata.org/entity/Q816264",
        "type": "instanceOf"
      },
      {
        "source": "http://www.wikidata.org/entity/Q475023",
        "target": "http://www.wikidata.org/entity/Q816264",
        "type": "subclassOf"
      },
      {
        "source": "http://www.wikidata.org/entity/Q395",
        "target": "http://www.wikidata.org/entity/Q3968",
        "type": "hasPart"
      },
      {
        "source": "http://www.wikidata.org/entity/Q395",
        "target": "http://www.wikidata.org/entity/Q8087",
        "type": "hasPart"
      },
      {
        "source": "http://www.wikidata.org/entity/Q395",
        "target": "http://www.wikidata.org/entity/Q12479",
        "type": "hasPart"
      },
      {
        "source": "http://www.wikidata.org/entity/Q395",
        "target": "http://www.wikidata.org/entity/Q12482",
        "type": "hasPart"
      },
      {
        "source": "http://www.wikidata.org/entity/Q395",
        "target": "http://www.wikidata.org/entity/Q12483",
        "type": "hasPart"
      },
      {
        "source": "http://www.wikidata.org/entity/Q395",
        "target": "http://www.wikidata.org/entity/Q42989",
        "type": "hasPart"
      },
      {
        "source": "http://www.wikidata.org/entity/Q395",
        "target": "http://www.wikidata.org/entity/Q131476",
        "type": "hasPart"
      },
      {
        "source": "http://www.wikidata.org/entity/Q395",
        "target": "http://www.wikidata.org/entity/Q149972",
        "type": "hasPart"
      },
      {
        "source": "http://www.wikidata.org/entity/Q395",
        "target": "http://www.wikidata.org/entity/Q217413",
        "type": "hasPart"
      },
      {
        "source": "http://www.wikidata.org/entity/Q395",
        "target": "http://www.wikidata.org/entity/Q5862903",
        "type": "hasPart"
      },
      {
        "source": "http://www.wikidata.org/entity/Q131476",
        "target": "http://www.wikidata.org/entity/Q1192971",
        "type": "hasPart"
      },
      {
        "source": "http://www.wikidata.org/entity/Q149972",
        "target": "http://www.wikidata.org/entity/Q149999",
        "type": "hasPart"
      },
      {
        "source": "http://www.wikidata.org/entity/Q149972",
        "target": "http://www.wikidata.org/entity/Q150008",
        "type": "hasPart"
      }
    ],
  </code></pre>
  
  <h2>    }</h2>
  
  <p><strong>============================= EDIT 2 ===============================</strong></p>
  
  <p>I managed to get something very weird
  <a href="https://i.stack.imgur.com/AHfT8.png" rel="noreferrer"><img src="https://i.stack.imgur.com/AHfT8.png" alt="enter image description here"></a></p>