我如何找到邻居节点&所有选定节点的边缘? D3

时间:2014-12-18 12:39:25

标签: javascript algorithm d3.js nearest-neighbor

我有一个力导向图,能够双击一个节点,只显示该节点及其邻居,其余的给出一个隐藏的类 - >可视性:隐藏

但这仅适用于一个节点。我可以选择多个节点并为它们提供一个selectedNode类。

现在我希望发生的是在具有selectedNode类的所有节点上使用此邻近算法。这样所有选定的节点和连接它们的边缘仍然显示,未选择的节点和边缘将被隐藏。

以下是我如何显示/隐藏边缘。同样,这仅适用于一个节点d3.select(this).node().__data__;。我试过d = d3.selectAll("selectedNode").data();但没有运气:(

var linkedByIndex = {};//Create an array logging what is connected to what

for (i = 0; i < graph.data.nodes.length; i++) //-populate the array
{
    linkedByIndex[i + "," + i] = 1;
};


graph.data.edges.forEach(function (d) //-checks what nodes are related in array
{
    linkedByIndex[d.source.index + "," + d.target.index] = 1;
});


//-------------------------check if nodes are linked
function neighboring(a, b) //This function looks up whether a pair are neighbours
{
    return linkedByIndex[a.index + "," + b.index];
}

d = d3.select(this).node().__data__;


links.classed("hidden", function (o) {
            return d.index==o.source.index | d.index==o.target.index ? false : true;
        });

添加了代码

var links = inner.selectAll(".link").append("g")
    .data(force.links())
    .enter().append("line")
    .attr("id", "links")
    .attr("class", "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; })
    .style("marker-end",  "url(#arrow)") //adds arrows, main code on SVG append towards bottom
    .style("stroke-width", lineWidth)   
    ;

1 个答案:

答案 0 :(得分:0)

我认为这里存在两个问题,因为你缺乏细节我会做出假设。

1)您有一种方法来检查两个节点是否是邻居。这是一个良好的开端,但这还不够,您还需要一种方法来告诉您任何给定节点是选定节点还是其中一个邻居。假设您正在维护数组selected中所选节点的列表,这是一个天真的实现中这样的函数的样子:

function shouldBeVisible(nodeIndex){
    // visible if either selected itself or neighbour of a selected node
    return selected.some(function(d){
        // assuming you don't care about the direction of your edges
        return linkedByIndex[nodeIndex+','+d]+linkedByIndex[d+','+nodeIndex];
    });
}

您甚至可以重载此方法以使其“边缘友好”:

function shouldBeVisible(sourceIndex, targetIndex){
    if (targetIndex !== undefined)
        return shouldBeVisible(sourceIndex)
            && shouldBeVisible(targetIndex);
    else return selected.some(function(d){
        return linkedByIndex[sourceIndex+','+d]
             + linkedByIndex[d+','+sourceIndex];
    });
}

请注意,如果您未在数据结构中维护选定的节点,则应该能够使用d3.selectAll('.selectedNode')轻松检索它们。您可能希望为边缘实现类似的方法。

2)您只是针对first node in the selection而不是all nodes in the selection检查邻域。无论哪种方式,你都不应该费心去做,假设links准确地描述了它的含义。

尝试这样的事情:

links.classed("hidden", function(d) {
    return !shouldBeVisible(d.source.index, d.target.index);
});