d3 / d3-force

Force-directed graph layout using velocity Verlet integration.
https://d3js.org/d3-force
ISC License
1.77k stars 375 forks source link

Suggestion: add an angle property to d3.forceRadial() to define the forces in this angle #152

Open logomanwolf opened 4 years ago

logomanwolf commented 4 years ago

It's a ground truth that in Polar coordinate system we need (angle,radius) to determine a position of a point. When I use d3.forceRadial to add a radial force on nodes, I surmise it could be more applicable if an angle() function is added to d3.forceRadial to define a force on an angle of radial. I thought it derives naturally without which we need to use d3.lineRadial to tranform this problem to what d3.forceCenter can solve. For example, I want to draw a graph as the following. image Each circle in the graph needs to be positioned just at the cover of an arc as if an magnet force existed.

Fil commented 4 years ago

Nice idea. See https://observablehq.com/@fil/forceangular for an implementation.

logomanwolf commented 4 years ago

Thank you for your reply. Actually, I've learned a lot from your coding.

Fil commented 4 years ago

New iteration of the code. The things that I was not happy with in the first iteration were:

1) the force did not have the correct dimension (should have been in pixels per iteration) ; it's fixed now by multiplying the tangent vector by the distance to the center.

2) points that were almost at the opposite of their target angle were boosted too much, resulting in spectacular (but wrong) movements; fixed by using hypot(1, tan(diff/2)) instead of 1+tan^2.

In both cases the result is mathematically justified, so I think the code is final. I don't know if it should be included in d3-force or not.

If it is included, and we want to modify d3.forceRadial to take into account the angle, there's a difficulty with the order of arguments: forceRadial(r, x, y) can't be easily expanded to forceRadial(r, a, x, y).

However we could define forcePolar(r, a, x, y), and make syntactic sugar for forceRadial(r, x, y) and forceAngular(a, x, y).

vasturiano commented 4 years ago

I think these new forces are very useful for various scenarios. Thanks for putting them together @Fil!

In case they don't make it to d3-force would be nice to have them available as NPM modules for ease of reuse. We can also list them on d3-force-registry.

Fil commented 4 years ago

I've mixed them into forcePolar https://observablehq.com/@fil/forcepolar with syntactic sugar for forceRadial and forceAngular

Fil commented 4 years ago

Related: https://github.com/d3/d3-force/pull/113