手で
メモリがそれほどまばらなリソースではない場合は、より大きなチャンクで作業することを検討します。
ここにいくつかの擬似コードがあります。
class Chunk {
Chunk new(int size) {...}
void setPixel(int x, int y, int value) {...}
int getPixel(int x, int y) {...}
}
class Grid {
Map<int, Map<Chunk>> chunks;
Grid new(int chunkSize) {...}
void setPixel(int x, int y, int value) {
getChunk(x,y).setPixel(x % chunkSize, y % chunkSize, value);//actually the modulo could be right in Chunk::setPixel and getPixel for more safety
}
int getPixel(int x, int y) { /*along the lines of setPixel*/ }
private Chunk getChunk(int x, int y) {
x /= chunkSize;
y /= chunkSize;
Map<Chunk> row = chunks.get(y);
if (row == null) chunks.set(y, row = new Map<Chunk>());
Chunk ret = row.get(x);
if (ret == null) row.set(x, ret = new Chunk(chunkSize));
return ret;
}
}
この実装は非常に単純です。
1つは、getPixelにチャンクを作成することです(基本的に、その位置にチャンクが定義されていない場合は、単純に0を返すだけでかまいません)。2つ目は、十分に高速でスケーラブルなMapの実装があるという前提に基づいています。私の知る限り、すべてのまともな言語には1つあります。
また、チャンクサイズでプレイする必要があります。密なビットマップの場合、チャンクサイズは大きい方が適切です。まばらなビットマップの場合、チャンクサイズは小さいほど良いです。実際、非常にまばらなものの場合、「チャンクサイズ」は1が最適です。「チャンク」自体を廃止し、データ構造をピクセルのintマップのintマップに減らします。
既製品
別の解決策は、いくつかのグラフィックライブラリを調べることです。実際には、2Dバッファーを別の2Dバッファーに描画するのが非常に得意です。つまり、より大きなバッファを割り当てて、それに対応する座標でオリジナルを描画することになります。
一般的な戦略として:「動的に増大するメモリブロック」がある場合、使い尽くされたら、その複数を割り当てることをお勧めします。これはかなりメモリを消費しますが、割り当てとコピーのコストを大幅に削減します。ほとんどのベクター実装では、サイズを超えるとサイズの2倍が割り当てられます。したがって、特に既製のソリューションを使用する場合は、1ピクセルしか要求されなかったため、バッファを1ピクセルだけ拡張しないでください。割り当てられたメモリは安価です。再割り当て、コピー、解放にはコストがかかります。