vasturiano / 3d-force-graph

3D force-directed graph component using ThreeJS/WebGL
https://vasturiano.github.io/3d-force-graph/example/large-graph/
MIT License
4.48k stars 803 forks source link

selective use of d3Force('collision', d3.forceCollide #634

Closed PatrickF-mbse closed 11 months ago

PatrickF-mbse commented 11 months ago

Hi, A little question:

I trying to display an hierarchical structure in the Z direction and planar XY. On the picture below, case 1 does not use a the D3 collide function and case 2 use it. I noticed it is applying it to all the nodes.

I would like to apply the collide function for the large rectangular shape based on a dimension L1 and a different collide based on a different node size L2. => to have picture 1 but spaced only for the rectangular shape with the small rectangular plate and yellow nodes staying inside the larger plate they belong to.

Do you think this collide function can work for specific set of nodes? I tried the code ( case 2) but it did not spaced the rectangular layer (const geometry = new THREE.BoxGeometry(node.l1, node.l2, node.l3 || 10);)

not sure if this D3 collide function can work on a subset of nodes?

Thankyou

case1: ok working //this works test 1 //node.L1 Graph_g5.d3Force('collision', d3.forceCollide(node => Math.cbrt(500) * NODE_REL_SIZE)) Graph_g5.d3VelocityDecay(0.3)

case2: //test 2 only for package Graph_g5.d3Force('collision', (node) => { if (node.subtype === 'layer') { return Graph_g5.forceCollide(node => Math.cbrt(500) * NODE_REL_SIZE); } else { return null; // No collision force for other nodes } }) Graph_g5.d3VelocityDecay(0.3)

Case 1: .d3Force('charge').strength(-50) & Fz set image

Case 2 collide & .d3Force('charge').strength(-50); & Fz set image

vasturiano commented 11 months ago

@PatrickF-mbse I believe you just need to return radius 0 for the nodes you don't want the collision force to act. That essentially deactivates it. Something like:

.d3Force('collision', d3.forceCollide(node => node.subtype === 'layer' ? Math.cbrt(500) * NODE_REL_SIZE : 0))
PatrickF-mbse commented 11 months ago

@vasturiano Hi, thank you very much for the tip. it worked for the large panels and the smallest elements stayed closer but they are still trying to fill a space in between the big panels. Maybe enforcing the horizontal links distance between specifics elements could bring them back. Will try this next . Anyway thank you. Progress.

I could try to compute the position before creating the graph but I would prefer a solution that allows to "self arrange". I feel it almost like an hierarchy of "collide" functions or connected independent graphs with each having a set of "collide rules" problem to solve ( the yellow elements need to stay above the small blue panels that need to stay above the large grey panels while not colliding. and this happening at each level..:) maybe not be something in scope of d3 out of the box).

.Anyway thank you, I will investigate further the d3 physics api to see if could be possible to create some set of nodes where specifics collide rules are applied. This use of "node => node.subtype === 'layer' ?" is a good method i was not aware of.

image

PatrickF-mbse commented 11 months ago

..