/// <summary> /// Gets the matrix that transforms the part at this position to another position. /// </summary> /// <param name="other">The other.</param> /// <returns></returns> /// <exception cref="System.InvalidOperationException"> /// The method has been called on a default instance of the <see cref="EdgePartPosition" /> struct. /// </exception> /// <exception cref="System.ArgumentException">The other edge part has not been set.</exception> public Matrix3x2 GetTransformTo(EdgePartPosition other) { if (Part == null) { throw new InvalidOperationException("Edge part not set."); } if (other.Part == null) { throw new ArgumentException("Other edge part not set.", nameof(other)); } bool isClockwise = Part.IsClockwise; bool otherIsClockwise = other.Part.IsClockwise; Vector2 fromStart = isClockwise ? Start : End; Vector2 fromEnd = isClockwise ? End : Start; Vector2 toStart = otherIsClockwise ? other.Start : other.End; Vector2 toEnd = otherIsClockwise ? other.End : other.Start; Matrix3x2 transform = Matrix.GetTransform(fromStart, fromEnd, toStart, toEnd); if (isClockwise == otherIsClockwise) { transform *= Matrix.CreateReflection(toStart, toEnd); } return(transform); }
public EdgePartPosition GetEdgePartPosition([NotNull] EdgePart edgePart) => EdgePartPosition.Create(edgePart, Shape, Transform);
public Tiling CreateTiling( [NotNull] TilingDefinition tilingDefinition, [NotNull] ShapeSet shapes, [NotNull] StyleManager styleManager) { if (tilingDefinition == null) { throw new ArgumentNullException(nameof(tilingDefinition)); } if (shapes == null) { throw new ArgumentNullException(nameof(shapes)); } if (styleManager == null) { throw new ArgumentNullException(nameof(styleManager)); } if (!Tilings.Values.Contains(tilingDefinition)) { throw new ArgumentException( Strings.Template_CreateTiling_UnknownTilingDefinition, nameof(tilingDefinition)); } HashSet <ShapeTemplate> templates = new HashSet <ShapeTemplate>(shapes.Select(s => s.Template)); if (!templates.SetEquals(ShapeTemplates.Values)) { throw new ArgumentException(Strings.Template_CreateTiling_WrongShapes, nameof(shapes)); } Dictionary <int, ShapeLines> shapeLines = new Dictionary <int, ShapeLines>(); List <Tile> tiles = new List <Tile>(shapes.Count); // TODO Order shapes so that the nth shape is adjacent to at least one of the previous shapes foreach (Shape shape in shapes) { Debug.Assert(shape != null, "shape != null"); string label = null; Matrix3x2 transform = default(Matrix3x2); if (tiles.Count < 1) { label = tilingDefinition.AdjacentParts .Where(l => l.Value.ShapeTemplate == shape.Template) .OrderBy(l => l.Label, StringComparer.InvariantCulture) .First().Label; transform = Matrix3x2.Identity; } else { foreach (Tile t in tiles) { foreach (EdgePartShape partShape in t.PartShapes) { Debug.Assert(partShape != null, "partShape != null"); Labeled <EdgePart> adjacent; if (!tilingDefinition.AdjacentParts.TryGetAdjacent( partShape.Part.WithLabel(t.Label), out adjacent)) { continue; } Debug.Assert(adjacent.Value != null, "adjacent.Value != null"); if (adjacent.Value.ShapeTemplate != shape.Template) { continue; } label = adjacent.Label; transform = EdgePartPosition.Create(adjacent.Value, shape) .GetTransformTo(t.GetEdgePartPosition(partShape.Part)); } if (label != null) { break; } } if (label == null) { throw new InvalidDataException(); } } EdgePartShape[] partShapes = shape.Template.EdgeParts[tilingDefinition] .Select( ep => new EdgePartShape( ep, shapes.GetEdge(ep.EdgePattern.EdgeName), shapeLines.GetOrAdd(ep.PartShapeID, _ => ShapeLines.CreateDefault()))) .ToArray(); Tile tile = new Tile(label, shape, transform, partShapes); tile.Style = styleManager.GetStyle(tile); tiles.Add(tile); } return(new Tiling(this, tilingDefinition, tiles, styleManager)); }
/// <summary> /// Gets the matrix that transforms the part at this position to another position. /// </summary> /// <param name="other">The other.</param> /// <returns></returns> /// <exception cref="System.InvalidOperationException"> /// The method has been called on a default instance of the <see cref="EdgePartPosition" /> struct. /// </exception> /// <exception cref="System.ArgumentException">The other edge part has not been set.</exception> public Matrix3x2 GetTransformTo(EdgePartPosition other) { if (Part == null) throw new InvalidOperationException("Edge part not set."); if (other.Part == null) throw new ArgumentException("Other edge part not set.", nameof(other)); bool isClockwise = Part.IsClockwise; bool otherIsClockwise = other.Part.IsClockwise; Vector2 fromStart = isClockwise ? Start : End; Vector2 fromEnd = isClockwise ? End : Start; Vector2 toStart = otherIsClockwise ? other.Start : other.End; Vector2 toEnd = otherIsClockwise ? other.End : other.Start; Matrix3x2 transform = Matrix.GetTransform(fromStart, fromEnd, toStart, toEnd); if (isClockwise == otherIsClockwise) transform *= Matrix.CreateReflection(toStart, toEnd); return transform; }