【问题标题】:D3 repulsive forces on certain nodesD3 某些节点上的排斥力
【发布时间】:2020-08-29 22:24:03
【问题描述】:

我想在 3D 中制作强制导向布局。

图是连通的,所以每个节点至少有一条边到另一个节点。

特别是我将我的图表分成不同的集合。 假设 A 和 B 是不相交的集合,那么我想在每个节点之间添加排斥力。

所以A中的每个节点都应该对B中的每个节点都有排斥力。

有没有办法应用这些力量?我只找到了直接的方法 确定节点的 x 和 y 位置或通过链接施加力,但在这种情况下 可能 A 和 B 中的一些节点没有通过边连接,但仍然应该相互排斥。

提前谢谢你。

作为解决方案的伪代码,我想像这样:

lrepulsion = list of links
for a in componentA
    for b in componentB
        lrepulsion.add(source: a, target: b);

simulation.force("repulsion", d3.forceLink().id(function (d) {
                return d.id;
}));

simulation.force("repulsion").distance(function(d) { return -d.value; });
simulation.force("repulsion").links(lrepulsion);
simulation.alpha(1).restart();

a 和 b 包含有关用于绘制图形的图形节点的信息(如 id 等)。

我有以下代码(但力量仍然相互吸引而不是相互推开):

simulation
    .force("repulsion", d3.forceLink().id(function (d) {
        return d.id;
    }));
simulation.force("repulsion").distance(function(d) {
    return -d.value;
});

simulation.force("repulsion").strength(0.1);
let listofrepulsions = [];
for(let k = 0; k < bars.length; k++)
{
    if(!bars[k].selected)
    {
        continue;
    }
    let index = 0;
    for(let i = 0; i < bars[k].componentA.length; i++) {
        for(let j = 0; j < bars[k].componentB.length; j++) {
            let link = {};
            link.target = bars[k].componentB[j];
            link.source = bars[k].componentA[i];
            link.id = index;
            link.value = 2;
            index = index + 1;
            listofrepulsions.push(link);
        }
    }
}

console.log(listofrepulsions);

simulation.force("repulsion")
    .links(listofrepulsions);
simulation.alpha(1).restart();

bars 包含所有应该相互排斥的簇对。

最好我想在两个节点之间添加排斥而不在它们之间添加链接,但是这种排斥也不应该影响其他节点。

【问题讨论】:

  • 澄清一下,您是否正在寻找一种布局,其中所有 a 的集群和所有 b 的集群都在一起,而不管链接如何?
  • 一般来说,图是连通的(所以只有一个连通分量)。它应该具有弱力居中和使所有节点相互排斥的弱力。然后通过选择 2 个不相交的集群,我希望这些集群中的节点相互排斥(向所有节点增加力)。这能回答问题吗?
  • This 可能有用 - 它也使用 voronoi 背景,但如果没有它,听起来就像你所追求的那样。
  • 谢谢,但是也可能出现a和b(来自集群A和B)没有连接的情况,有没有办法直接对这两个节点施加力?
  • 您能否分享一个代码示例,我们可以根据它提出建议的解决方案?

标签: javascript d3.js


【解决方案1】:

我找到了一种方法:

// data.nodes contains all nodes
for(let i = 0; i < data.nodes.length - 1; i++)
{
    for(let j = i + 1; j < data.nodes.length; j++)
    {
        simulation.force(data.nodes[i].id.concat(data.nodes[j].id), isolate(d3.forceManyBodyReuse().strength(-30), data.nodes[i], data.nodes[j]));
    }
}

function isolate(force, nodeA, nodeB) {
    let initialize = force.initialize;
    force.initialize = function() { initialize.call(force, [nodeA, nodeB]); };
    return force;
}

对于每对节点,我可以创建自己的斥力,以后可以对其进行操作,因为我可以通过使用 id 组合作为名称来访问斥力。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 2012-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多