using System; namespace KeepersCompound.TMV; public static class RectPacker { public struct Rect { public int Id; public ushort X; public ushort Y; public ushort Width; public ushort Height; } public static Rect Pack(Rect[] rectangles, ushort width = 2048, ushort minHeight = 512) { ArgumentNullException.ThrowIfNull(rectangles); ArgumentOutOfRangeException.ThrowIfZero(width); ArgumentOutOfRangeException.ThrowIfZero(minHeight); var bounds = new Rect { Width = width, Height = minHeight }; if (rectangles.Length == 0) { return bounds; } Array.Sort(rectangles, (a, b) => b.Height.CompareTo(a.Height)); // Naively try to pack into the row, wrapping when we reach the end // and expanding the bounds when needed ushort rowMaxH = rectangles[0].Height; ushort x = 0; ushort y = 0; var rectCount = rectangles.Length; for (var i = 0; i < rectCount; i++) { var rect = rectangles[i]; if (x + rect.Width > width) { x = 0; y += rowMaxH; rowMaxH = rect.Height; } rect.X = x; rect.Y = y; rectangles[i] = rect; x += rect.Width; } bounds.Height = (ushort)(y + rowMaxH); return bounds; } }