2013-10-05 4 views
6

Я пытаюсь создать обнаружение столкновения в моей принудительной компоновке svg (d3js). Я следовал за this учебным пособием, который вызывает столкновение вокруг круга.Прямое обнаружение столкновений 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, потому что лучше соответствует тому, что мне нужно для моего собственного дела.

+0

Отлично, спасибо. Я искал что-то вроде этого. – damianmr

Смежные вопросы