score:2

I am definitely not sure if I understand your question, but if you are trying to position circles along a curve, I would suggest...

1. write the equation for the curve you want
2. convert that curve to a parametric equation
3. use the x equation for cx, use y equation for cy

The parametric equation will get you a single row. For each additional row you'll want to factor in an additional offset for all cy's in that row.

Here is a very rough example for you to build off of...

``````const p_circle = {
x(t){ return 100*Math.cos((t+10)/10)+150 },
y(t){ return 100*Math.sin((t+10)/10)-80 }
}

const p_parab = {
x(t){ return -(10*t-5)+100 },
y(t){ return -(t-5)*(t-5)+20 }
}

let t = Array.prototype.concat(
Array.from(Array(10).keys()).map(d=>[d,1]), //row 1
Array.from(Array(10).keys()).map(d=>[d,2]), //row 2
Array.from(Array(10).keys()).map(d=>[d,3])  //row 3
)

const p_parab_2 = {
x(t){ return (10*t-5)+100 }, // removing "-" so that first seat is on left, not right
y(t){ return -(t-5)*(t-5)+20 }
}

// adding 11th seat to center around seat 5 (seat in the center)
let t2 = Array.prototype.concat(
Array.from(Array(11).keys()).map(d=>[d,1]), //row 1
Array.from(Array(11).keys()).map(d=>[d,2]), //row 2
Array.from(Array(11).keys()).map(d=>[d,3])  //row 3
)

console.log(t)

d3.select("svg").selectAll(".circ")
.data(t)
.enter()
.append("circle")
.attr("class", "circ")
.attr("r",5)
.attr("fill","red")
.attr("cx", (d) => p_circle.x(d[0]))
.attr("cy", (d) => p_circle.y(d[0]) + 15*d[1])

d3.select("svg").selectAll(".parab2")
.data(t2)
.enter()
.append("circle")
.attr("class", "parab2")
.attr("r",7)
.attr("fill","blue")
.attr("cx", (d) => p_parab.x(d[0]))
.attr("cy", (d) => p_parab.y(d[0]) + 15*d[1])

d3.select("svg").selectAll(".parab")
.data(t)
.enter()
.append("circle")
.attr("class", "parab")
.attr("r",5)
.attr("fill","green")
.attr("cx", (d) => p_parab.x(d[0]))
.attr("cy", (d) => p_parab.y(d[0]) + 15*d[1])``````
``````<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

<svg height="250" width="250"></svg>``````

score:2

I like @steveladavich's answer but I'll propose an alternate. You can use `d3`'s ability to curve fit to points and then place the circles on the resulting path:

``````var r = 10,
points = [];
for (var i = 0; i < 10; i++) {
points.push({
x: (500 / 10) * i,
y: Math.random() * 500
});
}

var line = d3.line()
.x(function(d) {
return d.x;
})
.y(function(d) {
return d.y;
})
.curve(d3.curveCardinal);

var svg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 500);

var path = svg.append("g")
.datum(points)
.append("path")
.attr("d", line)
.style("fill", "none")
.style("stroke", "none")
.node();

var pathLength = path.getTotalLength();
svg.append("g")
.selectAll("circle")
.data(d3.range(0, pathLength, r))
.enter()
.append("circle")
.attr("transform", function(d) {
var p = path.getPointAtLength(d);
return "translate(" + p.x + "," + p.y + ")";
})
.attr("r", r / 2)
.style("fill", "steelblue");``````
``<script src="http://d3js.org/d3.v4.js"></script>``