2013-10-05 18 views
6

Ich versuche eine Kollisionserkennung in meinem erzwungenen Layout svg (d3js) zu erstellen. Ich habe this Tutorial gefolgt, die eine Kreisform Kollision macht.rect Kollisionserkennung d3js

Aus irgendeinem Grund funktioniert es nicht für die rect Form. Ich habe versucht, mit den Parametern in einem Schleier zu spielen.

Hier ist mein Code:

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); 

und diese:

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 + ")"; 
    }); 
}); 

und die Kollisionsfunktion:

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; 
    }; 
} 

Wie kann ich die Kollision für rect erkennen?

Danke !!!

+0

Ich habe die gleiche Frage, obwohl vielleicht ein wenig weiter als Ihr Beispiel. Etwas stimmt nicht mit den Änderungen, die ich an der Kollisionsfunktion gemacht habe, weil ich zu viel Abstoßung zwischen Rechtecken bekomme: http://bl.ocks.org/dobbs/1d353282475013f5c156 –

Antwort

9

Die Kollisionsfunktion im Beispiel d3 berechnet die Überlappung von Kreisen durch Vergleichen des Abstandes zwischen ihren Zentren l = Math.sqrt(x * x + y * y) mit der Summe ihrer Radien r = node.radius + quad.point.radius. Bei l < r überlappen sich die Kreise und die beiden Kreise werden voneinander weg bewegt, um die Überlappung zu korrigieren.

Eine ähnliche Kollisionsfunktion für Rechtecken, arbeitet in der gleichen Art und Weise, durch die Überlappung der Rechtecke Rechen- und jede weg von den anderen beweglichen:

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; 
    }; 
}; 

Die Überlappung in der Breite ist dx = Math.min(node.x2 - quad.point.x, quad.point.x2 - node.x)/2; wo Überlappung in Höhe dy = Math.min(node.y2 - quad.point.y, quad.point.y2 - node.y)/2; ist was zeigt, dass Ihre Knoten zwei Ecken der rect kennen müssen: oben links (x, y) und unten rechts (x2, y2).

Siehe ein vollständiges Beispiel hier: http://bl.ocks.org/dobbs/1d353282475013f5c156. Das Beispiel verwendet coffeescript und verschiebt die Dekore nur entlang der y-Achse voneinander, da dies besser mit dem übereinstimmt, was ich für meinen eigenen Fall benötige.

+0

Hervorragend, vielen Dank. Ich war auf der Suche nach so etwas. – damianmr