Files
RobustToolbox/Robust.Shared/Map/GridChunkPartition.cs
T
AcruidandGitHub 2183cd7ca1 Massive Namespace Cleanup (#1544)
* Removed the Interfaces folder.
* All objects inside the GameObjects subfolders are now in the GameObjects namespace.
* Added a Resharper DotSettings file to mark the GameObjects subfolders as not providing namespaces.
* Simplified Robust.client.Graphics namespace.
* Automated remove redundant using statements.
2021-02-10 23:27:19 -08:00

131 lines
4.0 KiB
C#

using System.Collections.Generic;
using Robust.Shared.Maths;
namespace Robust.Shared.Map
{
/// <summary>
/// Partitions a grid chunk into a set of non-overlapping rectangles.
/// </summary>
internal static class GridChunkPartition
{
public static void PartitionChunk(IMapChunk chunk, ref IList<Box2> rectangles, out Box2i bounds)
{
rectangles.Clear();
var size = chunk.ChunkSize;
// copy 2d img
bool[,] image = new bool[size,size];
for(ushort x=0;x<size;x++)
for (ushort y = 0; y < size; y++)
image[x, y] = !chunk.GetTile(x, y).IsEmpty;
Partition(size, size, image, out var blocks, out var blockCount);
bounds = new Box2i();
// convert blocks to rectangles array.
for(int i=0;i< blockCount; i++)
{
var block = blocks[i];
// block are in indices and rotated 90 degrees :(
var left = block.y1;
var right = block.y2 + 1;
var bottom = block.x1;
var top = block.x2 + 1;
rectangles.Add(new Box2(left, bottom, right, top));
if(bounds.Size.Equals(Vector2i.Zero))
bounds = new Box2i(left, bottom, right, top);
else
bounds = bounds.Union(new Box2i(left, bottom, right, top));
}
}
private struct Block
{
public int x1;
public int x2;
public int y1;
public int y2;
}
private static void Partition(in int L, in int W, in bool[,] img, out Block[] block, out int blockno)
{
// Credit: http://utopia.duth.gr/spiliot/papers/j7.pdf
block = new Block[L*W];
int[] p = new int[W];
int[] c = new int[W];
int kp = 0;
blockno = 0;
for (int y = 0; y < L; y++)
{
int x1 = 0;
int x2 = 0;
int kc = 0;
bool intervalfound = false;
int j_last = 0;
int j_curr = 0;
for (int x = 0; x < W; x++)
{
bool try2match = false;
if (img[y,x] && !intervalfound)
{
intervalfound = true;
x1 = x;
}
if (!img[y,x] && intervalfound)
{
intervalfound = false;
x2 = x - 1;
try2match = true;
}
if (x == W - 1 && img[y,x] && intervalfound)
{
x2 = x;
try2match = true;
}
if (try2match)
{
bool intervalmatched = false;
for (int j = j_last; j < kp && x1 >= block[p[j]].x1; j++)
if (x1 == block[p[j]].x1 && x2 == block[p[j]].x2)
{
c[kc] = p[j];
block[p[j]].y2 = y;
intervalmatched = true;
j_curr = j;
}
j_last = j_curr;
if (!intervalmatched)
{
block[blockno].x1 = x1;
block[blockno].x2 = x2;
block[blockno].y1 = y;
block[blockno].y2 = y;
c[kc] = blockno++;
}
if (!intervalmatched)
kc++;
}
}
for (var i = 0; i < kc; i++)
p[i] = c[i];
kp = kc;
}
}
}
}