d3/d3-force

Link force should not rewrite link index

Xemrox opened this issue · 1 comments

As seen here the link force rewrites the links index upon initialization.
Further down the road of the link force this has no apparent use.

d3-force/src/link.js

Lines 57 to 58 in 8d979ea

for (i = 0, count = new Array(n); i < m; ++i) {
link = links[i], link.index = i;

Same holds for the index/id function.

d3-force/src/link.js

Lines 4 to 5 in 8d979ea

function index(d) {
return d.index;

Why might this be a problem?
I do have a use-case where my force layout handles all links additionally as nodes.
Rewriting the index of links without a reason has an impact on all subsequent operations relying on the correct behavior and count of the internal index.
At the moment I have to fix the node/link index after applying the link force.

As an example my simulation has a force collide that relies on the node index.
All links are nodes which makes the force collide expect lets say 100 nodes/links.
Meanwhile the link force has rewritten the links index to a zero based index.
Which produces a node list with duplicated index definitions.
This interferes with the radius definition for nodes here:

d3-force/src/collide.js

Lines 75 to 77 in 8d979ea

var i, n = nodes.length, node;
radii = new Array(n);
for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes);

Overwriting existing radii.
E.g. nodes 0 to 50 were radius 10 until element 51 which is a link and has a rewritten index of 0 which overwrites the existing radius for node 0 to lets say 5.

This is the documented behavior and cannot be changed without a major release:

https://github.com/d3/d3-force/blob/master/README.md#link_links

Hence, in the current API you can’t use link objects as node objects, because the indexes will conflict; you must use different objects. Though you could have your node object point to the existing link object, and vice versa, if desired.