2013-07-29 3 views
12

В этом примере: http://bl.ocks.org/mbostock/1747543:Избегайте столкновений между узлами и ребрами в D3 силы макете

enter image description here

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

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

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

enter image description here

+2

Это невозможно при реализации компоновки силовых установок в D3. Вам нужно будет реализовать это самостоятельно. Обратите внимание, что на самом деле это очень сложная проблема (вычислительно), поэтому, даже если у вас была реализация, она, вероятно, не захочет запускать ее в браузере. –

+0

@ LarsKotthoff, вы говорите, в общем, ни один известный алгоритм построения графа (в том числе реализованный для D3) не может эффективно решить эту проблему? – skyork

+0

Это зависит от вашего определения. Найти (статическое) решение для этого звучит как минимум NP-сложно для меня. Это не значит, что его можно быстро решить в конкретных случаях, но в целом это сложно (и для больших графиков вы, вероятно, не можете сделать это быстро). Чтобы затем изменить это начальное решение таким образом, чтобы узлы двигались незначительно (по мере того, как будет выполняться симуляция), это будет очень просто, поскольку вам нужно только выполнить локальный ремонт. –

ответ

6

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

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.

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