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)); } } } }
public void AddSample(ITopoArray <Tile> sample, TileRotation tileRotation = null) { foreach (var s in OverlappingAnalysis.GetRotatedSamples(sample, tileRotation)) { AddSample(s); } }
private void SetupAdjacencies(TileModel model, TileRotation tileRotation, IList <AdjacentModel.Adjacency> adjacencies) { if (Config.PadTile != null) { adjacencies = AdjacencyUtils.ForcePadding(adjacencies, Parse(Config.PadTile)); } if (adjacencies.Count > 0) { var adjacentModel = model as AdjacentModel; if (adjacentModel == null) { throw new ConfigurationException("Setting adjacencies is only supported for the \"adjacent\" model."); } foreach (var a in adjacencies) { adjacentModel.AddAdjacency(a); } // If there are no samples, set frequency to 1 for everything mentioned in this block foreach (var tile in adjacentModel.Tiles.ToList()) { adjacentModel.SetFrequency(tile, 1, tileRotation); } } }
/// <summary> /// Finds a tile and all its rotations, and sets their total frequency. /// </summary> public void SetFrequency(Tile tile, double frequency, TileRotation tileRotation) { var rotatedTiles = new List <Tile>(); foreach (var rotation in tileRotation.RotationGroup) { if (tileRotation.Rotate(tile, rotation, out var result)) { // Note this deliberatly can count tiles twice rotatedTiles.Add(result); } } foreach (var rt in rotatedTiles) { int pattern = GetPattern(rt); frequencies[pattern] = 0.0; } var incrementalFrequency = frequency / rotatedTiles.Count; foreach (var rt in rotatedTiles) { int pattern = GetPattern(rt); frequencies[pattern] += incrementalFrequency; } }
/// <summary> /// Basiskonstruktor. /// </summary> public Tile() { Rotation = TileRotation.None; TileSheetRectangle = Rectangle.Empty; Shape = new AABBShape(); Body = new Body(); ID = IDManager.Instance.TileID; }
public Tile(TileRotation rotate = TileRotation.NONE) { Image = ImageProvider.Instance.GetImage(GetImageName()); Rotation = rotate; Width = Image.Width; Height = Image.Height; Fields = new Collection<Field>(); Init(); }
/// <summary> /// Declares that the tiles in dest can be placed adjacent to the tiles in src, in the direction specified. /// Then it adds similar declarations for other rotations and reflections, as specified by rotations. /// </summary> public void AddAdjacency(IList <Tile> src, IList <Tile> dest, Direction dir, TileRotation tileRotation = null) { RequireDirections(); var d = (int)dir; var x = directions.DX[d]; var y = directions.DY[d]; var z = directions.DZ[d]; AddAdjacency(src, dest, x, y, z, tileRotation); }
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); } }
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); }
public void AddSample(ITopoArray <Tile> sample, TileRotation tileRotation = null) { if (sample.Topology.Depth == 1) { nz = 1; } var topology = sample.Topology.AsGridTopology(); var periodicX = topology.PeriodicX; var periodicY = topology.PeriodicY; var periodicZ = topology.PeriodicZ; foreach (var s in OverlappingAnalysis.GetRotatedSamples(sample, tileRotation)) { OverlappingAnalysis.GetPatterns(s, nx, ny, nz, periodicX, periodicY, periodicZ, patternIndices, patternArrays, frequencies); } // Update the model based on the collected data var directions = topology.Directions; // TODO: Don't regenerate this from scratch every time propagator = new List <HashSet <int>[]>(patternArrays.Count); for (var p = 0; p < patternArrays.Count; p++) { propagator.Add(new HashSet <int> [directions.Count]); for (var d = 0; d < directions.Count; d++) { var l = new HashSet <int>(); for (var p2 = 0; p2 < patternArrays.Count; p2++) { var dx = directions.DX[d]; var dy = directions.DY[d]; var dz = directions.DZ[d]; if (Aggrees(patternArrays[p], patternArrays[p2], dx, dy, dz)) { l.Add(p2); } } propagator[p][d] = l; } } patternsToTiles = patternArrays .Select((x, i) => new KeyValuePair <int, Tile>(i, x.Values[0, 0, 0])) .ToDictionary(x => x.Key, x => x.Value); tilesToPatterns = patternsToTiles.ToLookup(x => x.Value, x => x.Key); }
/// <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); } } } }
/// <summary> /// Finds a tile and all its rotations, and sets their total frequency. /// </summary> public void SetFrequency(Tile tile, double frequency, TileRotation tileRotation) { var rotatedTiles = tileRotation.RotateAll(tile).ToList(); foreach (var rt in rotatedTiles) { int pattern = GetPattern(rt); frequencies[pattern] = 0.0; } var incrementalFrequency = frequency / rotatedTiles.Count; foreach (var rt in rotatedTiles) { int pattern = GetPattern(rt); frequencies[pattern] += incrementalFrequency; } }
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)); } } }
public void AddSample(ITopoArray <Tile> sample, TileRotation tileRotation = null) { if (sample.Topology.Depth == 1) { nz = 1; } var topology = sample.Topology.AsGridTopology(); var periodicX = topology.PeriodicX; var periodicY = topology.PeriodicY; var periodicZ = topology.PeriodicZ; foreach (var s in OverlappingAnalysis.GetRotatedSamples(sample, tileRotation)) { OverlappingAnalysis.GetPatterns(s, nx, ny, nz, periodicX, periodicY, periodicZ, patternIndices, patternArrays, frequencies); } sampleTopologyDirections = topology.Directions; propagator = null;// Mark as dirty }
public TileModel GetModel(DirectionSet directions, SampleSet sampleSet, TileRotation tileRotation) { var samples = sampleSet.Samples; var modelConfig = Config.Model ?? new Adjacent(); TileModel tileModel; if (modelConfig is Overlapping overlapping) { var model = new OverlappingModel(overlapping.NX, overlapping.NY, overlapping.NZ); foreach (var sample in samples) { model.AddSample(sample, tileRotation); } tileModel = model; } else if (modelConfig is Adjacent adjacent) { var model = new AdjacentModel(directions); foreach (var sample in samples) { model.AddSample(sample, tileRotation); } tileModel = model; } else { throw new ConfigurationException($"Unrecognized model type {modelConfig.GetType()}"); } var autoAdjacencies = Config.AutoAdjacency ? AdjacencyUtils.GetAutoAdjacencies(sampleSet, tileRotation, Config.AutoAdjacencyTolerance) : new AdjacentModel.Adjacency[0]; var manualAdjacencies = GetManualAdjacencies(sampleSet.Directions, tileRotation); SetupAdjacencies(tileModel, tileRotation, autoAdjacencies.Concat(manualAdjacencies).ToList()); SetupTiles(tileModel, tileRotation); return(tileModel); }
private void SetupAdjacencies(TileModel model, TileRotation tileRotation) { if (Config.Adjacencies != null) { var adjacentModel = model as AdjacentModel; if (adjacentModel == null) { throw new ConfigurationException("Setting adjacencies is only supported for the \"adjacent\" model."); } foreach (var a in Config.Adjacencies) { var srcAdj = a.Src.Select(Parse).Select(tileRotation.Canonicalize).ToList(); var destAdj = a.Dest.Select(Parse).Select(tileRotation.Canonicalize).ToList(); adjacentModel.AddAdjacency(srcAdj, destAdj, a.X, a.Y, a.Z, tileRotation); } // If there are no samples, set frequency to 1 for everything mentioned in this block foreach (var tile in adjacentModel.Tiles) { adjacentModel.SetFrequency(tile, 1, tileRotation); } } }
public static Vector2? GetInversedVector(Vector2? vect, int width, int height, TileRotation rotation) { Vector2? newVector = null; if (vect == null) { return null; } switch (rotation) { case TileRotation.DEGREE_90: newVector = new Vector2(width - vect.Value.Y, vect.Value.X); break; case TileRotation.DEGREE_180: newVector = new Vector2(width - vect.Value.X, height - vect.Value.Y); break; case TileRotation.DEGREE_270: newVector = new Vector2(vect.Value.Y, height - vect.Value.X); break; } return newVector; }
private void SetupTiles(TileModel model, TileRotation tileRotation) { if (Config.Tiles != null) { foreach (var tile in Config.Tiles) { var value = Parse(tile.Value); if (tile.MultiplyFrequency != null) { var cf = tile.MultiplyFrequency.Trim(); double cfd; if (cf.EndsWith("%")) { cfd = double.Parse(cf.TrimEnd('%'), CultureInfo.InvariantCulture) / 100; } else { cfd = double.Parse(cf, CultureInfo.InvariantCulture); } model.MultiplyFrequency(value, cfd, tileRotation); } } } }
public static IList <AdjacentModel.Adjacency> GetAutoAdjacencies(SampleSet sampleSet, TileRotation tileRotations, double tolerance) { if (sampleSet.ExportOptions is BitmapSetExportOptions bseo) { var subTiles = GetSubTiles(bseo, out var subTileTopology); return(GetAutoAdjacencies(subTiles, subTileTopology, tileRotations, DiffColor, tolerance)); } if (sampleSet.ExportOptions is VoxSetExportOptions vseo) { var subTiles = GetSubTiles(vseo, out var subTileTopology); return(GetAutoAdjacencies(subTiles, subTileTopology, tileRotations, DiffIndex, tolerance)); } throw new Exception("AutoAdjacency not supported for this type of tile set"); }
public void LoadContent(Layer layer, Vector2 tileSheetPosition, Vector2 mapPosition, TileRotation rotation) { this.layer = layer; layer.OnScaleChange += updateRectangle; mapTilePosition = mapPosition; Rotation = rotation; TileSheetRectangle = new Rectangle((int)(tileSheetPosition.X * layer.TileDimensions.X), (int)(tileSheetPosition.Y * layer.TileDimensions.Y), (int)layer.TileDimensions.X, (int)layer.TileDimensions.Y); Body.Position = mapPosition * layer.TileDimensions * layer.Scale; Shape.OnAreaChanged += delegate { Body.Area = Shape.Area; }; Body.LoadContent(Material.Tile); Shape.LoadContent(this, layer.TileDimensions.X, layer.TileDimensions.Y, layer.Scale); }
public List <ITileConstraint> GetConstraints(DirectionSet directions, TileRotation tileRotation) { var is3d = directions.Type == DirectionSetType.Cartesian3d; var constraints = new List <ITileConstraint>(); if (Config.Ground != null) { var groundTile = Parse(Config.Ground); constraints.Add(new BorderConstraint { Sides = is3d ? BorderSides.ZMin : BorderSides.YMax, Tiles = new[] { groundTile }, }); constraints.Add(new BorderConstraint { Sides = is3d ? BorderSides.ZMin : BorderSides.YMax, Tiles = new[] { groundTile }, InvertArea = true, Ban = true, }); } if (Config.Constraints != null) { foreach (var constraint in Config.Constraints) { if (constraint is PathConfig pathData) { var tiles = new HashSet <Tile>(pathData.Tiles.Select(Parse)); #pragma warning disable CS0618 // Type or member is obsolete var p = new PathConstraint(tiles, pathData.EndPoints, tileRotation) #pragma warning restore CS0618 // Type or member is obsolete { EndPointTiles = pathData.EndPointTiles == null ? null : new HashSet <Tile>(pathData.EndPointTiles.Select(Parse)) }; constraints.Add(p); } else if (constraint is EdgedPathConfig edgedPathData) { var exits = edgedPathData.Exits.ToDictionary( kv => Parse(kv.Key), x => (ISet <Direction>) new HashSet <Direction>(x.Value.Select(ParseDirection))); #pragma warning disable CS0618 // Type or member is obsolete var p = new EdgedPathConstraint(exits, edgedPathData.EndPoints, tileRotation) #pragma warning restore CS0618 // Type or member is obsolete { EndPointTiles = edgedPathData.EndPointTiles == null ? null : new HashSet <Tile>(edgedPathData.EndPointTiles.Select(Parse)) }; constraints.Add(p); } else if (constraint is BorderConfig borderData) { var tiles = borderData.Tiles.Select(Parse).ToArray(); var sides = borderData.Sides == null ? BorderSides.All : (BorderSides)Enum.Parse(typeof(BorderSides), borderData.Sides, true); var excludeSides = borderData.ExcludeSides == null ? BorderSides.None : (BorderSides)Enum.Parse(typeof(BorderSides), borderData.ExcludeSides, true); if (!is3d) { sides = sides & ~BorderSides.ZMin & ~BorderSides.ZMax; excludeSides = excludeSides & ~BorderSides.ZMin & ~BorderSides.ZMax; } constraints.Add(new BorderConstraint { Tiles = tiles, Sides = sides, ExcludeSides = excludeSides, InvertArea = borderData.InvertArea, Ban = borderData.Ban, }); } else if (constraint is FixedTileConfig fixedTileConfig) { constraints.Add(new FixedTileConstraint { Tiles = fixedTileConfig.Tiles.Select(Parse).ToArray(), Point = fixedTileConfig.Point, }); } else if (constraint is MaxConsecutiveConfig maxConsecutiveConfig) { var axes = maxConsecutiveConfig.Axes?.Select(ParseAxis); constraints.Add(new MaxConsecutiveConstraint { Tiles = new HashSet <Tile>(maxConsecutiveConfig.Tiles.Select(Parse)), MaxCount = maxConsecutiveConfig.MaxCount, Axes = axes == null ? null : new HashSet <Axis>(axes), }); } else if (constraint is MirrorXConfig mirrorYConfig) { constraints.Add(new MirrorXConstraint { TileRotation = tileRotation, }); } else if (constraint is MirrorYConfig mirrorXConfig) { constraints.Add(new MirrorYConstraint { TileRotation = tileRotation, }); } else if (constraint is CountConfig countConfig) { constraints.Add(new CountConstraint { Tiles = new HashSet <Tile>(countConfig.Tiles.Select(Parse)), Comparison = countConfig.Comparison, Count = countConfig.Count, Eager = countConfig.Eager, }); } else if (constraint is SeparationConfig separationConfig) { constraints.Add(new SeparationConstraint { Tiles = new HashSet <Tile>(separationConfig.Tiles.Select(Parse)), MinDistance = separationConfig.MinDistance, }); } else if (constraint is ConnectedConfig connectedConfig) { constraints.Add(new ConnectedConstraint { PathSpec = GetPathSpec(connectedConfig.PathSpec), }); } else if (constraint is LoopConfig loopConfig) { constraints.Add(new LoopConstraint { PathSpec = GetPathSpec(loopConfig.PathSpec), }); } else if (constraint is AcyclicConfig acyclicConfig) { constraints.Add(new AcyclicConstraint { PathSpec = GetPathSpec(acyclicConfig.PathSpec), }); } else { throw new NotImplementedException($"Unknown constraint type {constraint.GetType()}"); } } } return(constraints); }
/// <summary> /// Rotate field to reflect tile rotation /// </summary> /// <param name="field">field to rotate</param> /// <param name="rotation">rotation - 0 / 90 / 180 / 270 degrees</param> /// <param name="width">tile width</param> /// <param name="height">tile height</param> public static void RotateField(Field field, TileRotation rotation, int width, int height) { var newVector = MapVector.GetInversedVector(new Vector2(field.Rect.X, field.Rect.Y), width, height, rotation); var newX = (int)newVector.Value.X; var newY = (int)newVector.Value.Y; var tempOpenLeft = field.OpenLeft; var tempOpenRight = field.OpenRight; var tempOpenTop = field.OpenTop; var tempOpenBottom = field.OpenBottom; var tempTopField = field.TopField; var tempBottomField = field.BottomField; var tempLeftField = field.LeftField; var tempRightField = field.RightField; var tempTopRightField = field.TopRightField; var tempTopLeftField = field.TopLeftField; var tempBottomLeftField = field.BottomLeftField; var tempBottomRightField = field.BottomRightField; switch (rotation) { case TileRotation.DEGREE_90: newX -= field.Rect.Width; field.OpenLeft = tempOpenBottom; field.OpenRight = tempOpenTop; field.OpenTop = tempOpenLeft; field.OpenBottom = tempOpenRight; field.TopField = tempLeftField; field.BottomField = tempRightField; field.LeftField = tempBottomField; field.RightField = tempTopField; field.TopLeftField = tempBottomLeftField; field.TopRightField = tempTopLeftField; field.BottomRightField = tempTopRightField; field.BottomLeftField = tempBottomRightField; break; case TileRotation.DEGREE_180: newX -= field.Rect.Width; newY -= field.Rect.Height; field.OpenLeft = tempOpenRight; field.OpenRight = tempOpenLeft; field.OpenTop = tempOpenBottom; field.OpenBottom = tempOpenTop; field.LeftField = tempRightField; field.RightField = tempLeftField; field.TopField = tempBottomField; field.BottomField = tempTopField; field.TopLeftField = tempBottomRightField; field.TopRightField = tempBottomLeftField; field.BottomRightField = tempTopLeftField; field.BottomLeftField = tempTopRightField; break; case TileRotation.DEGREE_270: newY -= field.Rect.Height; field.OpenLeft = tempOpenTop; field.OpenRight = tempOpenBottom; field.OpenTop = tempOpenRight; field.OpenBottom = tempOpenLeft; field.LeftField = tempTopField; field.RightField = tempBottomField; field.TopField = tempRightField; field.BottomField = tempLeftField; field.TopLeftField = tempTopRightField; field.TopRightField = tempBottomRightField; field.BottomRightField = tempBottomLeftField; field.BottomLeftField = tempTopLeftField; break; } field.Rect = new Rectangle(newX, newY, field.Rect.Width, field.Rect.Height); field.OriginRect = field.Rect; }
private IList <AdjacentModel.Adjacency> GetManualAdjacencies(DirectionSet directions, TileRotation tileRotation) { if (Config.Adjacencies == null) { return(new AdjacentModel.Adjacency[0]); } AdjacentModel.Adjacency Convert(AdjacencyData a) { return(new AdjacentModel.Adjacency { Src = a.Src.Select(Parse).Select(tileRotation.Canonicalize).ToArray(), Dest = a.Dest.Select(Parse).Select(tileRotation.Canonicalize).ToArray(), Direction = a.Direction, }); } return(AdjacencyUtils.Rotate( Config.Adjacencies.Select(Convert).ToList(), tileRotation.RotationGroup, directions, tileRotation)); }
public void Rotate(TileRotation rotation, int width, int height) { FieldHelper.RotateField(this, rotation, width, height); }
/// <summary> /// Elforgatja a mezőt. A mező belső reprezentációjában van egy "rotation" tag, ami a mező aktuális elfordulását írja le, relatív a mező alapállapotához. /// </summary> public void Rotate() { Rotation = Rotation.GetNext(); }
public static ITopoArray <Tile> HexRotate(ITopoArray <Tile> original, Rotation rotation, TileRotation tileRotation = null) { bool TileRotate(Tile tile, out Tile result) { return(tileRotation.Rotate(tile, rotation, out result)); } return(HexRotate <Tile>(original, rotation, tileRotation == null ? null : (TileRotate <Tile>)TileRotate)); }
public static IList <AdjacentModel.Adjacency> Rotate(IList <AdjacentModel.Adjacency> adjacencies, RotationGroup rg, DirectionSet directions, TileRotation tileRotation) { return(rg.SelectMany(r => Rotate(adjacencies, r, directions, tileRotation)).ToList()); }
/// <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); } }
public static IList <AdjacentModel.Adjacency> Rotate(IList <AdjacentModel.Adjacency> adjacencies, Rotation rotation, DirectionSet directions, TileRotation tileRotation) { return(adjacencies .Select(x => Rotate(x, rotation, directions, tileRotation)) .Where(x => x.Src.Length > 0 && x.Dest.Length > 0) .ToList()); }
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), }); }
public TileEnterA(TileRotation rotate = TileRotation.NONE) : base(rotate) { }
public static ITopoArray <Tile> HexRotate(ITopoArray <Tile> original, int rotate, bool reflectX = false, TileRotation tileRotation = null) { bool TileRotate(Tile tile, out Tile result) { return(tileRotation.Rotate(tile, rotate, reflectX, out result)); } return(HexRotate <Tile>(original, rotate, reflectX, tileRotation == null ? null : (TileRotate <Tile>)TileRotate)); }
public TileModel GetModel(DirectionSet directions, ITopoArray <Tile>[] samples, TileRotation tileRotation) { var modelConfig = Config.Model ?? new Adjacent(); TileModel tileModel; if (modelConfig is Overlapping overlapping) { var model = new OverlappingModel(overlapping.NX, overlapping.NY, overlapping.NZ); foreach (var sample in samples) { model.AddSample(sample, tileRotation); } tileModel = model; } else if (modelConfig is Adjacent adjacent) { var model = new AdjacentModel(directions); foreach (var sample in samples) { model.AddSample(sample, tileRotation); } tileModel = model; } else { throw new ConfigurationException($"Unrecognized model type {modelConfig.GetType()}"); } SetupAdjacencies(tileModel, tileRotation); SetupTiles(tileModel, tileRotation); return(tileModel); }
public EdgedPathConstraint(IDictionary <Tile, ISet <Direction> > exits, Point[] endPoints = null, TileRotation tileRotation = null) { this.Exits = exits; this.EndPoints = endPoints; this.TileRotation = tileRotation; }
public PathConstraint(ISet <Tile> tiles, Point[] endPoints = null, TileRotation tileRotation = null) { this.Tiles = tiles; this.EndPoints = endPoints; this.TileRotation = tileRotation; }
public List <ITileConstraint> GetConstraints(DirectionSet directions, TileRotation tileRotation) { var is3d = directions.Type == DirectionSetType.Cartesian3d; var constraints = new List <ITileConstraint>(); if (Config.Ground != null) { var groundTile = Parse(Config.Ground); constraints.Add(new BorderConstraint { Sides = is3d ? BorderSides.ZMin : BorderSides.YMax, Tiles = new[] { groundTile }, }); constraints.Add(new BorderConstraint { Sides = is3d ? BorderSides.ZMin : BorderSides.YMax, Tiles = new[] { groundTile }, InvertArea = true, Ban = true, }); } if (Config.Constraints != null) { foreach (var constraint in Config.Constraints) { if (constraint is PathConfig pathData) { var tiles = new HashSet <Tile>(pathData.Tiles.Select(Parse)); var p = new PathConstraint(tiles, pathData.EndPoints); constraints.Add(p); } else if (constraint is EdgedPathConfig edgedPathData) { var exits = edgedPathData.Exits.ToDictionary( kv => Parse(kv.Key), x => (ISet <Direction>) new HashSet <Direction>(x.Value.Select(ParseDirection))); var p = new EdgedPathConstraint(exits, edgedPathData.EndPoints, tileRotation); constraints.Add(p); } else if (constraint is BorderConfig borderData) { var tiles = borderData.Tiles.Select(Parse).ToArray(); var sides = borderData.Sides == null ? BorderSides.All : (BorderSides)Enum.Parse(typeof(BorderSides), borderData.Sides, true); var excludeSides = borderData.ExcludeSides == null ? BorderSides.None : (BorderSides)Enum.Parse(typeof(BorderSides), borderData.ExcludeSides, true); if (!is3d) { sides = sides & ~BorderSides.ZMin & ~BorderSides.ZMax; excludeSides = excludeSides & ~BorderSides.ZMin & ~BorderSides.ZMax; } constraints.Add(new BorderConstraint { Tiles = tiles, Sides = sides, ExcludeSides = excludeSides, InvertArea = borderData.InvertArea, Ban = borderData.Ban, }); } else if (constraint is FixedTileConfig fixedTileConfig) { constraints.Add(new FixedTileConstraint { Tiles = fixedTileConfig.Tiles.Select(Parse).ToArray(), Point = fixedTileConfig.Point, }); } else if (constraint is MaxConsecutiveConfig maxConsecutiveConfig) { var axes = maxConsecutiveConfig.Axes?.Select(ParseAxis); constraints.Add(new MaxConsecutiveConstraint { Tiles = new HashSet <Tile>(maxConsecutiveConfig.Tiles.Select(Parse)), MaxCount = maxConsecutiveConfig.MaxCount, Axes = axes == null ? null : new HashSet <Axis>(axes), }); } else if (constraint is MirrorConfig mirrorConfig) { constraints.Add(new MirrorConstraint { TileRotation = tileRotation, }); } else { throw new NotImplementedException($"Unknown constraint type {constraint.GetType()}"); } } } return(constraints); }
public static ITopoArray <Tile> Rotate(ITopoArray <Tile> original, Rotation rotation, TileRotation tileRotation = null) { var type = original.Topology.Directions.Type; if (type == DirectionSetType.Cartesian2d || type == DirectionSetType.Cartesian3d) { return(SquareRotate(original, rotation, tileRotation)); } else if (type == DirectionSetType.Hexagonal2d) { return(HexRotate(original, rotation, tileRotation)); } else { throw new Exception($"Unknown directions type {type}"); } }
public TileExitA(TileRotation rotate = TileRotation.NONE) : base(rotate) { }
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); }