var simulation = d3.forceSimulation();
とは、
のような、グラフ可視化ができるシステム。リンク先を見ればコードの書き方はだいたい分かるけれども、実際に自分のデータでやってみると、いい感じになるパラメータの調整が意外と難しいので、この世界を簡単に解説する。詳しい説明は、
https://github.com/d3/d3-force
力あれ
1. 摩擦力
この世界には摩擦力があるので、動いているものはやがて止まる。
simulation.velocityDecay(0.01)
で摩擦係数を指定できる。いい感じになる前に止まってしまう場合は小さく、ふらふら動き続けて困る場合は大きくする。デフォルトは 0.4.
2. 重力
アリストテレスの重力よろしく、世界の中心に落ちていく力 d3.forceCenter
。
simulation.force("center", d3.forceCenter(width / 2, height / 2))
一点ではなくて一直線上に落ちていくようにしたい場合は d3.forceX(x)
d3.forceY(y)
がある。
3. バネ
いわゆるフックの法則。グラフの edge/link/枝が distance
よりも長い場合はその伸びに比例して引っ張られ、短い場合は押し合う。力は strength
で指定できるが、2より大きい値を入れるとなぜか爆発する。
simulation.force("link", d3.forceLink().id(function(d) { return d.id; }))
simulation.force("link")
.links(graph.links)
.distance(function(){ return 10;})
.strength(function(){ return 2; })
4. クーロン力/万有引力
simulation.force("charge", d3.forceManyBody())
simulation.force("charge")
.strength(function() { return -0.1; })
strength
に負の数を入れると互いに反発して、正の数だと引かれ合う。
5. 接触力
d3.forceCollide([radius])
グラフの vertex/node/頂点 が半径 radius
の球のようにぶつかるようになる。
固定
node0 = simulation.nodes()[0]
node0.fx = x;
node0.fy = y;
node0
を (x,y) に固定する。
alpha
alpha
というのは砂時計のようなもので、時間とともに減っていって、何ステップ世界が動くかを司る。
simulation.alpha([alpha]) // = 1
simulation.alphaMin([min]) // = 0.001
simulation.alphaDecay([decay]) // = 0.0228 = 1 - pow(0.001, 1/300)
simulation.alphaTarget([target]) // = 0
1ステップで(単位時間あたり)速度が摩擦力で
velocity <- velocity * velocityDecay
だけ減少して、alpha が、
alpha <- alpha + (alphaTarget - alpha) * alphaDecay
になる。alpha
が alphaMin
を下回ると止まり、デフォルトのパラメタでは300ステップに相当する。なぜこんなパラメタなのかわからないけれども:
-
alpha
はalphaTarget
に漸近する。 - よって、
alphaTarget
がalphaMin
以上だと止まらない。 - alphaDecay が大きければ少ないステップでalphaTargetに近づいて止まる。
例
将棋の序盤をグラフしてみたけれども、はみだしたりしてなかなか思うようにいかない...
https://junkoda.github.io/kyokumen/graph/2016_1.html