d3/d3-force

Description of the json format representing a GRAPH

ShiinaMitsuki opened this issue · 2 comments

Sorry for bothering, but could any body tells me where can I find the DESCRIPTION about the json format which representing a graph?

{
  "nodes": [
    {"id": "Myriel", "group": 1},
    {"id": "Napoleon", "group": 1},
    {"id": "Mlle.Baptistine", "group": 1},
    {"id": "Mme.Magloire", "group": 1},
],
"links": [
    {"source": "Napoleon", "target": "Myriel", "value": 1},
    {"source": "Mlle.Baptistine", "target": "Myriel", "value": 8},
    {"source": "Mme.Magloire", "target": "Myriel", "value": 10},
    {"source": "Mme.Magloire", "target": "Mlle.Baptistine", "value": 6},
]
}

eg:

  1. How many keys do we have?
  2. whtat is "value" for and "group"?
  3. How to add some properties to the "node" and "link"?
    .etc

Thanks in advance!!

Keys are just strings and you can have as many as fit in memory
Value is probably for weights or coloring. You can do whatever you want, link value is not mission critical
To add properties if you need to modify the svg elements use css classes or .attr, and .classed is cool for conditional classes to make things different colors. To modify the json in your example case, we have arrays so you must loop through the array, find the node in question by key:value, and then update the node, and replace it in the selection. Pretty craptastic and slow especially in React with 1 way data flow, or if you're doing immutable objects, you've got to copy everything every refresh, which is somewhat moronic.

I find it more performant to assign a uuidv4 to each node and link, and to make these a map. You can pass Object.values(nodes) to get the nodes array for simulation.nodes etc, but if we treat nodes and links as maps instead of arrays, some things become much faster O(1) lookup of specific nodes by their id. This means we can update, delete, select, deselect much faster. I'm not sure if this will scale but it might be possible to give nodes and links pointers to other nodes and links with the json, so then we can traverse the json like const result = node({ label: "bionicles" }).links({ type: "engineered" }).map(link => link.target).filter({ type: "software" }) -- basically, if we intend to use d3 to RENDER graphs, we need to actually USE graphs ... that means traversals on the front end (somehow)

However, even with objects instead of arrays of "nodes" and "links" there's no good traversal solution so we have to make one; probably a class which can filter walks and returns self. The definition of "graph" is "index-free adjacency" and thus, D3 Force Graphs are not actually graphs, as long as we must loop through arrays to do traversals, it does not scale.

Also the bounding box calculation must be incorporated in the tick actions which is super slow, it could probably be some kind of event listener which only calculates for certain nodes if those nodes are near the edges, so there is probably a big opportunity to accelerate constraints so nodes stay within a rectangle without a O(N) calculation every tick. Could be nice to run multiple "ticks" per constraint calculation, then schedule an animation.

If you want to look at nodes and links, just "inspect" in chrome and click on a node or link in the svg. D3 binds data to the svg so it will show the xy coords, etc etc

if we want a really legit graph software, we can use d3 for some aspects, but the lack of traversals, being forced to use arrays, and the hackerish constraint-by-tick are limiting. Good idea is to make your own graph first, then hook that up to d3 for visualization. D3 is not a graph database, but it does crush a number of forces well

hey @mbostock how do you think we should engineer graph traversals and improve constraint calculations for d3.force?

There isn’t a set JSON format; the behavior is controlled by the data structures and accessor functions you pass to d3.forceSimulation and d3.forceLink. Specifically see link.id for examples.