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); }
public WeightSetCollection(ITopoArray <int> weightSetByIndex, IDictionary <int, IDictionary <Tile, PriorityAndWeight> > weightSets, TileModelMapping tileModelMapping) { this.weightSetByIndex = weightSetByIndex; this.weightSets = weightSets; this.tileModelMapping = tileModelMapping; frequencySets = new Dictionary <int, FrequencySet>(); }
/// <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)); }
public void QuickStartTest() { ITopoArray <char> sample = TopoArray.Create(new[, ] { { '_', '_', '_' }, { '_', '*', '_' }, { '_', '_', '_' }, }, periodic: false); // Specify the model used for generation var model = new AdjacentModel(sample.ToTiles()); // Set the output dimensions var topology = new Topology(10, 10, periodic: false); // Actually run the algorithm var propagator = new TilePropagator(model, topology); var status = propagator.Run(); if (status != Resolution.Decided) { throw new Exception("Undecided"); } var output = propagator.ToValueArray <char>(); // Display the results for (var y = 0; y < 10; y++) { for (var x = 0; x < 10; x++) { System.Console.Write(output.Get(x, y)); } System.Console.WriteLine(); } }
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 AddSample(ITopoArray <Tile> sample, int rotationalSymmetry, bool reflectionalSymmetry, TileRotation tileRotation = null) { foreach (var s in OverlappingAnalysis.GetRotatedSamples(sample, rotationalSymmetry, reflectionalSymmetry, tileRotation)) { AddSample(s); } }
public static IEnumerable <ITopoArray <Tile> > GetRotatedSamples( ITopoArray <Tile> sample, int rotationalSymmetry, bool reflectionalSymmetry, TileRotation tileRotation = null) { if (sample.Topology.Directions.Type == DirectionsType.Hexagonal2d) { var reflections = reflectionalSymmetry ? 2 : 1; for (var r = 0; r < reflections; r++) { for (var i = 0; i < 6; i += (6 / rotationalSymmetry)) { yield return(TopoArrayUtils.HexRotate(sample, i, r > 0, tileRotation)); } } } else { var reflections = reflectionalSymmetry ? 2 : 1; for (var r = 0; r < reflections; r++) { for (var i = 0; i < 4; i += (4 / rotationalSymmetry)) { yield return(TopoArrayUtils.Rotate(sample, i, r > 0, tileRotation)); } } } }
public SampleSet Load(string filename) { var srcFilename = filename; // Hack for tsx files. Should handle this more properly in future var tileset = TiledUtil.LoadTileset(filename); tileset.FirstGid = 1; var map = new Map { CellWidth = tileset.TileWidth, CellHeight = tileset.TileHeight, Tilesets = new[] { tileset }, TiledVersion = "1.1.6", RenderOrder = RenderOrder.rightdown, }; var tilesByName = new Dictionary <string, Tile>(); TiledMapImporter.AddTileset(tilesByName, tileset); // TODO: Other directions var directions = DirectionSet.Cartesian2d; map.Orientation = Orientation.orthogonal; var samples = new ITopoArray <Tile> [0]; return(new SampleSet { Directions = directions, Samples = samples, TilesByName = tilesByName, ExportOptions = new TiledExportOptions { Template = map, SrcFileName = srcFilename, }, }); }
public void AddSample(ITopoArray <Tile> sample, TileRotation tileRotation = null) { foreach (var s in OverlappingAnalysis.GetRotatedSamples(sample, tileRotation)) { AddSample(s); } }
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); }
public static ITopoArray <Tile> HexRotate(ITopoArray <Tile> original, Rotation rotation, TileRotation tileRotation = null) { bool TileRotate(Tile tile, out Tile result) { return(tileRotation.Rotate(tile, rotation, out result)); } return(HexRotate <Tile>(original, rotation, tileRotation == null ? null : (TileRotate <Tile>)TileRotate)); }
public static ITopoArray <Tile> HexRotate(ITopoArray <Tile> original, int rotate, bool reflectX = false, TileRotation tileRotation = null) { bool TileRotate(Tile tile, out Tile result) { return(tileRotation.Rotate(tile, rotate, reflectX, out result)); } return(HexRotate <Tile>(original, rotate, reflectX, tileRotation == null ? null : (TileRotate <Tile>)TileRotate)); }
public static IEnumerable<ITopoArray<Tile>> GetRotatedSamples( ITopoArray<Tile> sample, TileRotation tileRotation = null) { tileRotation = tileRotation ?? new TileRotation(); foreach (var rotation in tileRotation.RotationGroup) { yield return TopoArrayUtils.Rotate(sample, rotation, tileRotation); } }
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)); }
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)); }
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)); }
/// <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); } } } } }
public void AddSample(ITopoArray <Tile> sample, TileRotation tileRotation = null) { if (sample.Topology.Depth == 1) { nz = 1; } var topology = sample.Topology.AsGridTopology(); var periodicX = topology.PeriodicX; var periodicY = topology.PeriodicY; var periodicZ = topology.PeriodicZ; foreach (var s in OverlappingAnalysis.GetRotatedSamples(sample, tileRotation)) { OverlappingAnalysis.GetPatterns(s, nx, ny, nz, periodicX, periodicY, periodicZ, patternIndices, patternArrays, frequencies); } // Update the model based on the collected data var directions = topology.Directions; // TODO: Don't regenerate this from scratch every time propagator = new List <HashSet <int>[]>(patternArrays.Count); for (var p = 0; p < patternArrays.Count; p++) { propagator.Add(new HashSet <int> [directions.Count]); for (var d = 0; d < directions.Count; d++) { var l = new HashSet <int>(); for (var p2 = 0; p2 < patternArrays.Count; p2++) { var dx = directions.DX[d]; var dy = directions.DY[d]; var dz = directions.DZ[d]; if (Aggrees(patternArrays[p], patternArrays[p2], dx, dy, dz)) { l.Add(p2); } } propagator[p][d] = l; } } patternsToTiles = patternArrays .Select((x, i) => new KeyValuePair <int, Tile>(i, x.Values[0, 0, 0])) .ToDictionary(x => x.Key, x => x.Value); tilesToPatterns = patternsToTiles.ToLookup(x => x.Value, x => x.Key); }
/// <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); }
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); }
public static void Save(Vox vox, ITopoArray <byte> topArray) { Size size = null; foreach (var chunk in vox.Chunks) { if (chunk is Size) { size = (Size)chunk; } else if (chunk is Xyzi xyzi) { Save(size, xyzi, topArray); return; } } }
public static void GetPatterns( ITopoArray <Tile> sample, int nx, int ny, int nz, bool periodicX, bool periodicY, bool periodicZ, Dictionary <PatternArray, int> patternIndices, List <PatternArray> patternArrays, List <double> frequencies) { var width = sample.Topology.Width; var height = sample.Topology.Height; var depth = sample.Topology.Depth; var maxx = periodicX ? width - 1 : width - nx; var maxy = periodicY ? height - 1 : height - ny; var maxz = periodicZ ? depth - 1 : depth - nz; for (var x = 0; x <= maxx; x++) { for (var y = 0; y <= maxy; y++) { for (var z = 0; z <= maxz; z++) { PatternArray patternArray; if (!TryExtract(sample, nx, ny, nz, x, y, z, out patternArray)) { continue; } int pattern; if (!patternIndices.TryGetValue(patternArray, out pattern)) { pattern = patternIndices[patternArray] = patternIndices.Count; patternArrays.Add(patternArray); frequencies.Add(1); } else { frequencies[pattern] += 1; } } } } }
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}"); } }
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 IEnumerable <ITopoArray <Tile> > GetRotatedSamples( ITopoArray <Tile> sample, TileRotation tileRotation = null) { tileRotation = tileRotation ?? new TileRotation(); foreach (var rotation in tileRotation.RotationGroup) { if (sample.Topology.Directions.Type == DirectionsType.Hexagonal2d) { yield return(TopoArrayUtils.HexRotate(sample, rotation, tileRotation)); } else { yield return(TopoArrayUtils.Rotate(sample, rotation, tileRotation)); } } }
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)); }
/// <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); }