예제 #1
0
        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();
            }
        }
예제 #2
0
        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();
            }
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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));
        }
예제 #5
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.");
                }
            }
        }
예제 #6
0
        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;
            }
        }
예제 #7
0
        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);
        }
예제 #8
0
        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();
                }
            }
        }
예제 #9
0
        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));
        }
예제 #10
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]);
        }
예제 #11
0
        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();
        }
예제 #13
0
        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();
        }
예제 #14
0
        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}");
                    }
                }
            }
        }
예제 #15
0
        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);
        }
예제 #16
0
        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.");
                }
            }
        }
예제 #17
0
        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);
                }
            }
        }