3

私は、D3 に組み込まれている力指向アルゴリズムを使用して、ネットワーク トポロジの視覚化に取り組んできました。すべてがうまく機能していますが、1 つの重要な詳細に問題があります...さまざまな数のノードを持つグラフの理想的な方法でグラフをレイアウトすることができないようです。理想的には、ノードはそれぞれから適切な間隔で配置され (オーバーラップなし)、意味のある場所にノードがクラスター化されることを意味します。力のレイアウトの「電荷」と「重力」のプロパティを調整することでこれを実行しようとしましたが、何を試しても、1 つのシナリオ (つまり、多数のノード) では常に機能するようですが、そうではありません。別のシナリオ (つまり、少数のノード) の場合。たとえば、大きなグラフでレイアウトが機能している場合、電荷/重力の同じ式を使用して小さなグラフを見ると、残りのノードから離れた場所にあるノードがいくつかあります。別のSOの質問に基づいて使用していた式の例を次に示しますポスト:

var k = Math.sqrt(json.nodes.length / (dim.w * dim.h));
var charge = -10 / k;
var gravity = 100 * k;

これは 14 ノードのグラフで機能しますが、5 ノードのグラフで同じことを試みると、それらのノードの一部が完全に画面からはみ出してしまいます。「k」の計算で使用される幅/高さは、これら 2 つのシナリオ間で変化しないことに注意してください。グラフの表示領域の幅/高さに基づいて、これらのプロパティを使用しないでください。正直なところ、これは要件ではありません。グラフをレンダリングしてグラフのビューポートに収める必要はありません。グラフ自体を適切にレイアウトする必要があるだけなので、特に大きなグラフでは、一部が可視領域外にある場合でも問題ありません。私はまた、いくつかの成功を収めて以下を試しましたが、小さなグラフの場合、ノードがグラフの残りの部分から離れすぎてレンダリングされていることがまだわかります:

var charge = -1 * Math.pow(json.nodes.length, 3);
var gravity = 1 / json.nodes.length;

誰でもこれで私を助けることができますか?このatmに行き詰まりを感じているので、大変感謝しています。

4

2 に答える 2

3

これは実は自分で調べたのですが…

したがって、電荷/重力などに使用していた値はそれほど問題ではありませんでした。この問題は、グラフを調整するために tick 関数が呼び出された回数に関連していました。私のより大きなグラフでは、ノードは常にかなり適切に配置されていました。私が抱えていた主な問題は、小さなグラフでした。グラフに約 5 ~ 10 個のノードしかない場合、ノードが頻繁にビューポートの外側に配置されることがわかりました。

私のコードでは、次のように tick 関数を手動で呼び出しています。

force.start();

for (var i = tickLimit; i > 0; --i)
    force.tick();

force.stop();

以前は、 tickLimit は次のように設定されていました。

var tickLimit = Math.pow(json.nodes.length, 2);

電荷/重力値などをいじった後、これは小さなグラフには不十分であることに最終的に気付きました。4 つのノードを持つグラフがある場合、16 回の tick() 呼び出しのみが行われることを意味します。これは、グラフがそれ自体を完全に調整する (つまり、安定させる) には十分ではありません。したがって、グラフが最小回数 (例: 少なくとも 300 回) と最大回数 (例: 10000 回以下) を刻むようにするためのチェックを追加する必要がありました。

これは誰にとってもうまくいくとは限りませんが、私にとっては問題を解決します。

于 2013-09-19T18:40:18.963 に答える