namespace Squish
{
///
/// An object which contains a two-dimensional grid of values.
///
/// The type of values.
public class Grid
: IEnumerable
{
#region Constructors
///
/// An object which contains a two-dimensional grid of values.
///
/// The width.
/// The height.
public Grid(int width, int height)
{
if (width < 0) width = 0; // Having a width or height of 0 won't be usable,
if (height < 0) height = 0; // but at least the value ranges would be "expected"
_values = new T[height][];
for (int i = 0; i < height; i++)
_values[i] = new T[width];
Width = width;
Height = height;
}
#endregion
#region Indexers
///
/// Gets or sets a value.
///
/// The X coordinate.
/// The Y coordinate.
/// The value.
public T this[int x, int y]
{
get
{
return _values[y][x];
}
set
{
_values[y][x] = value;
}
}
#endregion
// Variables
private readonly T[][] _values;
// Properties
#region Width
///
/// Gets a value which indicates the width.
///
public int Width
{
get;
private set;
}
#endregion
#region Height
///
/// Gets a value which indicates the height.
///
public int Height
{
get;
private set;
}
#endregion
// Methods
#region Transpose
///
/// Returns a new object which is the transpose copy of this grid.
///
/// The grid.
public Grid Transpose()
{
Grid result = new Grid(Height, Width);
for (int y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
result._values[x][y] = _values[y][x];
return result;
}
#endregion
#region Flip
///
/// Returns a new object which is a horizontal or vertical copy of this grid.
///
/// Whether to perform a horizontal flip.
/// Whether to perform a vertical flip.
/// The grid.
public Grid Flip(bool horizontal, bool vertical)
{
Grid result = new Grid(Width, Height);
if (horizontal && vertical)
{
for (int y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
result._values[y][x] = _values[Height - y - 1][Width - x - 1];
return result;
}
if (horizontal)
{
for (int y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
result._values[y][x] = _values[y][Width - x - 1];
return result;
}
if (vertical)
{
for (int y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
result._values[y][x] = _values[Height - y - 1][x];
return result;
}
for (int y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
result._values[y][x] = _values[y][x];
return result;
}
#endregion
#region Rotate
///
/// Returns a new object which is the rotation copy of this grid.
///
/// Whether to rotate clockwise or anti-clockwise.
/// The grid.
public Grid Rotate(bool clockwise)
{
Grid result = new Grid(Height, Width);
if (clockwise)
{
for (int y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
result._values[x][y] = _values[Height - y - 1][x];
}
else
{
for (int y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
result._values[x][y] = _values[y][Width - x - 1];
}
return result;
}
#endregion
#region Copy
///
/// Returns a new object which is a copy of the grid.
///
/// The grid.
public Grid Copy()
{
Grid result = new Grid(Width, Height);
for (int y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
result._values[y][x] = _values[y][x];
return result;
}
#endregion
#region Slice
///
/// Returns a new object which is a subregion of the grid.
///
/// The region.
/// The grid.
public Grid Slice(Rectangle region)
{
region = Rectangle.Intersect(region, new Rectangle(0, 0, Width, Height));
Grid result = new Grid(region.Width, region.Height);
for (int y = 0; y < region.Height; y++)
for (int x = 0; x < region.Width; x++)
result._values[y][x] = _values[region.Y + y][region.X + x];
return result;
}
///
/// Returns a new object which is a subregion of the grid.
///
/// The X coordinate.
/// The Y coordinate.
/// The width.
/// The height.
/// The grid.
public Grid Slice(int x, int y, int width, int height)
{
return Slice(new Rectangle(x, y, width, height));
}
#endregion
#region GetEnumerator
///
/// Enumerates the elements of the grid.
///
/// The values.
public IEnumerator GetEnumerator()
{
for (int y = 0; y < Height; y++)
for (int x = 0; x < Width; x++)
yield return _values[y][x];
}
///
/// Enumerates the elements of the grid.
///
/// The value.
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
}