2013-10-05 78 views
6

我試圖在我的svg強制佈局(d3js)中創建碰撞檢測。 我跟着this教程做了一個圓形碰撞。rect碰撞檢測d3js

由於某種原因,它不適用於矩形形狀。我曾嘗試在面紗中使用參數。

這裏是我的代碼:

var node = svg.selectAll(".node") 
    .data(json.nodes) 
     .enter().append("g") 
     .attr("class", "node") 
     .call(force.drag); 

    node 
     .append("rect") 
      .attr("class", "tagHolder") 
      .attr("width", 60) 
      .attr("height", 60) 
      .attr("rx", 5) 
      .attr("ry", 5) 
      .attr("x", -10) 
      .attr("y", -10); 

這:

svg.selectAll(".node") 
     .attr("x", function(d) { return d.x; }) 
     .attr("y", function(d) { return d.y; }); 

    link.attr("x1", function(d) 
     { 
      return d.source.x; 
     }) 
      .attr("y1", function(d) { return d.source.y; }) 
      .attr("x2", function(d) { return d.target.x; }) 
      .attr("y2", function(d) { return d.target.y; }); 

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

和碰撞功能:

function collide(node) { 
    var r = 30, 
     nx1 = node.x - r, 
     nx2 = node.x + r, 
     ny1 = node.y - r, 
     ny2 = node.y + r; 

    return function(quad, x1, y1, x2, y2) 
    { 
     if (quad.point && (quad.point !== node)) 
     { 
      var x = node.x - quad.point.x, 
       y = node.y - quad.point.y, 
       l = Math.sqrt(x * x + y * y), 
       r = 30 + quad.point.radius; 
      if (l < r) 
      { 
       l = (l - r)/l * .5; 
       node.x -= x *= l; 
       node.y -= y *= l; 
       quad.point.x += x; 
       quad.point.y += y; 
      } 
     } 

     return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1; 
    }; 
} 

如何檢測爲矩形的碰撞?

謝謝!

+0

我有同樣的問題,雖然也許比你的例子稍微有一點點。有些東西與我對碰撞函數所做的更改不正確,'因爲我在矩形之間得到了太多的斥力:http://bl.ocks.org/dobbs/1d353282475013f5c156 –

回答

9

d3示例中的碰撞函數通過比較其中心l = Math.sqrt(x * x + y * y)與它們的半徑之和r = node.radius + quad.point.radius之和的距離來計算圓的重疊。當l < r圓圈重疊並且兩個圓圈彼此遠離以糾正重疊時。

爲矩形的類似衝突功能中相同的方式工作,通過計算矩形的重疊和來自其它各移動遠離:

function collide(node) { 
    var nx1, nx2, ny1, ny2, padding; 
    padding = 32; 
    nx1 = node.x - padding; 
    nx2 = node.x2 + padding; 
    ny1 = node.y - padding; 
    ny2 = node.y2 + padding; 
    return function(quad, x1, y1, x2, y2) { 
    var dx, dy; 
    if (quad.point && (quad.point !== node)) { 
     if (overlap(node, quad.point)) { 
     dx = Math.min(node.x2 - quad.point.x, quad.point.x2 - node.x)/2; 
     node.x -= dx; 
     quad.point.x += dx; 
     dy = Math.min(node.y2 - quad.point.y, quad.point.y2 - node.y)/2; 
     node.y -= dy; 
     quad.point.y += dy; 
     } 
    } 
    return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1; 
    }; 
}; 

在寬度的重疊是dx = Math.min(node.x2 - quad.point.x, quad.point.x2 - node.x)/2;其中高度重疊dy = Math.min(node.y2 - quad.point.y, quad.point.y2 - node.y)/2;這表明你的節點必須知道矩形的兩個角落:左上角(x, y)和右下角(x2, y2)

查看完整的示例:http://bl.ocks.org/dobbs/1d353282475013f5c156。這個例子使用了coffeescript,並且只沿着y軸'cos將對方相互移開,這更好地匹配了我自己的情況。

+0

非常好,非常感謝。我正在尋找這樣的東西。 – damianmr