private static bool TryExtract(ITopoArray <Tile> sample, int nx, int ny, int nz, int x, int y, int z, out PatternArray pattern) { var width = sample.Topology.Width; var height = sample.Topology.Height; var depth = sample.Topology.Depth; var values = new Tile[nx, ny, nz]; for (int tx = 0; tx < nx; tx++) { var sx = (x + tx) % width; for (int ty = 0; ty < ny; ty++) { var sy = (y + ty) % height; for (int tz = 0; tz < nz; tz++) { var sz = (z + tz) % depth; var index = sample.Topology.GetIndex(sx, sy, sz); if (!sample.Topology.ContainsIndex(index)) { pattern = default(PatternArray); return(false); } values[tx, ty, tz] = sample.Get(sx, sy, sz); } } } pattern = new PatternArray { Values = values }; return(true); }
/// <summary> /// Calls <c>func</c> on each element of the array, returning a new <see cref="ITopoArray{T}"/> /// </summary> public static ITopoArray <U> Map <T, U>(this ITopoArray <T> topoArray, Func <T, U> func) { /* * var width = topoArray.Topology.Width; * var height = topoArray.Topology.Height; * var depth = topoArray.Topology.Depth; * var r = new U[width, height, depth]; * * for (var z = 0; z < depth; z++) * { * for (var y = 0; y < height; y++) * { * for (var x = 0; x < width; x++) * { * r[x, y, z] = func(topoArray.Get(x, y, z)); * } * } * } * * return new TopoArray3D<U>(r, topoArray.Topology); */ var r = new U[topoArray.Topology.IndexCount]; foreach (var i in topoArray.Topology.GetIndices()) { r[i] = func(topoArray.Get(i)); } return(new TopoArray1D <U>(r, topoArray.Topology)); }
public static ITopoArray <T> Scale <T>(ITopoArray <T> topoArray, int scale) { var topology = topoArray.Topology.AsGridTopology(); if (topology.Mask != null) { throw new NotSupportedException(); } var result = new T[topology.Width * scale, topology.Height *scale, topology.Depth *scale]; for (var z = 0; z < topology.Depth; z++) { for (var y = 0; y < topology.Height; y++) { for (var x = 0; x < topology.Width; x++) { var value = topoArray.Get(x, y, z); for (var dz = 0; dz < scale; dz++) { for (var dy = 0; dy < scale; dy++) { for (var dx = 0; dx < scale; dx++) { result[x * scale + dx, y *scale + dy, z *scale + dz] = value; } } } } } } var resultTopology = topology.WithSize(topology.Width * scale, topology.Height * scale, topology.Depth * scale); return(TopoArray.Create(result, resultTopology)); }
private Vector3Int?GetContradictionLocation(ITopoArray <ModelTile?> result) { var topology = result.Topology; var mask = topology.Mask; var empty = mask.ToArray(); for (var x = 0; x < topology.Width; x++) { for (var y = 0; y < topology.Height; y++) { for (var z = 0; z < topology.Depth; z++) { var p = new Vector3Int(x, y, z); // Skip if already filled if (!empty[GetMaskIndex(p)]) { continue; } var modelTile = result.Get(x, y, z); if (modelTile == null) { continue; } var tile = modelTile.Value.Tile; if (tile == null) { return(new Vector3Int(x, y, z)); } } } } return(null); }
private static void Save(Size size, Xyzi xyzi, ITopoArray <byte> topArray) { // TODO size.SizeX = topArray.Topology.Width; size.SizeY = topArray.Topology.Height; size.SizeZ = topArray.Topology.Depth; xyzi.Voxels = new List <Voxel>(); for (var z = 0; z < size.SizeZ; z++) { for (var y = 0; y < size.SizeY; y++) { for (var x = 0; x < size.SizeX; x++) { var colorIndex = topArray.Get(x, y, z); if (colorIndex != 0) { xyzi.Voxels.Add(new Voxel { X = (byte)x, Y = (byte)y, Z = (byte)z, ColorIndex = colorIndex, }); } } } } }
private static FrequencySet[] GetFrequencySets(ITopoArray <IDictionary <Tile, PriorityAndWeight> > weights, TileModelMapping tileModelMapping) { var frequencies = new FrequencySet[tileModelMapping.PatternTopology.IndexCount]; foreach (var patternIndex in tileModelMapping.PatternTopology.GetIndices()) { // TODO if (tileModelMapping.PatternCoordToTileCoordIndexAndOffset != null) { throw new NotImplementedException(); } // TODO: Detect duplicate dictionaries by reference and share the frequency sets? var tileIndex = patternIndex; var offset = 0; var weightDict = weights.Get(tileIndex); var newWeights = new double[tileModelMapping.PatternModel.PatternCount]; var newPriorities = new int[tileModelMapping.PatternModel.PatternCount]; foreach (var kv in weightDict) { var pattern = tileModelMapping.TilesToPatternsByOffset[offset][kv.Key].Single(); newWeights[pattern] = kv.Value.Weight; newPriorities[pattern] = kv.Value.Priority; } frequencies[patternIndex] = new FrequencySet(newWeights, newPriorities); } return(frequencies); }
public void DoBan(int index, int pattern) { var clean = cleanPatterns.Get(index); if (clean == pattern) { dirtyIndices.Add(index); } }
public void AddSample(ITopoArray <Tile> sample) { var topology = sample.Topology.AsGridTopology(); SetDirections(topology.Directions); var width = topology.Width; var height = topology.Height; var depth = topology.Depth; var directionCount = topology.Directions.Count; for (var z = 0; z < depth; z++) { for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { var index = topology.GetIndex(x, y, z); if (!topology.ContainsIndex(index)) { continue; } // Find the pattern and update the frequency var pattern = GetPattern(sample.Get(x, y, z)); frequencies[pattern] += 1; // Update propagator for (var d = 0; d < directionCount; d++) { int x2, y2, z2; if (topology.TryMove(x, y, z, (Direction)d, out x2, out y2, out z2)) { var pattern2 = GetPattern(sample.Get(x2, y2, z2)); propagator[pattern][d].Add(pattern2); } } } } } }
public FrequencySet Get(int index) { var id = weightSetByIndex.Get(index); if (frequencySets.TryGetValue(id, out var fs)) { return(fs); } return(frequencySets[id] = GetFrequencySet(weightSets[id], tileModelMapping)); }
private static ITopoArray <T> RotateInner <T>(ITopoArray <T> original, Func <int, int, ValueTuple <int, int> > mapCoord, TileRotate <T> tileRotate = null) { var originalTopology = original.Topology.AsGridTopology(); // Find new bounds var(x1, y1) = mapCoord(0, 0); var(x2, y2) = mapCoord(originalTopology.Width - 1, 0); var(x3, y3) = mapCoord(originalTopology.Width - 1, originalTopology.Height - 1); var(x4, y4) = mapCoord(0, originalTopology.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 = originalTopology.Depth; var mask = new bool[width * height * depth]; var topology = new GridTopology(originalTopology.Directions, width, height, originalTopology.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 < originalTopology.Depth; z++) { for (var y = 0; y < originalTopology.Height; y++) { for (var x = 0; x < originalTopology.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 && originalTopology.ContainsIndex(originalTopology.GetIndex(x, y, z)); } } } return(new TopoArray3D <T>(values, topology)); }
/// <summary> /// Converts from DeBroglie's array format back to Tessera's. /// </summary> internal IEnumerable <TesseraTileInstance> GetTesseraTileInstances(ITopoArray <ModelTile?> result) { var topology = result.Topology; var mask = topology.Mask; var empty = mask.ToArray(); for (var x = 0; x < topology.Width; x++) { for (var y = 0; y < topology.Height; y++) { for (var z = 0; z < topology.Depth; z++) { var p = new Vector3Int(x, y, z); // Skip if already filled if (!empty[GetMaskIndex(p)]) { continue; } var modelTile = result.Get(x, y, z); if (modelTile == null) { continue; } var rot = modelTile.Value.Rotation; var tile = modelTile.Value.Tile; if (tile == null) { continue; } var ti = GetTesseraTileInstance(x, y, z, modelTile.Value); // Fill locations foreach (var p2 in ti.Cells) { if (InBounds(p2)) { empty[GetMaskIndex(p2)] = false; } } if (ti != null) { yield return(ti); } } } } }
private static List <T> SliceZ <T>(ITopoArray <T> topoArray, int z) { var l = new List <T>(); var topology = topoArray.Topology; for (var y = 0; y < topology.Height; y++) { for (var x = 0; x < topology.Width; x++) { var i = topology.GetIndex(x, y, z); l.Add(topology.ContainsIndex(i) ? topoArray.Get(i) : default(T)); } } return(l); }
private static List <T> SliceY <T>(ITopoArray <T> topoArray, int y) { var l = new List <T>(); var topology = topoArray.Topology; for (var z = 0; z < topology.Depth; z++) { for (var x = 0; x < topology.Width; x++) { var i = topology.GetIndex(x, y, z); l.Add(topology.ContainsIndex(i) ? topoArray.Get(i) : default(T)); } } return(l); }
/// <summary> /// Copies a <see cref="ITopoArray{T}"/> into a 2d array. /// </summary> public static T[,] ToArray2d <T>(this ITopoArray <T> topoArray) { var width = topoArray.Topology.Width; var height = topoArray.Topology.Height; var results = new T[width, height]; for (var x = 0; x < width; x++) { for (var y = 0; y < height; y++) { results[x, y] = topoArray.Get(x, y); } } return(results); }
/// <summary> /// Copies a <see cref="ITopoArray{T}"/> into a 3d array. /// </summary> public static T[,,] ToArray3d <T>(this ITopoArray <T> topoArray) { var width = topoArray.Topology.Width; var height = topoArray.Topology.Height; var depth = topoArray.Topology.Depth; var results = new T[width, height, depth]; for (var x = 0; x < width; x++) { for (var y = 0; y < height; y++) { for (var z = 0; z < depth; z++) { results[x, y, z] = topoArray.Get(x, y, z); } } } return(results); }
/// <summary> /// Calls <c>func</c> on each element of the array, returning a new <see cref="ITopoArray{T}"/> /// </summary> public static ITopoArray <U> Map <T, U>(this ITopoArray <T> topoArray, Func <T, U> func) { var width = topoArray.Topology.Width; var height = topoArray.Topology.Height; var depth = topoArray.Topology.Depth; var r = new U[width, height, depth]; for (var z = 0; z < depth; z++) { for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { r[x, y, z] = func(topoArray.Get(x, y, z)); } } } return(new TopoArray3D <U>(r, topoArray.Topology)); }
/// <summary> /// Returns a <see cref="GridTopology"/> with the same parameters, but with the specified mask /// </summary> public GridTopology WithMask(ITopoArray <bool> mask) { if (!IsSameSize(mask.Topology.AsGridTopology())) { throw new System.Exception("Mask size doesn't fit the topology"); } var boolMask = new bool[Width * Height * Depth]; for (var z = 0; z < Depth; z++) { for (var y = 0; y < Height; y++) { for (var x = 0; x < Width; x++) { boolMask[x + y * Width + z * Width * Height] = mask.Get(x, y, z); } } } return(WithMask(boolMask)); }
public static ITopoArray <V> Explode <U, V>(ITopoArray <U> topoArray, Func <U, ITopoArray <V> > getSubTile, int tileWidth, int tileHeight, int tileDepth) { var inTopology = topoArray.Topology.AsGridTopology(); if (inTopology.Directions.Type != DirectionSetType.Cartesian2d && inTopology.Directions.Type != DirectionSetType.Cartesian3d) { throw new NotImplementedException(); } var inWidth = inTopology.Width; var inHeight = inTopology.Height; var inDepth = inTopology.Depth; var resultTopology = inTopology.WithSize( inWidth * tileWidth, inHeight * tileHeight, inDepth * tileDepth ); var result = new V[resultTopology.Width, resultTopology.Height, resultTopology.Depth]; var mask = new bool[resultTopology.Width * resultTopology.Height * resultTopology.Depth]; for (var z = 0; z < inDepth; z++) { for (var y = 0; y < inHeight; y++) { for (var x = 0; x < inWidth; x++) { if (inTopology.Mask != null) { var index = inTopology.GetIndex(x, y, z); if (!inTopology.Mask[index]) { continue; } } var inTile = topoArray.Get(x, y, z); var subTile = getSubTile(inTile); if (subTile == null) { continue; } for (var tz = 0; tz < tileDepth; tz++) { for (var ty = 0; ty < tileHeight; ty++) { for (var tx = 0; tx < tileWidth; tx++) { if (subTile.Topology.Mask != null) { var index = subTile.Topology.GetIndex(tx, ty, tz); if (!subTile.Topology.Mask[index]) { continue; } } result[x * tileWidth + tx, y *tileHeight + ty, z *tileDepth + tz] = subTile.Get(tx, ty, tz); mask[resultTopology.GetIndex(x * tileWidth + tx, y * tileHeight + ty, z * tileDepth + tz)] = true; } } } } } } return(TopoArray.Create(result, resultTopology)); }
/// <summary> /// Convers a <see cref="ITopoArray{T}"/> to a layer of a Map /// If the array is 3d, this reads a place with a given z co-ordinate. /// </summary> public static TileLayer MakeTileLayer(Map map, ITopoArray <Tile> array, int z = 0) { if (map.Orientation == Orientation.orthogonal || map.Orientation == Orientation.isometric && map.StaggerAxis == StaggerAxis.None) { var width = array.Topology.Width; var height = array.Topology.Height; var data = new int[width * height]; var i = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { data[i++] = TileToGid(array.Get(x, y, z), Orientation.orthogonal); } } var layer = new TileLayer(); layer.Encoding = "base64"; layer.Data = data; layer.Width = width; layer.Height = height; layer.Visible = true; layer.Opacity = 1.0; layer.LayerType = LayerType.tilelayer; return(layer); } else if (map.Orientation == Orientation.hexagonal) { // Tiled uses a staggered hex layout, while we use an axial one // Convert between them, masking out the dead space // For now, only support one mode of staggering if (map.StaggerAxis != StaggerAxis.y) { throw new NotImplementedException($"Maps staggered on x axis not supported"); } var width = array.Topology.Width; var height = array.Topology.Height; var newWidth = width + (height + 1) / 2; var newHeight = height; var data = new int[newWidth * newHeight]; var isStaggered = map.StaggerIndex == StaggerIndex.even; var xoffset = (isStaggered ? 1 : 0) + (height + 1) / 2; for (int y = 0; y < height; y++) { if (isStaggered) { xoffset -= 1; } for (int x = 0; x < width; x++) { var newY = y; var newX = x + xoffset; data[newX + newY * newWidth] = TileToGid(array.Get(x, y, 0), Orientation.hexagonal); } isStaggered = !isStaggered; } var layer = new TileLayer(); layer.Encoding = "base64"; layer.Data = data; layer.Width = newWidth; layer.Height = newHeight; layer.Visible = true; layer.Opacity = 1.0; return(layer); } else { throw new NotImplementedException($"{map.Orientation} not supported"); } }
public static ITopoArray <IEnumerable <V> > ExplodeSets <U, V>(ITopoArray <ISet <U> > topoArray, Func <U, ITopoArray <V> > getSubTile, int tileWidth, int tileHeight, int tileDepth) { if (topoArray.Topology.Directions.Type != DirectionsType.Cartesian2d && topoArray.Topology.Directions.Type != DirectionsType.Cartesian3d) { throw new NotImplementedException(); } var inTopology = topoArray.Topology; var inWidth = inTopology.Width; var inHeight = inTopology.Height; var inDepth = inTopology.Depth; var resultTopology = inTopology.WithSize( inWidth * tileWidth, inHeight * tileHeight, inDepth * tileDepth ); var result = new IEnumerable <V> [resultTopology.Width, resultTopology.Height, resultTopology.Depth]; var mask = new bool[resultTopology.Width * resultTopology.Height * resultTopology.Depth]; for (var z = 0; z < inDepth; z++) { for (var y = 0; y < inHeight; y++) { for (var x = 0; x < inWidth; x++) { if (inTopology.Mask != null) { var index = inTopology.GetIndex(x, y, z); if (!inTopology.Mask[index]) { continue; } } var inTileSet = topoArray.Get(x, y, z); if (inTileSet.Count == 0) { continue; } for (var tz = 0; tz < tileDepth; tz++) { for (var ty = 0; ty < tileHeight; ty++) { for (var tx = 0; tx < tileWidth; tx++) { var outSet = new List <V>(); foreach (var inTile in inTileSet) { var subTile = getSubTile(inTile); if (subTile == null) { continue; } if (subTile.Topology.Mask != null) { var index = subTile.Topology.GetIndex(tx, ty, tz); if (!subTile.Topology.Mask[index]) { continue; } } outSet.Add(subTile.Get(tx, ty, tz)); mask[resultTopology.GetIndex(x * tileWidth + tx, y * tileHeight + ty, z * tileDepth + tz)] = true; } result[x * tileWidth + tx, y *tileHeight + ty, z *tileDepth + tz] = outSet; } } } } } } return(TopoArray.Create(result, resultTopology)); }