0

D3 ネットワークの視覚化に取り組んでおり、レイアウトを微調整しようとしています。ノードは大学のコースを表し、エッジは前提条件を接続します (たとえば、コース A がコース B の前提条件である場合、A から B への有向エッジがあります)。「AND」と「OR」を表す小さなノードもあります。たとえば、コース C を実行するためにコース A またはコース B が必要な場合、A と B から「OR」ノードを指すエッジがあります。 、および「OR」ノードから C へのエッジ。これらのネットワークは、ユーザーが選択した一連のコースに基づいて動的に生成されるため、ノードの数は数個から数百個の範囲になります。

コース ノードは、年 (1、2、3、または 4) で分類できます。現在、SVG を 4 つの水平バンドに分割しています。tick()関数では、各ノードが正しいバンドにあるかどうかを確認し、そうでない場合は正しい方向に微調整します。この種の機能は、上から下への「流れ」を維持するために機能しますが、ノードが他のノードの後ろに引っかかって、正しい場所に到達しないことがよくあります。

また、最終的なネットワークでノードをオーバーラップさせたくないので、衝突検出を使用してノード間に常にスペースを確保しています。

これらは役に立ちましたが、私が得たレイアウトにはまだ満足していません. データの性質上、エッジは常に横または下を向いている必要がありますが、上を向いていません (つまり、1 年目または 2 年目のコースは 2 年目のコースの前提条件になる可能性がありますが、3 年目のコースはそうではありません)。それは実際には木ではありませんが、ある程度の方向性があります。この制約を実装する方法はありますか? 強制指向ツリーのアプローチを試しましたが、定数を増やしても、制約は十分に強くありませんでした。正しい方向にそっと微調整するだけですが、ノードが他の力のために「動かなくなった」場合、それらは止まる。矢印の方向を「最強」の制約 (電荷や重力などの反発よりも強い) にすると、ノードがよりうまく整理されると思います。

D3 を使用するのはこれが初めてで、すでに多くの作業が行われています (D3 フォース レイアウトの組み込みパラメータ、年ごとの編成、衝突検出)。

編集:

tickエッジを処理する関数の一部にこれを追加してみました:

if (d.target.y < d.source.y) {
    var avgY = (d.target.y + d.source.y)/2;
    d.target.y = avgY;
    d.source.y = avgY;
}

私のアイデアは、ターゲットがソースの上にある場合、両方を強制的に真ん中に合わせることができるというものでした. これはある程度機能していますが、衝突検出が競合する点で少しバグがあります。2 つのノードが衝突している場合、それらは離れて移動するはずですが、それらの間のエッジが上を向いている場合、それらは一緒に押される可能性があります。これにより、一部のノードが奇妙に跳ね返ります。また、矢印の端の一部がノードに接続されなくなります。これを修正する方法について何か提案はありますか?

編集#2:

前回の編集で追加したコードをまだ使用していますが、年ごとにノードをレイヤーに分割するコードを削除しました。また、これを衝突検出用の「衝突」関数に追加し、アルファ値を渡します。

// Minimum required distance between the two nodes' centers
if (alpha > 0) {
      r = node.radius + quad.point.radius - (alpha*100);
} else {
      r = node.radius + quad.point.radius;
}

これにより、レイアウトの終わり近くで衝突検出の制約が強くなります。これは、ノードが適切なレイアウトに向かう途中で「スタック」するのを防ぐため、良いことです。最終的なレイアウトで重なっている場合にのみ、移動中にノードが重なってもかまいません。これにより得られるレイアウトにかなり満足しており、「ぶつかり合う」ことのほとんどが解決されたようです。ただし、他のアイデアがある場合は、共有してください。

4

0 に答える 0