2013-10-05 15 views
6

Sto cercando di creare un rilevamento di collisione nel mio layout forzato svg (d3js). Ho seguito il tutorial this che crea una collisione di forma circolare.rilevamento collisione retta d3js

Per qualche motivo non funziona per la forma rettale. Ho provato a giocare con i parametri in un velo.

Ecco il mio codice:

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

e questo:

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

e la funzione di collisione:

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

Come posso rilevare la collisione per rect?

Grazie !!!

+0

Ho la stessa domanda, anche se forse un po 'più avanti del tuo esempio. Qualcosa non è giusto con le modifiche apportate alla funzione collide, "perché sto diventando troppa repulsione tra i rettangoli: http://bl.ocks.org/dobbs/1d353282475013f5c156 –

risposta

9

La funzione di collisione nell'esempio d3 calcola la sovrapposizione di cerchi confrontando la distanza tra i rispettivi centri l = Math.sqrt(x * x + y * y) con la somma dei loro raggi r = node.radius + quad.point.radius. Quando l < r i cerchi si sovrappongono e i due cerchi vengono allontanati l'uno dall'altro per correggere la sovrapposizione.

Una funzione collisione analoga per rettangoli funziona nello stesso modo, calcolando la sovrapposizione dei rettangoli e spostare ciascun allontanamento dall'altro:

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

La sovrapposizione di larghezza è dx = Math.min(node.x2 - quad.point.x, quad.point.x2 - node.x)/2; dove sovrapposizione in altezza è dy = Math.min(node.y2 - quad.point.y, quad.point.y2 - node.y)/2; che mostra che i tuoi nodi devono conoscere due angoli del rettangolo: in alto a sinistra (x, y) e in basso a destra (x2, y2).

Vedere un esempio completo qui: http://bl.ocks.org/dobbs/1d353282475013f5c156. L'esempio usa il coffeescript e sposta solo le rette l'una dall'altra lungo l'asse y, cos che meglio corrisponde a ciò di cui ho bisogno per il mio caso.

+0

Eccezionale, grazie mille. Stavo cercando qualcosa del genere. – damianmr

Problemi correlati