{
const img_width = 600;
const height = 300;
let ranges = {x: [-100, 100], y: [-50, 50]};
let graph = createStandardGrid(ranges.x, ranges.y);
let nodes = [
{
x: -5, y: -5,
m: 1000,
vx: 0, vy: 0
}
];
graph.svg.append('circle')
.attr('r', 4)
.attr('cx', graph.x(nodes[0].x))
.attr('cy', graph.y(nodes[0].y))
.attr('fill', 'gray');
const F = gravityField(nodes, 1);
let s0 = makeStateVec(nodes);
const makeGrid = () => {
const q = pixelsPerSample;
const x0 = -q / 2, x1 = img_width + q;
const y0 = -q / 2, y1 = height + q;
const n = Math.ceil((x1 - x0) / q);
const m = Math.ceil((y1 - y0) / q);
const grid = new Array(n * m);
let pts = [];
for (let j = 0; j < m; ++j) {
for (let i = 0; i < n; ++i) {
let pt = [graph.x.invert(i*q + x0), graph.y.invert(j*q + y0)];
pts.push(pt);
let gvr = F(graph.x.invert(i*q + x0), graph.y.invert(j*q + y0), s0);
grid[j * n + i] = Math.sqrt(gvr.xpp**2 + gvr.ypp**2);
}
}
grid.x = -q;
grid.y = -q;
grid.k = q;
grid.n = n;
grid.m = m;
return [grid, pts];
}
const [grid, pts] = makeGrid();
let geoTrans = d3.geoTransform({
point: function(x, y) {
this.stream.point(grid.x + grid.k*x, grid.y + grid.k*y);
}
});
const contours = d3.contours()
.size([grid.n, grid.m])
.thresholds(thresh2)
(grid)
pts.map(([x, y]) => {
graph.svg.append('circle')
.attr('r', 1.5)
.attr('cx', graph.x(x))
.attr('cy', graph.y(y))
.attr('fill', 'lightgray');
});
graph.svg.append("g")
.attr("fill", "none")
.attr("stroke", "#000")
.attr("stroke-opacity", 0.5)
.selectAll("path")
.data(contours)
.join("path")
.attr("d", d3.geoPath(geoTrans));
return graph.svg.node();
}