3

ペインにノードをプロットする演習で忙しいです。私の最初の目標は、100万のノードで作業し、それを1,500万まで増やすことです。

カスタムオブジェクトグラフがあり、このオブジェクトにエッジとノードを追加できます。各ノードオブジェクトには、呼び出してプロットできる楕円があり、エッジオブジェクトと同じです。現在、ノードのランダムな位置を生成する関数があります。

現在、スクロールペインを使用して、ペインの周囲のパンを有効にし、すべてのノードを表示しています。

私が良い考えだと思ったのは、ハッシュマップを使用することでした

Map<String, ArrayList<Node>> mapX = new HashMap<String, ArrayList<Node>>();
Map<String, ArrayList<Node>> mapY = new HashMap<String, ArrayList<Node>>();

次のコードを使用して、ノードをハッシュマップに追加します。

int  tempXFloor = (int)Math.floor(tempX);
ArrayList<Node> tempList = mapX.get(tempXFloor+"");
if(tempList == null){
tempList = new ArrayList<>();
}
tempList.add(node); 
mapX.put(tempXFloor+"",tempList);

次に、パンしている間に現在の位置を取得し、床に配置して、マップにエントリが存在するかどうかを確認します。エントリが存在する場合は、ArrayList内のすべてのノードをnodesOnScreenに追加します。ノードOnScreenはArrayListタイプであり、パン中にノードをそのリストに追加します。同様に、画面外のノードはnodesOnScreen変数から削除されます。

ArrayListnodesOnScreenにあるノードのみをプロットします。

この件に関するガイダンスと、そのようなビッグデータ構造の処理方法をいただければ幸いです。私は正しい方向に進んでいますか、それともそれを行うための明白な「トリック」を逃していますか。

4

4 に答える 4

3

考慮すべき点がいくつかあります。

  1. ノードはどのくらい複雑ですか? それらが単なるドットである場合は、それらをWritableImageに描画して、多くのメモリを節約することを検討してください。より複雑なケースでは、 Canvasを使用したい場合があります。どちらの方法でも、イベント ハンドラー、プロパティ、およびその他の重要な小さなことを節約できます。

  2. もう 1 つの重要な問題は、データ ビューの関連性です。地図などを提示する場合、ユーザーは目に見える部分だけを気にします。残りはディスク キャッシュに格納でき、パレートの原則により、そのデータの 20% のみが多くの用途に使用されます。したがって、それに応じて計画を立て、目に見える部分だけに実際のグラフィカル ノードを持たせることができます (ユーザー エクスペリエンスのために調整された部分をプリロードすることもできます)。

  3. 「分割統治」構想。プラン (2) に従ってユーザー ビューを制限したくない場合でも、1500 万のノードが常に必要になるわけではありません。UI ライブラリにはありません。残念ながら十分な大きさのモニターがありません。したがって、データをセグメントに分割し、一度に 1 つのセグメントをロードします。セット全体に対して何らかの種類の計算を実行する必要がある場合は、ノードを使用せず、最も単純な実装を使用して、何らかのバックグラウンド プロセスで計算を実行します。

  4. 既存のソリューションは、大きなことを行う前に常に調査の問題です。たとえば、PojoCacheのようなキャッシング ライブラリが多数あり、数十億のノードをグループに分割するだけで関連データをシームレスに操作できます。

于 2012-12-18T17:21:17.467 に答える
3

あなたが望むものは、空間分割構造のカテゴリーに分類されます。

あなたが説明したことは、均一なグリッドまたはビンの特殊な形式です。一般的なバージョンは、各ビンのサイズが 1 ユニットを超える場合があるため、異なる解像度のデータセットにより適しているという点で、あなたのものとは異なります。ビンは一般に、多かれ少なかれ均一に分散されているデータセットに役立ちます。また、実装も非常に簡単です。画面上の要素を見つけるには、ビューポートが該当するすべてのビンを見つけるだけです。

データセットが均一でない場合、つまり密な塊と大きな空きスペースがある場合は、四分木などの代替構造を試してください。

また、ハッシュ テーブルまたはその他の Java コンテナーを使用している場合は、int を Integer ( Map<Integer, ...>) にボックス化して使用します。文字列に変換しないでください。文字列に変換すると、速度が大幅に低下し、より多くのメモリが消費されます。

于 2012-12-18T13:19:39.053 に答える
2

データ仮想化とデータプロバイダーを使用して、「オンザフライ」でビルドしてみることができます。ビッグデータを保持するためにRAMを使用しないでください。データベースクエリを使用します。リストタイプを実装し、そこにインデクサーを実装します。これにより、データベースからアイテムが返されます。

于 2012-12-18T13:31:53.520 に答える
1

詳細レベルについて考えてみましょう。画面上に 15M の個別のドットを表示することはおそらく不可能です (背景の上に個々のノードの前景を表示するのに十分なピクセルがありません)。2 種類の詳細レベル アプローチを使用できます。

  • グラフィカル: 非常に大きなキャンバス (たとえば、10M x 10M) を使用し、一度に小さなタイル (たとえば、1K x 1K ピクセル) を描画し、これらを縮小して最終的な画像を構成します (たとえば、1K x 1K -> 10 x 10 を 2 回使用すると、10M x 10M の仮想キャンバスを 1K x 1K の画像に縮小できます)。

  • セマンティック: ノードの塊を単一のノードに集約し、個々のノードの代わりに塊ノードを描画します。これは、いくつかのレベルで行うことができます。実際、グラフの描画を計画している場合、これはまさにグラフ描画アルゴリズムがその下で行うことです (グラフ描画アルゴリズムは、何らかの階層分解なしに適切な時間で 50K を超えるノードを処理しません)。

どちらの場合も、ある種のズームと詳細をオンデマンドで提供します。メインの概要は、特定の詳細にパンおよびズームするためだけに使用されます。ある種の空間インデックス (クワッド ツリーが最も一般的なものです) を使用すると、ディスクまたはセカンダリ ストレージからタイルをすばやく取得できます。セマンティックズームのシナリオでは、代わりに各ノードに「親」フィールドを追加して、ノードの巨大な (外部でシリアル化されます。本当に必要でない限り、メモリに 15M ノードをロードしないでください) ツリーを構築します。

于 2012-12-18T17:47:40.443 に答える