Ejemplo n.º 1
0
        internal static FaceDir RotateBy(this FaceDir faceDir, Rotation r)
        {
            var f  = faceDir.Forward();
            var x1 = (int)f.x;
            var z1 = (int)f.z;

            var(x2, z2) = TopoArrayUtils.SquareRotateVector(x1, z1, r);
            if (x1 == x2 && z1 == z2)
            {
                return(faceDir);
            }
            if (x2 == 1)
            {
                return(FaceDir.Right);
            }
            if (x2 == -1)
            {
                return(FaceDir.Left);
            }
            if (z2 == 1)
            {
                return(FaceDir.Forward);
            }
            if (z2 == -1)
            {
                return(FaceDir.Back);
            }
            throw new System.Exception();
        }
Ejemplo n.º 2
0
 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));
             }
         }
     }
 }
Ejemplo n.º 3
0
        public void Init(TilePropagator propagator)
        {
            pathTileSet     = propagator.CreateTileSet(Exits.Keys);
            endPointTileSet = EndPointTiles != null?propagator.CreateTileSet(EndPointTiles) : null;

            graph = CreateEdgedGraph(propagator.Topology);

            var tileRotation = TileRotation ?? new TileRotation();

            actualExits = new Dictionary <Tile, ISet <Direction> >();
            foreach (var kv in Exits)
            {
                foreach (var rot in tileRotation.RotationGroup)
                {
                    if (tileRotation.Rotate(kv.Key, rot, out var rtile))
                    {
                        Direction Rotate(Direction d)
                        {
                            return(TopoArrayUtils.RotateDirection(propagator.Topology.Directions, d, rot));
                        }

                        var rexits = new HashSet <Direction>(kv.Value.Select(Rotate));
                        actualExits[rtile] = rexits;
                    }
                }
            }

            tilesByExit = actualExits
                          .SelectMany(kv => kv.Value.Select(e => Tuple.Create(kv.Key, e)))
                          .GroupBy(x => x.Item2, x => x.Item1)
                          .ToDictionary(g => g.Key, propagator.CreateTileSet);
        }
Ejemplo n.º 4
0
 public static AdjacentModel.Adjacency Rotate(AdjacentModel.Adjacency adjacency, Rotation rotation, DirectionSet directions, TileRotation tileRotation)
 {
     return(new AdjacentModel.Adjacency
     {
         Src = tileRotation.Rotate(adjacency.Src, rotation).ToArray(),
         Dest = tileRotation.Rotate(adjacency.Dest, rotation).ToArray(),
         Direction = TopoArrayUtils.RotateDirection(directions, adjacency.Direction, rotation),
     });
 }
Ejemplo n.º 5
0
        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);
            }
        }
Ejemplo n.º 6
0
        public void Init(TilePropagator propagator)
        {
            ISet <Tile> actualEndPointTiles;

            if (TileRotation != null)
            {
                actualExits = new Dictionary <Tile, ISet <Direction> >();
                foreach (var kv in Exits)
                {
                    foreach (var rot in TileRotation.RotationGroup)
                    {
                        if (TileRotation.Rotate(kv.Key, rot, out var rtile))
                        {
                            Direction Rotate(Direction d)
                            {
                                return(TopoArrayUtils.RotateDirection(propagator.Topology.AsGridTopology().Directions, d, rot));
                            }

                            var rexits = new HashSet <Direction>(kv.Value.Select(Rotate));
                            actualExits[rtile] = rexits;
                        }
                    }
                }
                actualEndPointTiles = EndPointTiles == null ? null : new HashSet <Tile>(TileRotation.RotateAll(EndPointTiles));
            }
            else
            {
                actualExits         = Exits;
                actualEndPointTiles = EndPointTiles;
            }

            pathTileSet         = propagator.CreateTileSet(Exits.Keys);
            pathSelectedTracker = propagator.CreateSelectedTracker(pathTileSet);
            endPointTileSet     = EndPointTiles != null?propagator.CreateTileSet(actualEndPointTiles) : null;

            endPointSelectedTracker = EndPointTiles != null?propagator.CreateSelectedTracker(endPointTileSet) : null;

            graph = CreateEdgedGraph(propagator.Topology);


            tilesByExit = actualExits
                          .SelectMany(kv => kv.Value.Select(e => Tuple.Create(kv.Key, e)))
                          .GroupBy(x => x.Item2, x => x.Item1)
                          .ToDictionary(g => g.Key, propagator.CreateTileSet);

            trackerByExit = tilesByExit
                            .ToDictionary(kv => kv.Key, kv => propagator.CreateSelectedTracker(kv.Value));

            Check(propagator, true);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Declares that the tiles in dest can be placed adjacent to the tiles in src, in the direction specified by (x, y, z).
        /// Then it adds similar declarations for other rotations and reflections, as specified by rotations.
        /// </summary>
        public void AddAdjacency(IList <Tile> src, IList <Tile> dest, int x, int y, int z, TileRotation tileRotation = null)
        {
            RequireDirections();

            tileRotation = tileRotation ?? new TileRotation();

            foreach (var rotation in tileRotation.RotationGroup)
            {
                var(x2, y2) = TopoArrayUtils.RotateVector(directions.Type, x, y, rotation);

                AddAdjacency(
                    tileRotation.Rotate(src, rotation).ToList(),
                    tileRotation.Rotate(dest, rotation).ToList(),
                    x2, y2, z);
            }
        }
Ejemplo n.º 8
0
        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));
                }
            }
        }
Ejemplo n.º 9
0
        private static ITopoArray <V> GetSubTile <V>(Tile tile, IDictionary <Tile, ITopoArray <V> > subTiles)
        {
            if (subTiles.TryGetValue(tile, out var result))
            {
                return(result);
            }

            if (tile.Value is RotatedTile rt)
            {
                if (!subTiles.TryGetValue(rt.Tile, out var subTile))
                {
                    return(null);
                }
                result = TopoArrayUtils.Rotate(subTile, rt.Rotation);
                return(subTiles[tile] = result);
            }

            return(null);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Declares that the tiles in dest can be placed adjacent to the tiles in src, in the direction specified by (x, y, z).
        /// Then it adds similar declarations for other rotations and reflections, as specified by rotations.
        /// </summary>
        public void AddAdjacency(IList <Tile> src, IList <Tile> dest, int x, int y, int z, TileRotation tileRotation = null)
        {
            tileRotation = tileRotation ?? new TileRotation();

            foreach (var rotation in tileRotation.RotationGroup)
            {
                int x2, y2;
                if (directions.Type == DirectionsType.Hexagonal2d)
                {
                    (x2, y2) = TopoArrayUtils.HexRotateVector(x, y, rotation);
                }
                else
                {
                    (x2, y2) = TopoArrayUtils.RotateVector(x, y, rotation);
                }

                AddAdjacency(
                    tileRotation.Rotate(src, rotation).ToList(),
                    tileRotation.Rotate(dest, rotation).ToList(),
                    x2, y2, z);
            }
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Declares that the tiles in dest can be placed adjacent to the tiles in src, in the direction specified by (x, y, z).
        /// Then it adds similar declarations for other rotations and reflections, as specified by rotations.
        /// </summary>
        public void AddAdjacency(IList <Tile> src, IList <Tile> dest, int x, int y, int z, int rotationalSymmetry, bool reflectionalSymmetry, TileRotation rotations = null)
        {
            rotations = rotations ?? new TileRotation();
            int totalRotationalSymmetry;

            if (directions.Type == DirectionsType.Hexagonal2d)
            {
                totalRotationalSymmetry = 6;
            }
            else
            {
                totalRotationalSymmetry = 4;
            }

            int reflections = reflectionalSymmetry ? 2 : 1;

            for (var r = 0; r < reflections; r++)
            {
                var reflectX = r > 0 ? true : false;
                for (var rotateCw = 0; rotateCw < totalRotationalSymmetry; rotateCw += (totalRotationalSymmetry / rotationalSymmetry))
                {
                    int x2, y2;
                    if (directions.Type == DirectionsType.Hexagonal2d)
                    {
                        (x2, y2) = TopoArrayUtils.HexRotateVector(x, y, rotateCw, reflectX);
                    }
                    else
                    {
                        (x2, y2) = TopoArrayUtils.RotateVector(x, y, rotateCw, reflectX);
                    }

                    AddAdjacency(
                        rotations.Rotate(src, rotateCw, reflectX).ToList(),
                        rotations.Rotate(dest, rotateCw, reflectX).ToList(),
                        x2, y2, z);
                }
            }
        }
Ejemplo n.º 12
0
        public void TestHexRotate()
        {
            var a = new int[2, 2];

            a[0, 0] = 1; a[1, 0] = 2;
            a[0, 1] = 3; a[1, 1] = 4;

            var ta = TopoArray.Create(a, new Topology(DirectionSet.Hexagonal2d, 2, 2, false, false));

            var r5 = TopoArrayUtils.HexRotate(ta, new Rotation(5 * 60, false));

            Assert.AreEqual(2, r5.Get(0, 0));
            Assert.AreEqual(1, r5.Get(0, 1)); Assert.AreEqual(4, r5.Get(1, 1));
            Assert.AreEqual(3, r5.Get(1, 2));

            var r1 = TopoArrayUtils.HexRotate(ta, new Rotation(1 * 60, false));

            Assert.AreEqual(3, r1.Get(0, 0)); Assert.AreEqual(1, r1.Get(1, 0));
            Assert.AreEqual(4, r1.Get(1, 1)); Assert.AreEqual(2, r1.Get(2, 1));

            var r2 = TopoArrayUtils.HexRotate(ta, new Rotation(2 * 60, false));

            Assert.AreEqual(3, r2.Get(0, 0));
            Assert.AreEqual(4, r2.Get(0, 1)); Assert.AreEqual(1, r2.Get(1, 1));
            Assert.AreEqual(2, r2.Get(1, 2));

            var r3 = TopoArrayUtils.HexRotate(ta, new Rotation(3 * 60, false));

            Assert.AreEqual(4, r3.Get(0, 0)); Assert.AreEqual(3, r3.Get(1, 0));
            Assert.AreEqual(2, r3.Get(0, 1)); Assert.AreEqual(1, r3.Get(1, 1));


            var refl = TopoArrayUtils.HexRotate(ta, new Rotation(0 * 60, true));

            Assert.AreEqual(2, refl.Get(0, 0)); Assert.AreEqual(1, refl.Get(1, 0));
            Assert.AreEqual(4, refl.Get(1, 1)); Assert.AreEqual(3, refl.Get(2, 1));
        }
Ejemplo n.º 13
0
        public void TestRotate()
        {
            var a = new int[2, 2];

            a[0, 0] = 1; a[1, 0] = 2;
            a[0, 1] = 3; a[1, 1] = 4;

            var ta = TopoArray.Create(a, new Topology(2, 2, false));

            var r1 = TopoArrayUtils.Rotate(ta, new Rotation(3 * 90));

            Assert.AreEqual(2, r1.Get(0, 0)); Assert.AreEqual(4, r1.Get(1, 0));
            Assert.AreEqual(1, r1.Get(0, 1)); Assert.AreEqual(3, r1.Get(1, 1));

            var r3 = TopoArrayUtils.Rotate(ta, new Rotation(1 * 90));

            Assert.AreEqual(3, r3.Get(0, 0)); Assert.AreEqual(1, r3.Get(1, 0));
            Assert.AreEqual(4, r3.Get(0, 1)); Assert.AreEqual(2, r3.Get(1, 1));

            var refl = TopoArrayUtils.Rotate(ta, new Rotation(0 * 90, true));

            Assert.AreEqual(2, refl.Get(0, 0)); Assert.AreEqual(1, refl.Get(1, 0));
            Assert.AreEqual(4, refl.Get(0, 1)); Assert.AreEqual(3, refl.Get(1, 1));
        }
Ejemplo n.º 14
0
        private static IList <AdjacentModel.Adjacency> GetAutoAdjacencies <T>(
            IDictionary <Tile, ITopoArray <T> > subTiles,
            GridTopology subTileTopology,
            TileRotation tileRotations,
            Func <T, T, double> diff,
            double tolerance)
        {
            // Pre-process for rotations
            var allSubTiles = subTiles;

            if (subTileTopology.Width == subTileTopology.Height)
            {
                allSubTiles = new Dictionary <Tile, ITopoArray <T> >();
                foreach (var kv in subTiles)
                {
                    foreach (var rot in tileRotations.RotationGroup)
                    {
                        if (tileRotations.Rotate(kv.Key, rot, out var rt) && !allSubTiles.ContainsKey(rt))
                        {
                            allSubTiles[rt] = TopoArrayUtils.Rotate(kv.Value, rot);
                        }
                    }
                }
            }


            var output = new List <AdjacentModel.Adjacency>();

            // Left-right
            {
                var leftSlices  = allSubTiles.ToDictionary(x => x.Key, x => SliceX(x.Value, 0));
                var rightSlices = allSubTiles.ToDictionary(x => x.Key, x => SliceX(x.Value, subTileTopology.Width - 1));

                foreach (var kv1 in leftSlices)
                {
                    foreach (var kv2 in rightSlices)
                    {
                        if (DiffSlice(kv1.Value, kv2.Value, diff) <= tolerance)
                        {
                            output.Add(new AdjacentModel.Adjacency
                            {
                                Src       = new[] { kv2.Key },
                                Dest      = new[] { kv1.Key },
                                Direction = Direction.XPlus
                            });
                        }
                    }
                }
            }

            //
            {
                var upSlices   = allSubTiles.ToDictionary(x => x.Key, x => SliceY(x.Value, 0));
                var downSlices = allSubTiles.ToDictionary(x => x.Key, x => SliceY(x.Value, subTileTopology.Height - 1));

                foreach (var kv1 in upSlices)
                {
                    foreach (var kv2 in downSlices)
                    {
                        if (DiffSlice(kv1.Value, kv2.Value, diff) <= tolerance)
                        {
                            output.Add(new AdjacentModel.Adjacency
                            {
                                Src       = new[] { kv2.Key },
                                Dest      = new[] { kv1.Key },
                                Direction = Direction.YPlus
                            });
                        }
                    }
                }
            }

            //
            if (subTileTopology.Directions.Type == DirectionSetType.Cartesian3d)
            {
                var aboveSlices = allSubTiles.ToDictionary(x => x.Key, x => SliceZ(x.Value, 0));
                var belowSlices = allSubTiles.ToDictionary(x => x.Key, x => SliceZ(x.Value, subTileTopology.Depth - 1));

                foreach (var kv1 in aboveSlices)
                {
                    foreach (var kv2 in belowSlices)
                    {
                        if (DiffSlice(kv1.Value, kv2.Value, diff) <= tolerance)
                        {
                            output.Add(new AdjacentModel.Adjacency
                            {
                                Src       = new[] { kv2.Key },
                                Dest      = new[] { kv1.Key },
                                Direction = Direction.ZPlus
                            });
                        }
                    }
                }
            }

            return(output);
        }
Ejemplo n.º 15
0
        public EdgedPathView(EdgedPathSpec spec, TilePropagator propagator)
        {
            if (spec.TileRotation != null)
            {
                exits = new Dictionary <Tile, ISet <Direction> >();
                foreach (var kv in spec.Exits)
                {
                    foreach (var rot in spec.TileRotation.RotationGroup)
                    {
                        if (spec.TileRotation.Rotate(kv.Key, rot, out var rtile))
                        {
                            Direction Rotate(Direction d)
                            {
                                return(TopoArrayUtils.RotateDirection(propagator.Topology.AsGridTopology().Directions, d, rot));
                            }

                            var rexits = new HashSet <Direction>(kv.Value.Select(Rotate));
                            exits[rtile] = rexits;
                        }
                    }
                }
                endPointTiles = spec.RelevantTiles == null ? null : new HashSet <Tile>(spec.TileRotation.RotateAll(spec.RelevantTiles));
            }
            else
            {
                exits         = spec.Exits;
                endPointTiles = spec.RelevantTiles;
            }

            pathTileSet         = propagator.CreateTileSet(exits.Keys);
            pathSelectedTracker = propagator.CreateSelectedTracker(pathTileSet);

            Graph           = CreateEdgedGraph(propagator.Topology);
            this.propagator = propagator;
            this.topology   = propagator.Topology;

            var nodesPerIndex = GetNodesPerIndex();

            CouldBePath = new bool[propagator.Topology.IndexCount * nodesPerIndex];
            MustBePath  = new bool[propagator.Topology.IndexCount * nodesPerIndex];

            tileSetByExit = exits
                            .SelectMany(kv => kv.Value.Select(e => Tuple.Create(kv.Key, e)))
                            .GroupBy(x => x.Item2, x => x.Item1)
                            .ToDictionary(g => g.Key, propagator.CreateTileSet);

            trackerByExit = tileSetByExit
                            .ToDictionary(kv => kv.Key, kv => propagator.CreateSelectedTracker(kv.Value));

            hasEndPoints = spec.RelevantCells != null || spec.RelevantTiles != null;

            if (hasEndPoints)
            {
                CouldBeRelevant = new bool[propagator.Topology.IndexCount * nodesPerIndex];
                MustBeRelevant  = new bool[propagator.Topology.IndexCount * nodesPerIndex];
                endPointIndices = spec.RelevantCells == null ? null :
                                  spec.RelevantCells.Select(p => propagator.Topology.GetIndex(p.X, p.Y, p.Z)).ToList();
                endPointTileSet = endPointTiles != null?propagator.CreateTileSet(endPointTiles) : null;

                endPointSelectedTracker = endPointTiles != null?propagator.CreateSelectedTracker(endPointTileSet) : null;
            }
            else
            {
                CouldBeRelevant = CouldBePath;
                MustBeRelevant  = MustBePath;
                endPointTileSet = pathTileSet;
            }
        }
Ejemplo n.º 16
0
 /// <summary>
 /// Rotates v about the y-axis by r.
 /// </summary>
 internal static Vector3Int Rotate(Rotation r, Vector3Int v)
 {
     (v.x, v.z) = TopoArrayUtils.SquareRotateVector(v.x, v.z, r);
     return(v);
 }