2017-12-20 6 views
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>

노드 사이에 너무 많은 차이가있다, 나는 타원은 충돌 감지에 사각형으로 처리되어 있기 때문에 알고있다.

누구에게 좋은 솔루션이 있습니까?

미리 감사드립니다.

답변

0

나는 이것을 스스로 알아 냈습니다.

다음은 d3에 대한 충돌 감지 라이브러리입니다.

ellipse-collision-detection

나는 위의 저장소에 예를 들어 작업을 첨부했습니다.

감사합니다.