Избегайте столкновения узлов и ребер в компоновке силы D3

В этом примере: http://bl.ocks.org/mbostock/1747543:

enter image description here

... Майк показывает нам, как избежать столкновения между узлами, чтобы ни один из двух узлов не перекрывал друг друга.

Интересно, можно ли избежать столкновения между узлами и ребрами, чтобы no node "клипы" или перекрывали ребро, если он не связан этим ребром.

В следующем примере с использованием D3 force-direct показано, что node L перекрывается с ребрами, соединяющими I и A, и аналогичным образом node M перекрывается с ребром, соединяющим L и D. Как предотвратить такие случаи?

enter image description here

Ответ 1

Если на вашем графике не слишком много узлов, вы можете подделать его. Просто вставьте один или несколько узлов для каждой ссылки и установите их положение по ссылке в обработчике tick. Посмотрите http://bl.ocks.org/couchand/7190660 на пример, но изменения в версии Mike Bostock в основном сводятся к следующему:

var linkNodes = [];

graph.links.forEach(function(link) {
  linkNodes.push({
    source: graph.nodes[link.source],
    target: graph.nodes[link.target]
  });
});

и

// force.on('tick', function() {
linkNodes.forEach(function(node) {
  node.x = (node.source.x + node.target.x) * 0.5;
  node.y = (node.source.y + node.target.y) * 0.5;
});

Это приведет к довольно серьезным издержкам производительности, если у вас очень много узлов и ребер, но если ваш график не будет намного больше вашего примера, это вряд ли будет замечено.

Вы также можете играть с относительной силой реальных узлов по сравнению с узлами связи.

Сделайте еще один шаг вперед, и вы получите хорошие изогнутые ссылки http://bl.ocks.org/mbostock/4600693.