2013-10-30 53 views
0

我期待開發一個由節點鏈接圖組成的viz。我有一系列點的位置,除非圖上有碰撞(另一個點),否則我不想改變它們的位置。在發生碰撞的節點的情況下,我想將它們間隔開,以便它們不重疊。我的JS代碼如下D3力圖 - 不重疊的固定節點

var chartWidth = 200; 
var chartHeight = 200; 
var widthPadding = 40; 
var heightPadding = 40; 

var link, node; 

$(function(){ 
    initialize(); 
}); 


function initialize() { 
    var jsonString = '{"nodes":[{"x":40,"y":64,"r":6,"fixed":true},{"x":40,"y":63,"r":6,"fixed":true},{"x":119,"y":53,"r":6,"fixed":true},{"x":119,"y":73,"r":6,"fixed":true},{"x":137,"y":73,"r":6,"fixed":true},{"x":140,"y":140,"r":6,"fixed":true},{"x":68,"y":57,"r":6,"fixed":true},{"x":70,"y":75,"r":6,"fixed":true},{"x":51,"y":59,"r":6,"fixed":true},{"x":51,"y":54,"r":6,"fixed":true},{"x":137,"y":40,"r":6,"fixed":true}],"links":[{"source":0,"target":1},{"source":1,"target":2},{"source":2,"target":3},{"source":3,"target":4},{"source":4,"target":5},{"source":0,"target":1},{"source":1,"target":6},{"source":6,"target":7},{"source":7,"target":4},{"source":4,"target":5},{"source":0,"target":1},{"source":1,"target":8},{"source":8,"target":9},{"source":9,"target":10},{"source":10,"target":5}]}'; 
    drawForceDirectedNodeLink($.parseJSON(jsonString)); 
} 


function drawForceDirectedNodeLink(graph){ 
var width = chartWidth + (2*widthPadding); 
var height = chartHeight + (2*heightPadding); 

var q = d3.geom.quadtree(graph.nodes), 
    i = 0, 
    n = graph.nodes.length; 

while (++i < n) { 
    q.visit(collide(graph.nodes[i])); 
} 

var force = d3.layout.force() 
    .size([width, height]) 
    .gravity(0.05) 
    .on("tick", function(){ 
     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("cx", function(d) { return d.x; }) 
      .attr("cy", function(d) { return d.y; }) 
      .attr("r", function(d) { return d.r; }); 
    }); 

var svg = d3.select("body").append("svg") 
    .attr("width", width) 
    .attr("height", height); 

var link = svg.selectAll(".link"), 
    node = svg.selectAll(".node"); 

force 
    .nodes(graph.nodes) 
    .links(graph.links) 
    .start(); 

link = link.data(graph.links) 
    .enter().append("line") 
    .attr("class", "link"); 

node = node.data(graph.nodes) 
    .enter().append("circle") 
    .attr("class", "node"); 
} 


function collide(node) { 
    var r = node.radius + 16, 
     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 = node.radius + 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; 
    }; 
} 

正如你所看到的,我試圖實現碰撞檢測邏輯提到here。但是,有些我沒有能夠得到那部分工作。

Also attaching the output that I've managed until now

回答

2

請注意,在initialize()jsonString聲明中,每個節點都將被賦予r屬性。然而,再往下collide()內,你做以下幾點:

.attr("r", function(d) { return d.radius - 2; }) 

確保您的節點有一個radius屬性附加到他們。如果沒有,下面的變化應該這樣做:

.attr("r", function(d) { return d.r - 2; }) 

你可以在他的節點最初與radius財產申報,而不是你的財產r邁克·博斯托克的腳本的第30行看到的。

var nodes = d3.range(200).map(function() { return {radius: Math.random() * 12 + 4}; }), 
+0

謝謝! @Walter。 –

1

UPDATE

變化node.radiusnode.rquad.point.radiusquad.point.r。它應該工作。看起來這只是一個NaN的問題。

+0

我早就試過了。沒有工作。另外,因爲我所有的節點都需要強制地固定在它們的位置上(除非發生碰撞),所以我認爲最好在繪製之前計算一次碰撞。 –

+0

哎呀,你想要所有的節點都有'fixed:true',除非有碰撞?我想你可能會遇到一個問題,因爲當你移動node1以防止與node2發生衝突時,最終會與node3發生新的碰撞(因此爲什麼很多圖形佈局是迭代的)。 – redmallard

+0

好吧,看起來像@沃爾特4秒鐘打敗了我的拳頭;) – redmallard