public static ITopoArray <T> Rotate <T>(ITopoArray <T> original, int rotateCw, bool reflectX = false, TileRotate <T> tileRotate = null) { if (rotateCw == 0 && !reflectX) { return(original); } ValueTuple <int, int> MapCoord(int x, int y) { return(RotateVector(x, y, rotateCw, reflectX)); } return(RotateInner(original, MapCoord, tileRotate)); }
private static ITopoArray <T> RotateInner <T>(ITopoArray <T> original, Func <int, int, ValueTuple <int, int> > mapCoord, TileRotate <T> tileRotate = null) { // Find new bounds var(x1, y1) = mapCoord(0, 0); var(x2, y2) = mapCoord(original.Topology.Width - 1, 0); var(x3, y3) = mapCoord(original.Topology.Width - 1, original.Topology.Height - 1); var(x4, y4) = mapCoord(0, original.Topology.Height - 1); var minx = Math.Min(Math.Min(x1, x2), Math.Min(x3, x4)); var maxx = Math.Max(Math.Max(x1, x2), Math.Max(x3, x4)); var miny = Math.Min(Math.Min(y1, y2), Math.Min(y3, y4)); var maxy = Math.Max(Math.Max(y1, y2), Math.Max(y3, y4)); // Arrange so that co-ordinate transfer is into the rect bounced by width, height var offsetx = -minx; var offsety = -miny; var width = maxx - minx + 1; var height = maxy - miny + 1; var depth = original.Topology.Depth; var mask = new bool[width * height * depth]; var topology = new Topology(original.Topology.Directions, width, height, original.Topology.Depth, false, false, false, mask); var values = new T[width, height, depth]; // Copy from original to values based on the rotation, setting up the mask as we go. for (var z = 0; z < original.Topology.Depth; z++) { for (var y = 0; y < original.Topology.Height; y++) { for (var x = 0; x < original.Topology.Width; x++) { var(newX, newY) = mapCoord(x, y); newX += offsetx; newY += offsety; int newIndex = topology.GetIndex(newX, newY, z); var newValue = original.Get(x, y, z); bool hasNewValue = true; if (tileRotate != null) { hasNewValue = tileRotate(newValue, out newValue); } values[newX, newY, z] = newValue; mask[newIndex] = hasNewValue && original.Topology.ContainsIndex(original.Topology.GetIndex(x, y, z)); } } } return(new TopoArray3D <T>(values, topology)); }
public static ITopoArray <T> HexRotate <T>(ITopoArray <T> original, int rotateCw, bool reflectX, TileRotate <T> tileRotate = null) { if (rotateCw == 0 && !reflectX) { return(original); } var microRotate = rotateCw % 3; var rotate180 = rotateCw % 2 == 1; // Actually do a reflection/rotation ValueTuple <int, int> MapCoord(int x, int y) { return(HexRotateVector(x, y, microRotate, rotate180, reflectX)); } return(RotateInner(original, MapCoord, tileRotate)); }
public static ITopoArray <T> HexRotate <T>(ITopoArray <T> original, Rotation rotation, TileRotate <T> tileRotate = null) { if (rotation.IsIdentity) { return(original); } var microRotate = (rotation.RotateCw / 60) % 3; var rotate180 = (rotation.RotateCw / 60) % 2 == 1; // Actually do a reflection/rotation ValueTuple <int, int> MapCoord(int x, int y) { return(HexRotateVector(x, y, microRotate, rotate180, rotation.ReflectX)); } return(RotateInner(original, MapCoord, tileRotate)); }
public static ITopoArray <T> SquareRotate <T>(ITopoArray <T> original, Rotation rotation, TileRotate <T> tileRotate = null) { if (rotation.IsIdentity) { return(original); } ValueTuple <int, int> MapCoord(int x, int y) { return(SquareRotateVector(x, y, rotation)); } return(RotateInner(original, MapCoord, tileRotate)); }
public static ITopoArray <T> Rotate <T>(ITopoArray <T> original, Rotation rotation, TileRotate <T> tileRotate = null) { var type = original.Topology.Directions.Type; if (type == DirectionSetType.Cartesian2d || type == DirectionSetType.Cartesian3d) { return(SquareRotate(original, rotation, tileRotate)); } else if (type == DirectionSetType.Hexagonal2d) { return(HexRotate(original, rotation, tileRotate)); } else { throw new Exception($"Unknown directions type {type}"); } }