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 static string SerializeTiles(IMapChunk chunk) { // number of bytes written per tile, because sizeof(Tile) is useless. const int structSize = 4; var nTiles = chunk.ChunkSize * chunk.ChunkSize * structSize; var barr = new byte[nTiles]; using (var stream = new MemoryStream(barr)) using (var writer = new BinaryWriter(stream)) { for (ushort y = 0; y < chunk.ChunkSize; y++) { for (ushort x = 0; x < chunk.ChunkSize; x++) { var tile = chunk.GetTile(x, y); writer.Write(tile.TypeId); writer.Write(tile.Data); } } } return(Convert.ToBase64String(barr)); }
/// <summary> /// /// </summary> /// <param name="chunk"></param> /// <param name="bounds">The overall bounds that covers every rectangle.</param> /// <param name="rectangles">Each individual rectangle comprising the chunk's bounds</param> public static void PartitionChunk(IMapChunk chunk, out Box2i bounds, out List <Box2i> rectangles) { rectangles = new List <Box2i>(); // TODO: Use the existing PartitionChunk version because that one is likely faster and you can Span that shit. // Convert each line into boxes as long as they can be. for (ushort y = 0; y < chunk.ChunkSize; y++) { var origin = 0; var running = false; for (ushort x = 0; x < chunk.ChunkSize; x++) { if (!chunk.GetTile(x, y).IsEmpty) { running = true; continue; } // Still empty if (running) { rectangles.Add(new Box2i(origin, y, x, y + 1)); } origin = x + 1; running = false; } if (running) { rectangles.Add(new Box2i(origin, y, chunk.ChunkSize, y + 1)); } } // Patch them together as available for (var i = rectangles.Count - 1; i >= 0; i--) { var box = rectangles[i]; for (var j = i - 1; j >= 0; j--) { var other = rectangles[j]; // Gone down as far as we can go. if (other.Top < box.Bottom) { break; } if (box.Left == other.Left && box.Right == other.Right) { box = new Box2i(box.Left, other.Bottom, box.Right, box.Top); rectangles[i] = box; rectangles.RemoveAt(j); i -= 1; continue; } } } bounds = new Box2i(); foreach (var rectangle in rectangles) { bounds = bounds.IsEmpty() ? rectangle : bounds.Union(rectangle); } }