vasturiano / d3-force-registry

A curated compilation of plugins and all-things related to d3-force
139 stars 10 forks source link

Iterative-Relaxation in d3.forceLink #8

Open gvarnavi opened 3 years ago

gvarnavi commented 3 years ago

Wasn't too sure where to post this, but this repo seems to curate d3-force plugins for use in (perhaps) unusual use-cases, like physical simulations - so figured I'd alert users to energy-conservation in d3-force.

In particular, the Pendulum example asks:

Ok, I'm confused. Why isn't energy conserved and does the pendulum eventually stop?

Similarly, the Newton's Cradle example also 'thermalizes' albeit both explicitly setting:

d3.forceSimulation()
    .alphaDecay(0)
    .velocityDecay(0)

The issue is that d3.forceLink actually performs iterative relaxation. The offending lines in the source code are:

        x = target.x + target.vx - source.x - source.vx || jiggle(random);
        y = target.y + target.vy - source.y - source.vy || jiggle(random);

Note the link distance is specified by 'peeking ahead' to the anticipated position of the node ⟨x + vx,y + vy⟩.

This notebook further explains the issue using examples, and suggests two alternatives.

vasturiano commented 3 years ago

@gvarnavi this is awesome research, great work! I think it's well worth to post this on the https://github.com/d3/d3-force repo for broader visibility.