public void CountSetup() { 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(100, 100, false); var count = 30; var options = new TilePropagatorOptions { Constraints = new[] { new CountConstraint { Tiles = new[] { tile1 }.ToHashSet(), Count = count, Comparison = CountComparison.AtMost, Eager = false, } } }; propagator6 = new TilePropagator(model, topology, options); }
public void TestLargeSeparationConstraint() { 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 separationConstraint = new SeparationConstraint { Tiles = new[] { tile1 }.ToHashSet(), MinDistance = 10, }; var topology = new GridTopology(100, 100, false); var options = new TilePropagatorOptions { Constraints = new ITileConstraint[] { separationConstraint }, BacktrackType = BacktrackType.Backtrack, }; var propagator = new TilePropagator(model, topology, options); propagator.Run(); Assert.AreEqual(Resolution.Decided, propagator.Status); var r = propagator.ToArray(); for (var x = 0; x < 100; x++) { for (var y = 0; y < 100; y++) { if (r.Get(x, y) != tile1) { continue; } for (var dx = -1; dx <= 1; dx += 2) { for (var dy = -1; dy <= 1; dy += 2) { var x2 = x + dx; var y2 = y + dy; if (x2 >= 0 && x2 < 100 && y2 >= 0 && y2 < 100) { Assert.AreNotEqual(r.Get(x2, y2), tile1); } } } } } }
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 WangSetup() { // Reproduces the wang tiles found at // https://en.wikipedia.org/wiki/Wang_tile // They only have aperiodic tiling, so they are a hard set to put down. // Clockwise from top var tileBorders = new[] { "rrrg", "brbg", "rggg", "wbrb", "bbwb", "wwrw", "rgbw", "bwbr", "brwr", "ggbr", "rwrg", }; var model = new AdjacentModel(DirectionSet.Cartesian2d); for (var tile1 = 0; tile1 < tileBorders.Length; tile1++) { var tile1Border = tileBorders[tile1]; for (var i = 0; i < 4; i++) { var d = new[] { 3, 0, 2, 1 }[i]; var o = (i + 2) % 4; for (var tile2 = 0; tile2 < tileBorders.Length; tile2++) { var tile2Border = tileBorders[tile2]; if (tile2Border[o] != tile1Border[i]) { continue; } model.AddAdjacency(new Tile(tile1), new Tile(tile2), (Direction)d); } } } model.SetUniformFrequency(); var topology = new GridTopology(15, 15, false); var options = new TilePropagatorOptions { BackTrackDepth = -1, }; propagatorWang = new TilePropagator(model, topology, options); }
public void MirrorSetup() { var trb = new TileRotationBuilder(4, true, TileRotationTreatment.Missing); var tile1 = new Tile(1); var tile2 = new Tile(2); var tile3 = new Tile(3); var tile4 = new Tile(4); var tile5 = new Tile(5); var tiles = new[] { tile1, tile2, tile3, tile4 }; var reflectX = new Rotation(0, true); trb.Add(tile1, reflectX, tile2); trb.Add(tile3, reflectX, tile3); trb.Add(tile5, reflectX, tile5); var model = new AdjacentModel(DirectionSet.Cartesian2d); model.AddAdjacency(tiles, tiles, Direction.XPlus); model.AddAdjacency(new[] { tile5 }, tiles, Direction.XPlus); model.AddAdjacency(new[] { tile5 }, tiles, Direction.XMinus); model.AddAdjacency(tiles, tiles, Direction.YPlus); model.SetUniformFrequency(); model.SetFrequency(tile5, 0.0); var tr = trb.Build(); var constraints = new[] { new MirrorXConstraint { TileRotation = tr } }; // NB: It's important that width is an odd number var topology = new GridTopology(31, 31, false); var options = new TilePropagatorOptions { Constraints = constraints, }; propagator7 = new TilePropagator(model, topology, options); }
public void TestParityConstraint() { var w = 10; var h = 10; var topology = new GridTopology(10, 10, false); var pathModel = new PathModel(forks: false); var constraint = new ParityConstraint { PathSpec = new EdgedPathSpec { Exits = pathModel.Exits }, }; var options = new TilePropagatorOptions { BackTrackDepth = -1, Constraints = new[] { constraint }, }; var propagator = new TilePropagator(pathModel.Model, topology, options); for (var x = 0; x < w; x++) { for (var y = 0; y < h; y++) { void Select(Tile t) => propagator.Select(x, y, 0, t); if (x == 0 && y == 1) { Select(pathModel.Straight2); continue; } if (x == 0 || y == 0 || x == w - 1 || y == h - 1) { Select(pathModel.Empty); } } } propagator.Step(); Assert.AreEqual(Resolution.Contradiction, propagator.Status); }
public void TestSeparationConstraint() { 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 separationConstraint = new SeparationConstraint { Tiles = new[] { tile1 }.ToHashSet(), MinDistance = 3, }; var countConstraint = new CountConstraint { Tiles = new[] { tile1 }.ToHashSet(), Count = 2, Comparison = CountComparison.Exactly, }; var topology = new GridTopology(4, 1, false); var options = new TilePropagatorOptions { Constraints = new ITileConstraint[] { separationConstraint, countConstraint }, BacktrackType = BacktrackType.Backtrack, }; var propagator = new TilePropagator(model, topology, options); propagator.Run(); Assert.AreEqual(Resolution.Decided, propagator.Status); var r = propagator.ToArray(); // Only possible solution given the constraints Assert.AreEqual(tile1, r.Get(0)); Assert.AreEqual(tile2, r.Get(1)); Assert.AreEqual(tile2, r.Get(2)); Assert.AreEqual(tile1, r.Get(3)); }
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 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 TestUnassignableEager() { 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(3, 1, false); var count = 3; var options = new TilePropagatorOptions { Constraints = new[] { new CountConstraint { Tiles = new[] { tile1, }.ToHashSet(), Count = count, Comparison = CountComparison.Exactly, Eager = true, } } }; var propagator = new TilePropagator(model, topology, options); propagator.Select(1, 0, 0, tile2); propagator.Run(); Assert.AreEqual(Resolution.Contradiction, propagator.Status); }