block by emeeks 068ef3e4106e155467a3

Orbital Layout of D3.js API

Full Screen

An example of d3.layout.orbit that visualizes the D3 API.

When you mouseover a node, it displays its label and centers the orbit layout on that node. It also draws spokes to children and parents where applicable.

index.html

<html xmlns="//www.w3.org/1999/xhtml">
<head>
  <title>Orbit Layout Modes</title>
  <meta charset="utf-8" />
</head>
<style>

  #viz, svg {
    width: 100%;
    height: 100%;
  }

  text {
    pointer-events: none;
  }

  #buttons {
    position: fixed;
    top:0;
    left:0;
  }

  circle.ring {
    fill: none;
    stroke: black;
    stroke-width: 1px;
    stroke-opacity: .15;

  }
  
</style>
<script>


function makeViz() {

  d3.json("d3.json", function(data) {drawOrbit(data)});

}

function drawOrbit(_data) {

  var center = {};
  var recenter = false;


  for (var x=0;x<_data.children.length;x++) {
    _data.children[x].size = _data.children[x].children ? _data.children[x].children.length : 0;
  }

  _data.children.sort(function(a,b) {
        if (a.size > b.size) {
          return 1;
        }
        if (a.size < b.size) {
          return -1;
        }
        return 0;
  })


  sizeScale = d3.scale.linear().domain([0,1,5,10,20]).range([4,6,8,10,12]).clamp(true);
  colorScale = d3.scale.linear().domain([0,1,2,3,4]).range(["rgb(161,208,120)","rgb(247,148,72)","rgb(225,203,208)","rgb(174,223,228)","rgb(245,132,102)"]);

  planetColors = {Mercury: "gray", Venus: "#d6bb87", Earth: "#677188", Mars: "#7c5541", Jupiter: "#a36a3e", Saturn: "#e9ba85", Uranus: "#73cbf0", Neptune: "#6383d1"}


  orbit = d3.layout.orbit().size([800,800])
  .revolution(customRevolution)
  .orbitSize(function(d) {return d.depth >= 2 ? 6 : 4})
  .speed(.25)
  .mode([35,36,8,3,1])
  .nodes(_data);

  center = orbit.nodes()[0];

  d3.select("svg")
.append("g")
.attr("class", "viz")
.attr("transform", "translate(50,50)")
  .selectAll("g.node").data(orbit.nodes())
  .enter()
  .append("g")
  .attr("class", "node")
  .attr("transform", function(d) {return "translate(" +d.x +"," + d.y+")"})
  .on("mouseover", nodeOver)
  .on("click", recenter)

  d3.selectAll("g.node")
  .append("circle")
  .attr("class", "satellite")
  .attr("r", function(d) {return sizeScale(d.children ? d.children.length : 0)})
  .style("fill", function(d) {return colorScale(d.depth)})
  .style("stroke", "brown")
  .style("stroke-width", "1px")

  d3.selectAll("g.node").filter(function(d) {return d.depth == 1})
  .append("text")
  .text(function(d) {return d.depth == 0 ? "Sun" : d.key})
  .attr("y", 20)
  .style("text-anchor", "middle")

  d3.select("g.viz")
  .selectAll("circle.ring")
  .data(orbit.orbitalRings())
  .enter()
  .insert("circle", "g")
  .attr("class", "ring")
  .attr("r", function(d) {return d.r})
  .attr("cx", function(d) {return d.x})
  .attr("cy", function(d) {return d.y})

  orbit.on("tick", orbitTick);

  orbit.start();

  function orbitTick() {

    var newX = 200- center.x;
    var newY = 200 - center.y;

    d3.select("g.viz")
    .attr("transform", "scale("+(1 + (center.depth *.1)) +") translate(" + newX + "," + newY + ")")


    d3.selectAll("g.node")
      .attr("transform", function(d) {return "translate(" +d.x +"," + d.y+")"});

    d3.selectAll("circle.ring")
    .attr("cx", function(d) {return d.x})
    .attr("cy", function(d) {return d.y});

        d3.selectAll("line.visible")
        .attr("x1", function(p) {return p.source.x})
        .attr("x2", function(p) {return p.target.x})
        .attr("y1", function(p) {return p.source.y})
        .attr("y2", function(p) {return p.target.y})

  }

  function changeCenter() {
        recenter = false;
        orbit.stop();
    var newX = 200 - center.x;
    var newY = 200 - center.y;

    d3.select("g.viz")
    .transition()
    .duration(1000)
    .attr("transform", "scale("+(1 + (center.depth *.1)) +") translate(" + newX + "," + newY + ")")
    .each("end", function() {orbit.start()})

  }

  function customRevolution(d) 
  {
    if (d.name == "time") {
      return d.depth * .25;
    }
    if (d.name == "geo") {
      return -d.depth * .25;      
    }
    return d.depth
  }

  function nodeOver(d) {
    orbit.stop();

      center = d;
      changeCenter();

      d3.selectAll("text.sat").remove();

      d3.selectAll("line.visible").remove();

      if (d.children) {
        var lines = d.children.map(function(p) {return {source: d, target: p}})
        d3.select("g.viz").selectAll("line.visible")
        .data(lines)
        .enter()
        .insert("line", "g")
        .attr("x1", function(p) {return p.source.x})
        .attr("x2", function(p) {return p.target.x})
        .attr("y1", function(p) {return p.source.y})
        .attr("y2", function(p) {return p.target.y})
        .attr("class", "visible")
        .style("stroke", "rgb(73,106,154)")
        .style("stroke-width", 2)
      }

      if (d.parent) {

        d3.select("g.viz").selectAll("line.fake")
        .data([{source:d, target: d.parent}])
        .enter()
        .insert("line", "g")
        .attr("x1", function(p) {return p.source.x})
        .attr("x2", function(p) {return p.target.x})
        .attr("y1", function(p) {return p.source.y})
        .attr("y2", function(p) {return p.target.y})
        .attr("class", "visible")
        .style("stroke", "rgb(165,127,124)")
        .style("stroke-width", 3)
      }


      d3.selectAll("g.node")
      .filter(function(p) {return p == d || p == d.parent || (d.children ? d.children.indexOf(p) > -1 : false)})
      .append("text")
      .text(function(p) {return p.name})
      .style("text-anchor", "middle")
      .attr("y", 15)
      .attr("class", "sat")
      .style("fill", "none")
      .style("stroke", "white")
      .style("stroke-width", 3)
      .style("stroke-opacity", .7);

      d3.selectAll("g.node")
      .filter(function(p) {return p == d || p == d.parent || (d.children ? d.children.indexOf(p) > -1 : false)})
      .append("text")
      .text(function(p) {return p.name})
      .style("text-anchor", "middle")
      .attr("y", 15)
      .attr("class", "sat");

    d3.selectAll("g.node > circle").style("stroke", "brown").style("stroke-width", 1);    

    d3.select(this).select("circle").style("stroke", "black").style("stroke-width", 3);

  }


}

</script>
<body onload="makeViz()">
<div id="viz"><svg></svg><div id="buttons"></div></div>
<footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="d3.layout.orbit.js" charset="utf-8" type="text/javascript"></script>
</footer>
</body>
</html>

d3.json

{
  "name": "d3",
  "children": [
    {"name": "version"},
    {"name": "ascending"},
    {"name": "descending"},
    {"name": "min"},
    {"name": "max"},
    {"name": "extent"},
    {"name": "sum"},
    {"name": "mean"},
    {"name": "quantile"},
    {"name": "median"},
    {"name": "variance"},
    {"name": "deviation"},
    {"name": "bisectLeft"},
    {"name": "bisectRight"},
    {"name": "bisect"},
    {"name": "bisector"},
    {"name": "shuffle"},
    {"name": "permute"},
    {"name": "pairs"},
    {"name": "zip"},
    {"name": "transpose"},
    {"name": "keys"},
    {"name": "values"},
    {"name": "entries"},
    {"name": "merge"},
    {"name": "range"},
    {"name": "map"},
    {"name": "nest"},
    {"name": "set"},
    {
      "name": "behavior",
      "children": [
        {"name": "drag"},
        {"name": "zoom"}
      ]
    },
    {"name": "rebind"},
    {"name": "dispatch"},
    {"name": "event"},
    {"name": "requote"},
    {
      "name": "selection",
      "children": [{"name": "enter"}]
    },
    {
      "name": "ns",
      "children": [
        {
          "name": "prefix",
          "children": [
            {"name": "svg"},
            {"name": "xhtml"},
            {"name": "xlink"},
            {"name": "xml"},
            {"name": "xmlns"}
          ]
        },
        {"name": "qualify"}
      ]
    },
    {"name": "select"},
    {"name": "selectAll"},
    {"name": "mouse"},
    {"name": "touch"},
    {"name": "touches"},
    {"name": "interpolateZoom"},
    {"name": "color"},
    {"name": "hsl"},
    {"name": "hcl"},
    {"name": "lab"},
    {"name": "rgb"},
    {"name": "functor"},
    {"name": "xhr"},
    {"name": "dsv"},
    {
      "name": "csv",
      "children": [
        {"name": "parse"},
        {"name": "parseRows"},
        {"name": "format"},
        {"name": "formatRows"}
      ]
    },
    {
      "name": "tsv",
      "children": [
        {"name": "parse"},
        {"name": "parseRows"},
        {"name": "format"},
        {"name": "formatRows"}
      ]
    },
    {
      "name": "timer",
      "children": [{"name": "flush"}]
    },
    {"name": "round"},
    {"name": "formatPrefix"},
    {
      "name": "time",
      "children": [
        {
          "name": "year",
          "children": [
            {"name": "round"},
            {"name": "ceil"},
            {"name": "offset"},
            {
              "name": "range",
              "children": [{"name": "utc"}]
            },
            {
              "name": "utc",
              "children": [
                {"name": "round"},
                {"name": "ceil"},
                {"name": "offset"},
                {"name": "range"}
              ]
            }
          ]
        },
        {
          "name": "years",
          "children": [{"name": "utc"}]
        },
        {
          "name": "day",
          "children": [
            {"name": "round"},
            {"name": "ceil"},
            {"name": "offset"},
            {
              "name": "range",
              "children": [{"name": "utc"}]
            },
            {
              "name": "utc",
              "children": [
                {"name": "round"},
                {"name": "ceil"},
                {"name": "offset"},
                {"name": "range"}
              ]
            }
          ]
        },
        {
          "name": "days",
          "children": [{"name": "utc"}]
        },
        {"name": "dayOfYear"},
        {
          "name": "sunday",
          "children": [
            {"name": "round"},
            {"name": "ceil"},
            {"name": "offset"},
            {
              "name": "range",
              "children": [{"name": "utc"}]
            },
            {
              "name": "utc",
              "children": [
                {"name": "round"},
                {"name": "ceil"},
                {"name": "offset"},
                {"name": "range"}
              ]
            }
          ]
        },
        {
          "name": "sundays",
          "children": [{"name": "utc"}]
        },
        {"name": "sundayOfYear"},
        {
          "name": "monday",
          "children": [
            {"name": "round"},
            {"name": "ceil"},
            {"name": "offset"},
            {
              "name": "range",
              "children": [{"name": "utc"}]
            },
            {
              "name": "utc",
              "children": [
                {"name": "round"},
                {"name": "ceil"},
                {"name": "offset"},
                {"name": "range"}
              ]
            }
          ]
        },
        {
          "name": "mondays",
          "children": [{"name": "utc"}]
        },
        {"name": "mondayOfYear"},
        {
          "name": "tuesday",
          "children": [
            {"name": "round"},
            {"name": "ceil"},
            {"name": "offset"},
            {
              "name": "range",
              "children": [{"name": "utc"}]
            },
            {
              "name": "utc",
              "children": [
                {"name": "round"},
                {"name": "ceil"},
                {"name": "offset"},
                {"name": "range"}
              ]
            }
          ]
        },
        {
          "name": "tuesdays",
          "children": [{"name": "utc"}]
        },
        {"name": "tuesdayOfYear"},
        {
          "name": "wednesday",
          "children": [
            {"name": "round"},
            {"name": "ceil"},
            {"name": "offset"},
            {
              "name": "range",
              "children": [{"name": "utc"}]
            },
            {
              "name": "utc",
              "children": [
                {"name": "round"},
                {"name": "ceil"},
                {"name": "offset"},
                {"name": "range"}
              ]
            }
          ]
        },
        {
          "name": "wednesdays",
          "children": [{"name": "utc"}]
        },
        {"name": "wednesdayOfYear"},
        {
          "name": "thursday",
          "children": [
            {"name": "round"},
            {"name": "ceil"},
            {"name": "offset"},
            {
              "name": "range",
              "children": [{"name": "utc"}]
            },
            {
              "name": "utc",
              "children": [
                {"name": "round"},
                {"name": "ceil"},
                {"name": "offset"},
                {"name": "range"}
              ]
            }
          ]
        },
        {
          "name": "thursdays",
          "children": [{"name": "utc"}]
        },
        {"name": "thursdayOfYear"},
        {
          "name": "friday",
          "children": [
            {"name": "round"},
            {"name": "ceil"},
            {"name": "offset"},
            {
              "name": "range",
              "children": [{"name": "utc"}]
            },
            {
              "name": "utc",
              "children": [
                {"name": "round"},
                {"name": "ceil"},
                {"name": "offset"},
                {"name": "range"}
              ]
            }
          ]
        },
        {
          "name": "fridays",
          "children": [{"name": "utc"}]
        },
        {"name": "fridayOfYear"},
        {
          "name": "saturday",
          "children": [
            {"name": "round"},
            {"name": "ceil"},
            {"name": "offset"},
            {
              "name": "range",
              "children": [{"name": "utc"}]
            },
            {
              "name": "utc",
              "children": [
                {"name": "round"},
                {"name": "ceil"},
                {"name": "offset"},
                {"name": "range"}
              ]
            }
          ]
        },
        {
          "name": "saturdays",
          "children": [{"name": "utc"}]
        },
        {"name": "saturdayOfYear"},
        {
          "name": "week",
          "children": [
            {"name": "round"},
            {"name": "ceil"},
            {"name": "offset"},
            {
              "name": "range",
              "children": [{"name": "utc"}]
            },
            {
              "name": "utc",
              "children": [
                {"name": "round"},
                {"name": "ceil"},
                {"name": "offset"},
                {"name": "range"}
              ]
            }
          ]
        },
        {
          "name": "weeks",
          "children": [{"name": "utc"}]
        },
        {"name": "weekOfYear"},
        {
          "name": "format",
          "children": [
            {
              "name": "utc",
              "children": [{"name": "multi"}]
            },
            {"name": "multi"},
            {
              "name": "iso",
              "children": [
                {"name": "parse"},
                {"name": "toString"}
              ]
            }
          ]
        },
        {
          "name": "second",
          "children": [
            {"name": "round"},
            {"name": "ceil"},
            {"name": "offset"},
            {
              "name": "range",
              "children": [{"name": "utc"}]
            },
            {
              "name": "utc",
              "children": [
                {"name": "round"},
                {"name": "ceil"},
                {"name": "offset"},
                {"name": "range"}
              ]
            }
          ]
        },
        {
          "name": "seconds",
          "children": [{"name": "utc"}]
        },
        {
          "name": "minute",
          "children": [
            {"name": "round"},
            {"name": "ceil"},
            {"name": "offset"},
            {
              "name": "range",
              "children": [{"name": "utc"}]
            },
            {
              "name": "utc",
              "children": [
                {"name": "round"},
                {"name": "ceil"},
                {"name": "offset"},
                {"name": "range"}
              ]
            }
          ]
        },
        {
          "name": "minutes",
          "children": [{"name": "utc"}]
        },
        {
          "name": "hour",
          "children": [
            {"name": "round"},
            {"name": "ceil"},
            {"name": "offset"},
            {
              "name": "range",
              "children": [{"name": "utc"}]
            },
            {
              "name": "utc",
              "children": [
                {"name": "round"},
                {"name": "ceil"},
                {"name": "offset"},
                {"name": "range"}
              ]
            }
          ]
        },
        {
          "name": "hours",
          "children": [{"name": "utc"}]
        },
        {
          "name": "month",
          "children": [
            {"name": "round"},
            {"name": "ceil"},
            {"name": "offset"},
            {
              "name": "range",
              "children": [{"name": "utc"}]
            },
            {
              "name": "utc",
              "children": [
                {"name": "round"},
                {"name": "ceil"},
                {"name": "offset"},
                {"name": "range"}
              ]
            }
          ]
        },
        {
          "name": "months",
          "children": [{"name": "utc"}]
        },
        {
          "name": "scale",
          "children": [{"name": "utc"}]
        }
      ]
    },
    {"name": "locale"},
    {"name": "format"},
    {
      "name": "geo",
      "children": [
        {"name": "stream"},
        {"name": "area"},
        {"name": "bounds"},
        {"name": "centroid"},
        {"name": "clipExtent"},
        {
          "name": "conicEqualArea",
          "children": [{"name": "raw"}]
        },
        {"name": "albers"},
        {"name": "albersUsa"},
        {"name": "path"},
        {"name": "transform"},
        {"name": "projection"},
        {"name": "projectionMutator"},
        {
          "name": "equirectangular",
          "children": [{"name": "raw"}]
        },
        {"name": "rotation"},
        {"name": "circle"},
        {"name": "distance"},
        {"name": "graticule"},
        {"name": "greatArc"},
        {"name": "interpolate"},
        {"name": "length"},
        {
          "name": "azimuthalEqualArea",
          "children": [
            {
              "name": "raw",
              "children": [{"name": "invert"}]
            }
          ]
        },
        {
          "name": "azimuthalEquidistant",
          "children": [
            {
              "name": "raw",
              "children": [{"name": "invert"}]
            }
          ]
        },
        {
          "name": "conicConformal",
          "children": [{"name": "raw"}]
        },
        {
          "name": "conicEquidistant",
          "children": [{"name": "raw"}]
        },
        {
          "name": "gnomonic",
          "children": [
            {
              "name": "raw",
              "children": [{"name": "invert"}]
            }
          ]
        },
        {
          "name": "mercator",
          "children": [
            {
              "name": "raw",
              "children": [{"name": "invert"}]
            }
          ]
        },
        {
          "name": "orthographic",
          "children": [
            {
              "name": "raw",
              "children": [{"name": "invert"}]
            }
          ]
        },
        {
          "name": "stereographic",
          "children": [
            {
              "name": "raw",
              "children": [{"name": "invert"}]
            }
          ]
        },
        {
          "name": "transverseMercator",
          "children": [
            {
              "name": "raw",
              "children": [{"name": "invert"}]
            }
          ]
        }
      ]
    },
    {
      "name": "geom",
      "children": [
        {"name": "hull"},
        {"name": "polygon"},
        {"name": "voronoi"},
        {"name": "delaunay"},
        {"name": "quadtree"}
      ]
    },
    {"name": "interpolateRgb"},
    {"name": "interpolateObject"},
    {"name": "interpolateNumber"},
    {"name": "interpolateString"},
    {"name": "interpolate"},
    {"name": "interpolators"},
    {"name": "interpolateArray"},
    {"name": "ease"},
    {"name": "interpolateHcl"},
    {"name": "interpolateHsl"},
    {"name": "interpolateLab"},
    {"name": "interpolateRound"},
    {"name": "transform"},
    {"name": "interpolateTransform"},
    {
      "name": "layout",
      "children": [
        {"name": "bundle"},
        {"name": "chord"},
        {"name": "force"},
        {"name": "hierarchy"},
        {"name": "partition"},
        {"name": "pie"},
        {"name": "stack"},
        {"name": "histogram"},
        {"name": "pack"},
        {"name": "tree"},
        {"name": "cluster"},
        {"name": "treemap"}
      ]
    },
    {
      "name": "random",
      "children": [
        {"name": "normal"},
        {"name": "logNormal"},
        {"name": "bates"},
        {"name": "irwinHall"}
      ]
    },
    {
      "name": "scale",
      "children": [
        {"name": "linear"},
        {"name": "log"},
        {"name": "pow"},
        {"name": "sqrt"},
        {"name": "ordinal"},
        {"name": "category10"},
        {"name": "category20"},
        {"name": "category20b"},
        {"name": "category20c"},
        {"name": "quantile"},
        {"name": "quantize"},
        {"name": "threshold"},
        {"name": "identity"}
      ]
    },
    {
      "name": "svg",
      "children": [
        {"name": "arc"},
        {
          "name": "line",
          "children": [{"name": "radial"}]
        },
        {
          "name": "area",
          "children": [{"name": "radial"}]
        },
        {"name": "chord"},
        {
          "name": "diagonal",
          "children": [{"name": "radial"}]
        },
        {"name": "symbol"},
        {"name": "symbolTypes"},
        {"name": "axis"},
        {"name": "brush"}
      ]
    },
    {"name": "transition"},
    {"name": "text"},
    {"name": "json"},
    {"name": "html"},
    {"name": "xml"},
    {"name": "hexbin"}
  ]
}

d3.layout.orbit.js

d3.layout.orbit = function() {
	var currentTickStep = 0;
	var orbitNodes;
	var orbitSize = [1,1];
	var nestedNodes;
	var flattenedNodes = [];
	var tickRadianStep = 0.004363323129985824;
    var orbitDispatch = d3.dispatch('tick');
    var tickInterval;
    var orbitalRings = [];
    var orbitDepthAdjust = function() {return 2.95};
    var childrenAccessor = function(d) {return d.children};
    var tickRadianFunction = function() {return 1};
    var fixedOrbitArray = [99];
    var orbitMode = "flat";


	function _orbitLayout() {

		return _orbitLayout;
	}

	_orbitLayout.mode = function(_mode) {
		//Atomic, Solar, other?
		if (!arguments.length) return orbitMode;

		if (_mode == "solar") {
			fixedOrbitArray = [1]
		}
		if (_mode == "atomic") {
			fixedOrbitArray = [2,8]
		}
		if (_mode == "flat") {
			fixedOrbitArray = [99]
		}
		orbitMode = _mode;
		if (Array.isArray(_mode)) {
			fixedOrbitArray = _mode;
			orbitMode = "custom";
		}
		return this
	}

	_orbitLayout.start = function() {
		//activate animation here
		tickInterval = setInterval(
			function() {
			currentTickStep++;
			flattenedNodes.forEach(function(_node){
				if (_node.parent) {
					_node.x = _node.parent.x + ( (_node.ring) * Math.sin( _node.angle + (currentTickStep * tickRadianStep * tickRadianFunction(_node))) );
					_node.y = _node.parent.y + ( (_node.ring) * Math.cos( _node.angle + (currentTickStep * tickRadianStep * tickRadianFunction(_node))) );
				}
			})
			orbitalRings.forEach(function(_ring) {
				_ring.x = _ring.source.x;
				_ring.y = _ring.source.y;
			})
			orbitDispatch.tick();
		}, 
		10);
	}

	_orbitLayout.stop = function() {
		//deactivate animation here
		clearInterval(tickInterval);
	}

	_orbitLayout.speed = function(_degrees) {
		if (!arguments.length) return tickRadianStep / (Math.PI / 360);
		tickRadianStep = tickRadianStep = _degrees * (Math.PI / 360);
		return this;
	}

	_orbitLayout.size = function(_value) {
		if (!arguments.length) return orbitSize;
		orbitSize = _value;
		return this;
		//change size here
	}

	_orbitLayout.revolution = function(_function) {
		//change ring size reduction (make that into dynamic function)
		if (!arguments.length) return tickRadianFunction;
		tickRadianFunction = _function;
		return this
	}

	_orbitLayout.orbitSize = function(_function) {
		//change ring size reduction (make that into dynamic function)
		if (!arguments.length) return orbitDepthAdjust;
		orbitDepthAdjust = _function;
		return this
	}

	_orbitLayout.orbitalRings = function() {
		//return an array of data corresponding to orbital rings
		if (!arguments.length) return orbitalRings;
		return this;
	}

	_orbitLayout.nodes = function(_data) {
    	if (!arguments.length) return flattenedNodes;
    	nestedNodes = _data;
    	calculateNodes();
		return this;
	}

	_orbitLayout.children = function(_function) {
    	if (!arguments.length) return childrenAccessor;
    	
    	//Probably should use d3.functor to turn a string into an object key
    	childrenAccessor = _function;
    	return this;


	}

    d3.rebind(_orbitLayout, orbitDispatch, "on");

	return _orbitLayout;
	function calculateNodes() {
	    orbitalRings = [];
			orbitNodes = nestedNodes;

			orbitNodes.x = orbitSize[0] / 2;
			orbitNodes.y = orbitSize[1] / 2;
			orbitNodes.ring = orbitSize[0] / 2;
			orbitNodes.depth = 0;

			flattenedNodes.push(orbitNodes);

			traverseNestedData(orbitNodes);

		function traverseNestedData(_node) {

			if(childrenAccessor(_node)) {
				var y = 0;
				var totalChildren = childrenAccessor(_node).length;
				var _rings = 0;
				var _total_positions = 0;
				var _p = 0;
				while (_total_positions < totalChildren) {
					if (fixedOrbitArray[_p]) {
						_total_positions += fixedOrbitArray[_p];
					}
					else {
						_total_positions += fixedOrbitArray[fixedOrbitArray.length - 1];						
					}
					_p++;
					_rings++;
				}

				while (y < totalChildren) {
					var _pos = 0;
					var _currentRing = 0;
					var _p = 0;
					var _total_positions = 0;

				while (_total_positions <= y) {
					if (fixedOrbitArray[_p]) {
						_total_positions += fixedOrbitArray[_p];
					}
					else {
						_total_positions += fixedOrbitArray[fixedOrbitArray.length-1];						
					}

						_p++;
						_currentRing++;
				}

				var ringSize = fixedOrbitArray[fixedOrbitArray.length-1];

				if (fixedOrbitArray[_currentRing-1]) {
					ringSize = fixedOrbitArray[_currentRing-1];
				}

					if (_node.parent) {
						var _ring = {source: _node, x: _node.x, y: _node.y, r: _node.parent.ring / orbitDepthAdjust(_node) * (_currentRing / _rings)};
					}
					else {
						var _ring = {source: _node, x: _node.x, y: _node.y, r: (orbitSize[0] / 2) * (_currentRing / _rings)};
					}


					var thisPie = d3.layout.pie().value(function(d) {return childrenAccessor(d) ? 4 : 1});
					var piedValues = thisPie(childrenAccessor(_node).filter(function(d,i) {return i >= y && i <= y+ringSize-1}));

					for (var x = y; x<y+ringSize && x<totalChildren;x++) {
						childrenAccessor(_node)[x].angle = ((piedValues[x - y].endAngle - piedValues[x - y].startAngle) / 2) + piedValues[x - y].startAngle;

						childrenAccessor(_node)[x].parent = _node;
						childrenAccessor(_node)[x].depth = _node.depth + 1;

						childrenAccessor(_node)[x].x = childrenAccessor(_node)[x].parent.x + ( (childrenAccessor(_node)[x].parent.ring / 2) * Math.sin( childrenAccessor(_node)[x].angle ) );
						childrenAccessor(_node)[x].y = childrenAccessor(_node)[x].parent.y + ( (childrenAccessor(_node)[x].parent.ring / 2) * Math.cos( childrenAccessor(_node)[x].angle ) );

						childrenAccessor(_node)[x].ring = _ring.r;

						flattenedNodes.push(childrenAccessor(_node)[x]);
						traverseNestedData(childrenAccessor(_node)[x]);
					}
					orbitalRings.push(_ring);
					y+=ringSize;
				}

			}
		}

	}

}