Leverage D3 force simulation as a functional programming tool

Currently, I am utilizing d3-force for collision detection in my project:

function customLayout(nodesWithCoordinates) {
  const simulation = forceSimulation(nodesWithCoordinates)
    .force('collide', forceCollide(4.5))
    .stop()
    .tick(300)

  return simulation.nodes()
}

I prefer not to have the graph animated so that I can retrieve the final state of the nodes after 300 ticks.

Would it be feasible to rerun the simulation (using the same nodesWithCoordinates) and obtain identical results? This would enhance its compatibility with React.

Is this achievable by adjusting iteration count or modifying alpha and decay values?

Answer №1

A few weeks ago, I came across a post by Mike Bostock in 2016 that discussed the use of phyllotaxis to achieve deterministic results in d3-force initialization. This method ensures consistency across reloads and various browsers. More information here

If I set the initial values for x and y as NaN, I am able to achieve deterministic outcomes. You can find some explanation on this here: Visit this link for more details

const nodes = d3.range(5).map(() => ({
    // use NaN to make deterministic
    x: NaN,
    y: NaN
}));
const simulation = d3.forceSimulation(nodes)
    .force("collide", d3.forceCollide(10))
    .stop()
    .tick(300)
console.log(nodes.map(d => d.x))
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

This shows that achieving deterministic results is possible when initial positions are not needed.

Answer №2

To put it simply: a D3 force simulation cannot and should not be treated as a pure function (meaning a function that consistently returns the same values for the same inputs).

The rationale behind this is that a simulation, much like a physical system, progresses in a chaotic manner, heavily influenced by the initial interactions that took place. By its very essence, a D3 force simulation is regarded as nondeterministic.

This can be easily exemplified with a basic simulation:

const nodes = d3.range(5).map(() => ({
  x: 100,
  y: 100
}));
const simulation = d3.forceSimulation(nodes)
  .force("collide", d3.forceCollide(10))
  .stop()
  .tick(300)
console.log(nodes.map(d => d.x))
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

If we execute that snippet multiple times, we will observe varying outcomes. For instance, the x coordinates of the nodes may differ:

1st time: [120.1198, 110.0542, 100.2805, 89.5732, 79.972]

2nd time: [67.6898, 83.854, 99.5493, 116.7441, 132.1625]

3rd time: [133.1773, 116.5792, 100.4626, 82.8064, 66.9742]

etc...

You can verify this yourself by clicking the Run code snippet button repeatedly.

In light of this, if you anticipate a D3 force simulation to function akin to a pure function, you are employing an unsuitable approach for the task at hand.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

using Angular and RxJS to filter out an element from an array

One of the functions in my service is a delete function. This function calls an API that returns either true or false. If the response is true, I then proceed to find the index of the item in my array, splice it out, and return the updated array. Here&apos ...

Tips for displaying or concealing data in table cells in Google Charts

Using a Google charts table to display server exceptions, but the errors are too long for cells. How can I show only an excerpt of error messages in each cell with a + expansion sign for full details in a modal box on click? I have successfully implement ...

Execute an AJAX post request to the identical PHP page (utilizing the Jquery Form Plugin)

I am in the process of developing a new web interface using JavaTMP, an AJAX-based admin template. After spending time understanding its functionality, I have created a page with a form to allow users to create projects within my software. Typically, creat ...

Remove an item from a complex JSON structure based on the specified name. The function will then return the

Hey there, I'm just starting out with react native and I have an array of objects. My goal is to remove an inner object from this JSON data. [ { Key: 1, exchnageArr: [ { name: ”FX” }, { name: ”MK” ...

What is the best way to save the response data into an array outside of the current function in Node.js?

How can I efficiently store all the result data into an array called pImages? I am able to retrieve the results, but I believe using an async function would be more suitable. However, I am unsure of how to implement it. Any assistance would be greatly appr ...

Tips for submitting multiple radio button values in a tabular format

HTML Code: <div class="tab"><h4>Zip Code</h4> <p><input type="text" class="text1" placeholder="Enter zip code..." oninput="this.className = ''" name="zipcode"></p> </div> <div class="tab">& ...

Capture the onclick attribute with jQuery and then reapply it

I am facing a challenge with a page that has several calendars composed of HTML tables where each day is represented by a td. The td elements have an onClick attribute which I need to manipulate using jQuery. Specifically, I need to remove the onClick attr ...

How to apply class binding within a v-for loop in Vue.js

When using Vuejs3, I am currently iterating through an array of objects: <div v-for="ligne in lignes" :key="ligne.id" :class="{ 'border-b-2':isSelected }" :id="`ligne_${ligne.id}`" > ...

What takes precedence in npm scripts - local dependencies or global ones?

When using npm scripts, the ./node_modules/.bin path is automatically added to your PATH. This means that by simply running npm test with the provided package.json, npm will utilize the local version of mocha located in ./node_modules/.bin. "scripts": { ...

transferring iterative information via ajax data flow

My form includes hidden input fields that are manually declared in the AJAX data without a loop. How can I efficiently loop through them in the AJAX data? Below is my form script: <form method="POST" name="myform"> <?php for($i=1;$i<=5;$i+ ...

Connecting to a MongoDB or Mongoose database dynamically using Node.js

I am currently working on developing a multi-tenant application where each client will have its own dedicated database. Here is my scenario: I have created a middleware that identifies the client based on their subdomain and retrieves the necessary datab ...

Unable to install npm package from git source

I am attempting to install a package from a git repository that I had previously forked. Here is the command I tried: npm i catsaredoomed/invest-openapi-js-sdk --save-dev Unfortunately, I encountered this error message: npm ERR! prepareGitDep 2> npm W ...

What is the best approach for adding variable rows to a Postgres junction table: should you concatenate a query string, utilize multiple queries, or explore alternative methods

Below is the code snippet for handling a variable-length list of tags and inserting data into the database: // JSON object from req.body { "title": "title", "reference": "1213", "noteType": &q ...

Laravel is unable to interpret formData

I've been on a quest to find answers, but so far I'm coming up empty. I'm trying to send file input to a Laravel controller via Ajax, but it seems like the controller can't read the data at all. Here is my Ajax code: let fd = n ...

Setting a variable equal to user input

When using a jQuery script, the elements for the details are dynamically created inside a jQuery function. However, there seems to be an issue with assigning the value from the variable "startLocation" to the input "detail_startLocation[]". Only the firs ...

I am struggling to render the pages and components in React while using BrowserRouter

Below is the code snippet for App.js and Home.js that I'm working on. My aim is to showcase the Home.js component in the browser. App.js import "./App.css"; import { Route, BrowserRouter } from "react-router-dom"; import Home from ...

ParcelJs is having trouble resolving the service_worker path when building the web extension manifest v3

Currently, I am in the process of developing a cross-browser extension. One obstacle I have encountered is that Firefox does not yet support service workers, which are essential for Chrome. As a result, I conducted some tests in Chrome only to discover tha ...

Pinchin opts for alternative methods over utilizing the Hammer library for calls

After downloading Hammers.js version-1.0.10, I have been trying to call the 'pinch in' function from the JavaScript file but it is not executing. I suspect there may be a problem with the library as I have tried downloading another one, but the s ...

Develop an XML document with the use of either Javascript or PHP

I have an XML file that contains information about bracelets with photo details. <bracelets> <photo filename="b1.jpg" thumbnail="a1.jpg" description="aa" /> <photo filename="b2.jpg" thumbnail="a2.jpg" description="aa" /> & ...

What is the process for incorporating an npm package into an HTML document?

Here is the code from my HTML file: <!DOCTYPE html> <head> ... </head> <body> ... <script src="script.js"></script> </body> This is what I have in my JavaScript file named script.js: import * as File ...