/// <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); } } }
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); }
/// <summary> /// Scales the the occurency frequency of a given tile by the given multiplier, /// including other rotations of the tile. /// </summary> public virtual void MultiplyFrequency(Tile tile, double multiplier, TileRotation tileRotation) { var rotatedTiles = new HashSet <Tile>(); foreach (var rotation in tileRotation.RotationGroup) { if (tileRotation.Rotate(tile, rotation, out var result)) { if (rotatedTiles.Add(result)) { MultiplyFrequency(result, multiplier); } } } }
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); }