1
すべて、楕円のD3強制衝突検出
円と矩形のD3.js衝突検出の例はたくさんあります。
私は楕円ノードの強制的なシミュレーションをしようとしています。
私はもともと長方形のスニペットを試しましたが、完璧ではありません。
var width = 960,
height = 500,
minSize = 10,
maxSize = 30;
var n = 20,
m = 10;
var color = d3.scaleOrdinal(d3.schemeCategory10)
.domain(d3.range(m));
var nodes = d3.range(n).map(function() {
var c = Math.floor(Math.random() * m),
rx = Math.sqrt((c + 1)/m * -Math.log(Math.random())) * (maxSize - minSize) + minSize,
ry = Math.sqrt((c + 1)/m * -Math.log(Math.random())) * (maxSize - minSize) + minSize,
d = {color: c, rx: rx, ry: ry};
return d;
});
var collide = function(alpha) {
var quadtree = d3.quadtree()
.x((d) => d.x)
.y((d) => d.y)
.addAll(nodes);
nodes.forEach((d) => {
quadtree.visit((quad, x0, y0, x1, y1) => {
let updated = false;
if (quad.data && (quad.data !== d)) {
let x = d.x - quad.data.x,
y = d.y - quad.data.y,
xSpacing = (quad.data.rx + d.rx),
ySpacing = (quad.data.ry + d.ry),
absX = Math.abs(x),
absY = Math.abs(y),
l, lx, ly;
if (absX < xSpacing && absY < ySpacing) {
l = Math.sqrt(x * x + y * y);
lx = (absX - xSpacing)/l * alpha;
ly = (absY - ySpacing)/l * alpha;
if (Math.abs(lx) > Math.abs(ly)) {
lx = 0;
} else {
ly = 0;
}
d.x -= x *= lx;
d.y -= y *= ly;
quad.data.x += x;
quad.data.y += y;
updated = true;
}
}
return updated;
});
});
};
var force = d3.forceSimulation()
.nodes(nodes)
.force("center", d3.forceCenter())
.force("collide", (alpha) => collide(alpha))
.force("x", d3.forceX().strength(.01))
.force("y", d3.forceY().strength(.01))
.on("tick", tick);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append('g')
.attr('transform', 'translate(' + width/2 + ',' + height/2 + ')');
var ellipse = svg.selectAll("ellipse")
.data(nodes)
.enter().append("ellipse")
.attr("rx", function(d) { return d.rx; })
.attr("ry", function(d) { return d.ry; })
.style("fill", function(d) { return color(d.color); })
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
function tick() {
ellipse
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
function dragstarted(d) {
if (!d3.event.active) force.alphaTarget(0.3).restart();
d.x = d.x;
d.y = d.y;
}
function dragged(d) {
d.x = d3.event.x;
d.y = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) force.alphaTarget(0);
d.x = d3.event.x;
d.y = d3.event.y;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
は、ノード間の、あまりにも多くのギャップがあり、私は楕円の衝突検出で四角形として扱われるので、それは知っています。
これには良い解決策がありますか?
ありがとうございます。