Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I influence link distance in 3d-force-graph?

I am trying out the 3d Force Graph in this package and I am looking for ways to influence bond strength between nodes. Either link width or length would be good, but I don't see anything in API that allows me to control or influence either. What is the correct field of Graph to pass in link strenghts, one for each link?

like image 463
Brian Dolan Avatar asked Oct 17 '25 16:10

Brian Dolan


1 Answers

Here is a modified version of this example which applies a custom distance per link:

const N = 300;
const gData = {
  nodes: [...Array(N).keys()].map(i => ({ id: i })),
  links: [...Array(N).keys()]
    .filter(id => id)
    .map(id => {

      var distance = (Math.random() < 0.2) ? 75 : 250;
      var width = (distance == 75) ? 4 : 0.2;

      return ({
        source: id,
        target: Math.round(Math.random() * (id-1)),
        width: width,
        distance: distance
      })
    })
};

const Graph = ForceGraph3D()
  (document.getElementById('3d-graph'))
    .graphData(gData)
    .linkWidth('width')
    .cameraPosition({ z: 600 })
    .d3Force("link", d3.forceLink().distance(d => d.distance))
    .d3Force("charge", d3.forceManyBody().theta(0.5).strength(-1));
<head>
  <style> body { margin: 0; } </style>

  <script src="//unpkg.com/3d-force-graph"></script>
  <script src="https://d3js.org/d3.v4.min.js"></script>
</head>

<body>
  <div id="3d-graph"></div>
</body>

In fact, to allow users to modify links parameters, the library simply uses the d3 force API. The only difference is the name of the accessor in the 3d-force-graph library which is .d3Force() (instead of .force() in d3).

For instance, to modify the distance per link, we can add a distance attribute to each link data point (in addition to source and target) and then modify this distance as follow in the force layout (using the d3Force accessor):

.d3Force("link", d3.forceLink().distance(d => d.distance))

whereas in a d3 force layout we would have used:

.force("link", d3.forceLink().distance(d => d.distance))

which gives us:

const Graph = ForceGraph3D()
  (document.getElementById('3d-graph'))
    .graphData(gData)
    .linkWidth('width')
    // The link distance modification:
    .d3Force("link", d3.forceLink().distance(d => d.distance))
    // To make it prettier:
    .d3Force("charge", d3.forceManyBody().theta(0.5).strength(-1));

The strength can be adjusted the same way, using:

.d3Force("link", d3.forceLink().strength(d => d.strength))

In the example, I have given each link a distance which is randomly either 75 or 250. And to make it clear, I have given a bigger width to links with a smaller distance. The distribution of nodes in my demo is not perfect, and might need additional tuning.

like image 90
Xavier Guihot Avatar answered Oct 20 '25 06:10

Xavier Guihot



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!