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(); } }
public static void Write(TilePropagator propagator) { var results = propagator.ToValueArray <int>(-1, -2).ToArray2d(); for (var y = 0; y < results.GetLength(1); y++) { for (var x = 0; x < results.GetLength(0); x++) { var r = results[x, y]; string c; switch (r) { case -1: c = "?"; break; case -2: c = "*"; break; case 0: c = " "; break; default: c = r.ToString(); break; } System.Console.Write(c); } System.Console.WriteLine(); } }
public void Export(TileModel model, TilePropagator tilePropagator, string filename, DeBroglieConfig config, ExportOptions exportOptions) { Vox vox; ITopoArray <byte> array; if (exportOptions is VoxExportOptions veo) { vox = veo.Template; array = tilePropagator.ToValueArray <byte>(); } else if (exportOptions is VoxSetExportOptions vseo) { vox = vseo.Template; var tileArray = tilePropagator.ToArray(); var subTiles = vseo.SubTiles.ToDictionary(x => x.Key, x => VoxUtils.ToTopoArray(x.Value)); array = MoreTopoArrayUtils.ExplodeTiles(tileArray, subTiles, vseo.TileWidth, vseo.TileHeight, vseo.TileDepth); } else { throw new System.Exception($"Cannot export from {exportOptions.TypeDescription} to .vox"); } VoxUtils.Save(vox, array); using (var stream = new FileStream(filename, FileMode.Create)) { var br = new BinaryWriter(stream); VoxSerializer.Write(br, vox); } }
public void TestPriority() { var t1 = new Tile(1); var t2 = new Tile(2); var t3 = new Tile(3); var model = new AdjacentModel(DirectionSet.Cartesian2d); model.AddAdjacency(t1, t1, Direction.XPlus); model.AddAdjacency(t1, t2, Direction.XPlus); model.AddAdjacency(t2, t2, Direction.XPlus); model.AddAdjacency(t2, t3, Direction.XPlus); model.AddAdjacency(t3, t3, Direction.XPlus); model.SetUniformFrequency(); var topology = new GridTopology(6, 1, false).WithMask(new bool[] { true, true, true, true, true, false }); IDictionary <Tile, PriorityAndWeight> weights = new Dictionary <Tile, PriorityAndWeight> { { t1, new PriorityAndWeight { Priority = 0, Weight = 1 } }, { t2, new PriorityAndWeight { Priority = 1, Weight = 1 } }, { t3, new PriorityAndWeight { Priority = 2, Weight = 1 } }, }; var weightsArray = TopoArray.CreateByIndex(_ => weights, topology); var propagator = new TilePropagator(model, topology, new TilePropagatorOptions { IndexPickerType = IndexPickerType.ArrayPriorityMinEntropy, WeightSetByIndex = TopoArray.CreateByIndex(_ => 0, topology), WeightSets = new Dictionary <int, IDictionary <Tile, PriorityAndWeight> > { { 0, weights } }, }); propagator.Select(0, 0, 0, t1); propagator.Run(); Assert.AreEqual(Resolution.Decided, propagator.Status); var r = propagator.ToValueArray <int>(); Assert.AreEqual(1, r.Get(0, 0)); Assert.AreEqual(2, r.Get(1, 0)); Assert.AreEqual(3, r.Get(2, 0)); Assert.AreEqual(3, r.Get(3, 0)); }
public void Export(TileModel model, TilePropagator propagator, string filename, DeBroglieConfig config, ExportOptions exportOptions) { if (config.Animate) { if (exportOptions is BitmapExportOptions) { var topoArray = propagator.ToWeightedArraySets().Map(WeightedColorAverage); var bitmap = BitmapUtils.ToBitmap(topoArray.ToArray2d()); bitmap.Save(filename); } else if (exportOptions is BitmapSetExportOptions bseo) { var topoArray = propagator.ToWeightedArraySets(); var tileTopology = topoArray.Topology.AsGridTopology().WithSize(bseo.TileWidth, bseo.TileHeight, 1); var subTiles = bseo.Bitmaps.ToDictionary(x => x.Key, x => TopoArray.Create(BitmapUtils.ToColorArray(x.Value), tileTopology).Map(c => new Tile(c))); var exploded = MoreTopoArrayUtils.ExplodeWeightedTiles(topoArray, subTiles, bseo.TileWidth, bseo.TileHeight, 1).Map(WeightedColorAverage); var bitmap = BitmapUtils.ToBitmap(exploded.ToArray2d()); bitmap.Save(filename); } else { throw new System.Exception($"Cannot export from {exportOptions.TypeDescription} to bitmap."); } } else { if (exportOptions is BitmapExportOptions) { var topoArray = propagator.ToValueArray(Rgba32.Gray, Rgba32.Magenta); var bitmap = BitmapUtils.ToBitmap(topoArray.ToArray2d()); bitmap.Save(filename); } else if (exportOptions is BitmapSetExportOptions bseo) { var undecided = new Tile(new object()); var contradiction = new Tile(new object()); var topoArray = propagator.ToArray(undecided, contradiction); var tileTopology = topoArray.Topology.AsGridTopology().WithSize(bseo.TileWidth, bseo.TileHeight, 1); var subTiles = bseo.Bitmaps.ToDictionary(x => x.Key, x => TopoArray.Create(BitmapUtils.ToColorArray(x.Value), tileTopology)); subTiles[undecided] = TopoArray.FromConstant(Rgba32.Gray, tileTopology); subTiles[contradiction] = TopoArray.FromConstant(Rgba32.Magenta, tileTopology); var exploded = MoreTopoArrayUtils.ExplodeTiles(topoArray, subTiles, bseo.TileWidth, bseo.TileHeight, 1); var bitmap = BitmapUtils.ToBitmap(exploded.ToArray2d()); bitmap.Save(filename); } else { throw new System.Exception($"Cannot export from {exportOptions.TypeDescription} to bitmap."); } } }
public void TestCountConstraint(CountComparison comparison, bool eager) { var model = new AdjacentModel(DirectionSet.Cartesian2d); var tile1 = new Tile(1); var tile2 = new Tile(2); var tiles = new[] { tile1, tile2 }; model.AddAdjacency(tiles, tiles, Direction.XPlus); model.AddAdjacency(tiles, tiles, Direction.YPlus); model.SetUniformFrequency(); var topology = new GridTopology(10, 10, false); var count = 3; var options = new TilePropagatorOptions { Constraints = new[] { new CountConstraint { Tiles = new[] { tile1 }.ToHashSet(), Count = count, Comparison = comparison, Eager = eager, } } }; var propagator = new TilePropagator(model, topology, options); propagator.Run(); Assert.AreEqual(Resolution.Decided, propagator.Status); var actualCount = propagator.ToValueArray <int>().ToArray2d().OfType <int>().Count(x => x == 1); switch (comparison) { case CountComparison.AtMost: Assert.LessOrEqual(actualCount, count); break; case CountComparison.AtLeast: Assert.GreaterOrEqual(actualCount, count); break; case CountComparison.Exactly: Assert.AreEqual(count, actualCount); break; } }
public void TestDoubleCountConstraint() { var model = new AdjacentModel(DirectionSet.Cartesian2d); var tile1 = new Tile(1); var tile2 = new Tile(2); var tile3 = new Tile(3); var tiles = new[] { tile1, tile2, tile3 }; model.AddAdjacency(new[] { tile2 }, new[] { tile1 }, Direction.XPlus); model.AddAdjacency(new[] { tile1 }, new[] { tile3 }, Direction.XPlus); model.AddAdjacency(new[] { tile3 }, new[] { tile3 }, Direction.XPlus); model.AddAdjacency(new[] { tile3 }, new[] { tile2 }, Direction.XPlus); model.AddAdjacency(tiles, tiles, Direction.YPlus); model.SetUniformFrequency(); var topology = new GridTopology(10, 10, false); var count = 10; var options = new TilePropagatorOptions { Constraints = new[] { new CountConstraint { Tiles = new[] { tile1, tile2 }.ToHashSet(), Count = count, Comparison = CountComparison.Exactly, Eager = true, } } }; var propagator = new TilePropagator(model, topology, options); propagator.Run(); Assert.AreEqual(Resolution.Decided, propagator.Status); var actualCount = propagator.ToValueArray <int>().ToArray2d().OfType <int>().Count(x => x == 1 || x == 2); Assert.AreEqual(count, actualCount); }
public void Path() { propagator5.Clear(); propagator5.Run(); Check(propagator5); if (false) { var v = propagator5.ToValueArray <string>(); for (var y = 0; y < v.Topology.Height; y++) { for (var x = 0; x < v.Topology.Width; x++) { System.Console.Write(v.Get(x, y)); } System.Console.WriteLine(); } } }
public void TestDirtyIndexPicker() { var t1 = new Tile(1); var t2 = new Tile(2); var t3 = new Tile(3); var model = new AdjacentModel(DirectionSet.Cartesian2d); model.AddAdjacency(t1, t1, Direction.XPlus); model.AddAdjacency(t1, t2, Direction.XPlus); model.AddAdjacency(t2, t2, Direction.XPlus); model.AddAdjacency(t2, t3, Direction.XPlus); model.AddAdjacency(t3, t3, Direction.XPlus); model.AddAdjacency(t3, t2, Direction.XPlus); model.AddAdjacency(t2, t1, Direction.XPlus); model.SetUniformFrequency(); var topology = new GridTopology(6, 1, false); var options = new TilePropagatorOptions { IndexPickerType = IndexPickerType.Dirty, TilePickerType = TilePickerType.Ordered, CleanTiles = TopoArray.FromConstant(t1, topology), }; var propagator = new TilePropagator(model, topology, options); propagator.Select(3, 0, 0, t3); propagator.Run(); var a = propagator.ToValueArray <int?>(); Assert.AreEqual(null, a.Get(0, 0)); Assert.AreEqual(null, a.Get(1, 0)); Assert.AreEqual(2, a.Get(2, 0)); Assert.AreEqual(3, a.Get(3, 0)); Assert.AreEqual(2, a.Get(4, 0)); Assert.AreEqual(null, a.Get(5, 0)); }
public void TestToTopArray() { var a = new int[, ] { { 1, 0 }, { 0, 1 }, }; var model = OverlappingModel.Create(a, 2, false, 8); var propagator = new TilePropagator(model, new GridTopology(4, 4, false)); propagator.Select(0, 0, 0, new Tile(1)); var status = propagator.Run(); Assert.AreEqual(Resolution.Decided, status); var result = propagator.ToValueArray <int>().ToArray2d(); Assert.AreEqual(4, result.GetLength(0)); Assert.AreEqual(4, result.GetLength(1)); Assert.AreEqual(1, result[0, 0]); Assert.AreEqual(1, result[3, 3]); }
public void TestBorderConstraint() { var a = new int[, ] { { 1, 0, 0 }, { 0, 1, 1 }, { 0, 1, 1 }, }; var model = AdjacentModel.Create(a, true); var propagator = new TilePropagator(model, new GridTopology(10, 10, false), true, constraints: new[] { new BorderConstraint { Tiles = new [] { new Tile(0) }, } }); var status = propagator.Run(); Assert.AreEqual(Resolution.Decided, status); var result = propagator.ToValueArray <int>().ToArray2d(); Assert.AreEqual(0, result[0, 0]); Assert.AreEqual(0, result[9, 0]); Assert.AreEqual(0, result[0, 9]); Assert.AreEqual(0, result[9, 9]); }
public void TestConnectedConstraintWithEdged() { var a = new int[, ] { { 0, 0, 0, 1, 0, 0 }, { 0, 0, 0, 1, 0, 0 }, { 0, 0, 0, 1, 0, 0 }, { 1, 1, 1, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 } }; var allDirections = DirectionSet.Cartesian2d.ToHashSet(); var exits = new Dictionary <Tile, ISet <Direction> >() { { new Tile(1), allDirections }, }; var seed = Environment.TickCount; var r = new Random(seed); Console.WriteLine("Seed {0}", seed); var model = OverlappingModel.Create(a, 3, false, 8); var constraint = new ConnectedConstraint { PathSpec = new EdgedPathSpec { Exits = exits, RelevantCells = new[] { new Point(0, 0), new Point(9, 9) }, } }; var propagator = new TilePropagator(model, new GridTopology(10, 10, false), new TilePropagatorOptions { BackTrackDepth = -1, Constraints = new[] { constraint }, RandomDouble = r.NextDouble }); var status = propagator.Run(); Assert.AreEqual(Resolution.Decided, status); var result = propagator.ToValueArray <int>().ToArray2d(); // Write out result for debugging for (var y = 0; y < 10; y++) { for (var x = 0; x < 10; x++) { Console.Write(result[x, y]); } Console.WriteLine(); } // Simple flood fill algorithm to determine we have in fact got a path var stack = new Stack <ValueTuple <int, int> >(); var visited = new bool[10, 10]; stack.Push((0, 0)); while (stack.TryPop(out var current)) { var(x, y) = current; if (x < 0 || x >= 10 || y < 0 || y >= 10) { continue; } if (visited[x, y]) { continue; } visited[x, y] = true; if (result[x, y] == 1) { if (x == 9 && y == 9) { return; } stack.Push((x + 1, y)); stack.Push((x - 1, y)); stack.Push((x, y + 1)); stack.Push((x, y - 1)); } } Assert.Fail(); }
public void TestPathConstraint() { var a = new int[, ] { { 0, 0, 0, 1, 0, 0 }, { 0, 0, 0, 1, 0, 0 }, { 0, 0, 0, 1, 0, 0 }, { 1, 1, 1, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 } }; var seed = Environment.TickCount; var r = new Random(seed); Console.WriteLine("Seed {0}", seed); var model = OverlappingModel.Create(a, 3, false, 8); var propagator = new TilePropagator(model, new Topology(10, 10, false), true, constraints: new[] { new PathConstraint(new HashSet <Tile> { new Tile(1) }, new [] { new Point(0, 0), new Point(9, 9) }) }, random: r); var status = propagator.Run(); Assert.AreEqual(Resolution.Decided, status); var result = propagator.ToValueArray <int>().ToArray2d(); // Write out result for debugging for (var y = 0; y < 10; y++) { for (var x = 0; x < 10; x++) { Console.Write(result[x, y]); } Console.WriteLine(); } // Simple flood fill algorithm to determine we have in fact got a path var stack = new Stack <ValueTuple <int, int> >(); var visited = new bool[10, 10]; stack.Push((0, 0)); while (stack.TryPop(out var current)) { var(x, y) = current; if (x < 0 || x >= 10 || y < 0 || y >= 10) { continue; } if (visited[x, y]) { continue; } visited[x, y] = true; if (result[x, y] == 1) { if (x == 9 && y == 9) { return; } stack.Push((x + 1, y)); stack.Push((x - 1, y)); stack.Push((x, y + 1)); stack.Push((x, y - 1)); } } Assert.Fail(); }
public void TestLoopConstraint() { var a = new int[, ] { { 0, 0, 0, 1, 0, 0 }, { 0, 0, 0, 1, 0, 0 }, { 0, 0, 0, 1, 0, 0 }, { 1, 1, 1, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 } }; var seed = Environment.TickCount; // TODO: This seed shows that this constraint can fail occasionally //seed = -1847040250; var r = new Random(seed); System.Console.WriteLine("Seed {0}", seed); var model = OverlappingModel.Create(a, 3, false, 8); var constraint = new LoopConstraint { PathSpec = new PathSpec { Tiles = new HashSet <Tile> { new Tile(1) }, } }; var topology = new GridTopology(10, 10, false); var propagator = new TilePropagator(model, topology, new TilePropagatorOptions { BacktrackType = BacktrackType.Backtrack, Constraints = new[] { constraint }, RandomDouble = r.NextDouble }); var status = propagator.Run(); Assert.AreEqual(Resolution.Decided, status); var result = propagator.ToValueArray <int>().ToArray2d(); // Write out result for debugging for (var y = 0; y < topology.Height; y++) { for (var x = 0; x < topology.Width; x++) { System.Console.Write(result[x, y]); } System.Console.WriteLine(); } // Every cell should have exactly 2 neighbours for (var y = 0; y < topology.Height; y++) { for (var x = 0; x < topology.Width; x++) { if (result[x, y] == 1) { var n = 0; if (x > 0) { n += result[x - 1, y]; } if (x < topology.Width - 1) { n += result[x + 1, y]; } if (y > 0) { n += result[x, y - 1]; } if (y < topology.Height - 1) { n += result[x, y + 1]; } Assert.AreEqual(2, n, $"At {x},{y}"); } } } }
public void TestGraphAdjacentModel() { // Define simple cube graph which unfolds and orients as follows // // ┌─┐ // │4│ // ┌─┼─┼─┬─┐ // │3│0│1│2│ // └─┼─┼─┴─┘ // │5│ // └─┘ // Neighbours (from top, clockwise) // 0: [4, 1, 5, 3] // 1: [4, 2, 5, 0] // 2: [4, 3, 5, 1] // 3: [4, 0, 5, 2] // 4: [2, 1, 0, 3] // 5: [0, 1, 2, 3] var meshBuilder = new MeshTopologyBuilder(DirectionSet.Cartesian2d); meshBuilder.Add(0, 1, Direction.XPlus); meshBuilder.Add(0, 3, Direction.XMinus); meshBuilder.Add(0, 5, Direction.YPlus); meshBuilder.Add(0, 4, Direction.YMinus); meshBuilder.Add(1, 2, Direction.XPlus); meshBuilder.Add(1, 0, Direction.XMinus); meshBuilder.Add(1, 5, Direction.YPlus); meshBuilder.Add(1, 4, Direction.YMinus); meshBuilder.Add(2, 3, Direction.XPlus); meshBuilder.Add(2, 1, Direction.XMinus); meshBuilder.Add(2, 5, Direction.YPlus); meshBuilder.Add(2, 4, Direction.YMinus); meshBuilder.Add(3, 0, Direction.XPlus); meshBuilder.Add(3, 2, Direction.XMinus); meshBuilder.Add(3, 5, Direction.YPlus); meshBuilder.Add(3, 4, Direction.YMinus); meshBuilder.Add(4, 1, Direction.XPlus); meshBuilder.Add(4, 3, Direction.XMinus); meshBuilder.Add(4, 0, Direction.YPlus); meshBuilder.Add(4, 2, Direction.YMinus); meshBuilder.Add(5, 1, Direction.XPlus); meshBuilder.Add(5, 3, Direction.XMinus); meshBuilder.Add(5, 2, Direction.YPlus); meshBuilder.Add(5, 0, Direction.YMinus); var topology = meshBuilder.GetTopology(); var model = new GraphAdjacentModel(meshBuilder.GetInfo()); var empty = new Tile(" "); var straight1 = new Tile("║"); var straight2 = new Tile("═"); var corner1 = new Tile("╚"); var corner2 = new Tile("╔"); var corner3 = new Tile("╗"); var corner4 = new Tile("╝"); var tileRotationBuilder = new TileRotationBuilder(4, true, TileRotationTreatment.Missing); tileRotationBuilder.AddSymmetry(empty, TileSymmetry.X); tileRotationBuilder.AddSymmetry(straight1, TileSymmetry.I); tileRotationBuilder.AddSymmetry(straight2, TileSymmetry.I); tileRotationBuilder.AddSymmetry(corner1, TileSymmetry.L); tileRotationBuilder.AddSymmetry(corner2, TileSymmetry.Q); tileRotationBuilder.AddSymmetry(corner3, TileSymmetry.L); tileRotationBuilder.AddSymmetry(corner4, TileSymmetry.Q); tileRotationBuilder.Add(straight1, new Rotation(90), straight2); tileRotationBuilder.Add(corner1, new Rotation(90), corner2); tileRotationBuilder.Add(corner2, new Rotation(90), corner3); tileRotationBuilder.Add(corner3, new Rotation(90), corner4); tileRotationBuilder.Add(corner4, new Rotation(90), corner1); var tileRotation = tileRotationBuilder.Build(); model.AddAdjacency( new[] { empty, straight1, corner3, corner4 }, new[] { empty, straight1, corner1, corner2 }, Direction.XPlus, tileRotation); model.AddAdjacency( new[] { straight2, corner1, corner2 }, new[] { straight2, corner3, corner4 }, Direction.XPlus, tileRotation); model.AddAdjacency( new[] { empty, straight2, corner1, corner4 }, new[] { empty, straight2, corner2, corner3 }, Direction.YPlus, tileRotation); model.AddAdjacency( new[] { straight1, corner2, corner3 }, new[] { straight1, corner1, corner4 }, Direction.YPlus, tileRotation); model.SetUniformFrequency(); var propagator = new TilePropagator(model, topology, new TilePropagatorOptions { BackTrackDepth = -1, }); void PrintPropagator() { var a = propagator.ToValueArray("?", "!"); var str = @" ┌─┐ │4│ ┌─┼─┼─┬─┐ │3│0│1│2│ └─┼─┼─┴─┘ │5│ └─┘"; for (var i = 0; i < 6; i++) { str = str.Replace(i.ToString(), (string)a.Get(i)); } System.Console.Write(str); } propagator.Run(); PrintPropagator(); Assert.AreEqual(Resolution.Decided, propagator.Status); }
public void Export(TileModel model, TilePropagator propagator, string filename, DeBroglieConfig config, ExportOptions exportOptions) { if (config.Animate) { if (exportOptions is BitmapExportOptions) { var topoArray = propagator.ToValueSets <Rgba32>().Map(BitmapUtils.ColorAverage); var bitmap = BitmapUtils.ToBitmap(topoArray.ToArray2d()); bitmap.Save(filename); } else if (exportOptions is BitmapSetExportOptions bseo) { var topoArray = propagator.ToArraySets(); var tileTopology = topoArray.Topology.AsGridTopology().WithSize(bseo.TileWidth, bseo.TileHeight, 1); var subTiles = bseo.Bitmaps.ToDictionary(x => x.Key, x => TopoArray.Create(BitmapUtils.ToColorArray(x.Value), tileTopology)); var exploded = MoreTopoArrayUtils.ExplodeTileSets(topoArray, subTiles, bseo.TileWidth, bseo.TileHeight, 1).Map(BitmapUtils.ColorAverage); var bitmap = BitmapUtils.ToBitmap(exploded.ToArray2d()); bitmap.Save(filename); } else { throw new System.Exception($"Cannot export from {exportOptions.TypeDescription} to bitmap."); } } else { if (exportOptions is BitmapExportOptions) { var topoArray = propagator.ToValueArray(Rgba32.Gray, Rgba32.Magenta); var bitmap = BitmapUtils.ToBitmap(topoArray.ToArray2d()); var index = 0; var noExtension = Path.GetFileNameWithoutExtension(filename); var justExtension = Path.GetExtension(filename); var pathNoFile = Path.GetDirectoryName(filename); var seqFilename = ""; do { seqFilename = pathNoFile + Path.DirectorySeparatorChar + noExtension + (index == 0 ? "" : index.ToString()) + justExtension; index++; } while (File.Exists(seqFilename)); bitmap.Save(seqFilename); } else if (exportOptions is BitmapSetExportOptions bseo) { var undecided = new Tile(new object()); var contradiction = new Tile(new object()); var topoArray = propagator.ToArray(undecided, contradiction); var tileTopology = topoArray.Topology.AsGridTopology().WithSize(bseo.TileWidth, bseo.TileHeight, 1); var subTiles = bseo.Bitmaps.ToDictionary(x => x.Key, x => TopoArray.Create(BitmapUtils.ToColorArray(x.Value), tileTopology)); subTiles[undecided] = TopoArray.FromConstant(Rgba32.Gray, tileTopology); subTiles[contradiction] = TopoArray.FromConstant(Rgba32.Magenta, tileTopology); var exploded = MoreTopoArrayUtils.ExplodeTiles(topoArray, subTiles, bseo.TileWidth, bseo.TileHeight, 1); var bitmap = BitmapUtils.ToBitmap(exploded.ToArray2d()); bitmap.Save(filename); } else { throw new System.Exception($"Cannot export from {exportOptions.TypeDescription} to bitmap."); } } }
public void TestAcyclicConstraint() { var a = new int[, ] { { 0, 0, 0, 1, 0, 0 }, { 0, 0, 0, 1, 0, 0 }, { 0, 0, 0, 1, 0, 0 }, { 1, 1, 1, 1, 0, 0 }, { 0, 1, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 0 } }; var seed = Environment.TickCount; var r = new Random(seed); Console.WriteLine("Seed {0}", seed); var model = OverlappingModel.Create(a, 3, false, 8); var topology = new GridTopology(10, 10, false); /* * var pathSpec = new PathSpec * { * Tiles = new HashSet<Tile> { new Tile(1) }, * }; */ var pathSpec = new EdgedPathSpec { Exits = new Dictionary <Tile, ISet <Direction> > { { new Tile(1), topology.Directions.ToHashSet() } }, }; var constraint = new AcyclicConstraint { PathSpec = pathSpec, }; var propagator = new TilePropagator(model, topology, new TilePropagatorOptions { BackTrackDepth = -1, Constraints = new[] { constraint }, RandomDouble = r.NextDouble }); var status = propagator.Run(); Assert.AreEqual(Resolution.Decided, status); var result = propagator.ToValueArray <int>().ToArray2d(); // Write out result for debugging for (var y = 0; y < topology.Height; y++) { for (var x = 0; x < topology.Width; x++) { Console.Write(result[x, y]); } Console.WriteLine(); } var visited = new bool[topology.Width, topology.Height]; for (var y = 0; y < topology.Height; y++) { for (var x = 0; x < topology.Width; x++) { if (result[x, y] != 1) { continue; } if (visited[x, y]) { continue; } void Visit(int x2, int y2, int dir) { if (x2 < 0 || x2 >= topology.Width || y2 < 0 || y2 >= topology.Height) { return; } if (result[x2, y2] != 1) { return; } if (visited[x2, y2]) { Assert.Fail(); } visited[x2, y2] = true; if (dir != 0) { Visit(x2 - 1, y2, 2); } if (dir != 2) { Visit(x2 + 1, y2, 0); } if (dir != 1) { Visit(x2, y2 - 1, 3); } if (dir != 3) { Visit(x2, y2 + 1, 1); } } Visit(x, y, -1); } } }