Closed katossky closed 7 years ago
The most prominent example of topojson.neighbors
(the map coloring) uses this structure as a lookup table, something which is not easy to do with a list of links. (IOW, adjacency matrix vs adjacency list.)
It's a bit painful to switch from one representation to the other, in both directions. Here's my method (maybe not the best):
converting neighbors to links is relatively straightforward:
neighbors2links = (neighbors, objects) => d3.merge(
neighbors
.map((n,i) => n.map(j => j > i ? { source: objects[i], target: objects[j] } : null)
.filter(link => !!link))
);
to convert links to neighbors we need the nodes to have an index, or create it on the fly:
links2neighbors = (links, objects) => {
var neigh = [];
objects.forEach((d,i) => d.index = i); // create the index
links.forEach(d => {
neigh[d.source.index] = (neigh[d.source.index] || []).concat([d.target.index]);
neigh[d.target.index] = (neigh[d.target.index] || []).concat([d.source.index]);
});
return neigh.map((d,i) => neigh[i].sort());
}
both algorithms are linear (in O(V) and O(V+E)).
Maybe the question is not so much about changing topojson-client than wanting a d3-graph library.
Thanks for the suggestion. As @Fil suggests both representations can be useful in different contexts, so I don’t plan on changing from an adjacency matrix to an adjacency list. Though it might be neat to think about a more fleshed-out topology (or network) API…
Because I am working with both right now, I am wondering why links objects (from d3.force) and neighbors objects (from d3.geo) are structured differently, whereas they are substantially equivalent.
Since neighbors are, to my knowledge, not used directly in any subsequent functions, I would suggest to structure them as links objects.