まず、あなたの本当の要件が何であるかを検討する価値があると思います。「できるだけスペース効率の良い方法でアクティブなポイントを保存し、他のポイントを保存しない」だけでなく、ある程度の「隣接するポイントを近くのメモリ位置に保存して、適切なキャッシュ動作が得られるようにする」こともあると思います。 「検索が効率的にできるようにポイントを保存する」。
そうは言っても、ここに私が提案するものがあります。完全な 3D 領域をすべて同じサイズの立方体ブロックに分割します。ブロックごとに、ブロック内のすべてのポイントを密な配列に格納します。これには、各ポイントが組織領域内にあるかどうかを表すブール値の isTissue 配列が含まれます。ポイントを含むブロックのみを割り当てます。割り当てられていないブロックの NULL ポインターを使用して、ブロックへのポインターの (密な) 配列を作成します。
したがって、(i,j) のポイントを見つけるには、まず ii=i/ブロックサイド、jj=j/ブロックサイズを計算し、次に (ii,jj) のブロックへのポインター テーブルを調べて、次のブロックを見つけます。あなたのポイントが含まれています。そのポインターが NULL の場合、ポイントは組織内にありません。null でない場合は、そのブロックの (i mod blocksize, j mod blocksize) を見て、(i,j) ポイントがあります。その isTissue フラグをチェックして、それが「現在」のポイントかどうかを確認できます。
ブロックの境界を越える隣接点の計算を行う回数を最小限に抑えることと、ブロック内にあって組織領域には含まれない点の数を最小限に抑えることとの間のバランスとして、ブロック サイズを選択する必要があります。少なくとも、ブロックの行をキャッシュラインの長さにする必要があると思います。おそらく、最適値はそれよりもかなり大きいですが、ジオメトリによっては多少異なります。
3D ボックス内のすべてのポイントを反復処理するには、各ポイントのルックアップを行うか、(より効率的に) ボックスが接触しているブロックを特定し、ボックス内にあるブロック内の領域を反復処理して、 isTissue が false のもの。
ブロックの割り当て解除と再割り当てを頻繁に行っている場合は、ブロックを「未使用」プールにドロップしてブロックを「割り当て解除」し、ブロックを再割り当てするのではなく、そのプールからブロックを引き出すことをお勧めします。これには、これらのブロックのすべてのポイントが既に「存在しない」に設定されているという利点もあります (ブロックの割り当てを解除したため)。したがって、それらを初期化する必要はありません。
経験豊富な読者は、これと並列計算用のデータをレイアウトする方法との類似点に気付くでしょう。非常に大きなシミュレーションの場合、ブロックを複数のノードに簡単に分散でき、ブロック間の計算のためにノード間通信を行うだけで済みます。この種のアプリケーションでは、(ジオメトリ用の) 小さいブロックを含むメタ ブロック (クロスノード通信用) がある場合、ネストされたレベルのブロックを実行すると便利な場合があります。