View Source Vivid.Transform (vivid v0.4.4)

Creates and applies a "pipeline" of transformations to a shape. Transformation operations are collected up and only run once, when apply is called.

Examples

Take a square, rotate it 45°, scale it up 50% and center it within a frame.

iex> use Vivid
...> frame = Frame.init(40, 40, RGBA.white)
...> box = Box.init(Point.init(0,0), Point.init(10,10))
...>   |> Transform.rotate(45)
...>   |> Transform.scale(1.5)
...>   |> Transform.center(frame)
...>   |> Transform.apply
...> Frame.push(frame, box, RGBA.black)
...> |> to_string
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@ @ @@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@ @@@ @@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@ @@@@@ @@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@ @@@@@@@ @@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@  @@@@@@@@@ @@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@ @@@@@@@@@@@@@@ @@@@@@@@@@@@\n" <>
"@@@@@@@@@@@ @@@@@@@@@@@@@@@@ @@@@@@@@@@@\n" <>
"@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ @@@@@@@@@@\n" <>
"@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@ @@@@@@@@@\n" <>
"@@@@@@@@@@ @@@@@@@@@@@@@@@@@@ @@@@@@@@@@\n" <>
"@@@@@@@@@@@ @@@@@@@@@@@@@@@@ @@@@@@@@@@@\n" <>
"@@@@@@@@@@@@ @@@@@@@@@@@@@@ @@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@ @@@@@@@@@@ @@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@ @@@@@@@@@ @@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@ @@@@@@@ @@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@ @@@@@ @@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@ @@@ @@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@ @ @@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"

Summary

Functions

Apply a transformation pipeline returning the modified shape.

Center a shape within the specified bounds.

Scale a shape to the maximum size within bounds, respecting the shape's aspect ratio.

Scale a shape to completely fill bounds, respecting the shape's aspect ratio. Thus overflowing the bounds if the shape's aspect ratio doesn't match that of the bounds.

Rotate a shape around it's center point.

Rotate a shape around an origin point.

Uniformly scale a shape around it's center point.

Scale a shape around it's center point using the given x and y multipliers.

Stretch a shape to the maximum size within bounds, ignoring the shape's original aspect ratio.

Create an arbitrary transformation.

Translate (ie move) a shape by adding x and y to each Point.

Types

@type degrees() :: number()
@type shape_or_transform() :: t() | Vivid.Shape.t()
@type t() :: %Vivid.Transform{
  operations: [Vivid.Transform.Operation.t()],
  shape: Vivid.Shape.t()
}

Functions

@spec apply(t()) :: Vivid.Shape.t()

Apply a transformation pipeline returning the modified shape.

@spec center(shape_or_transform(), Vivid.Shape.t()) :: t()

Center a shape within the specified bounds.

Examples

iex> use Vivid
...> frame = Frame.init(13,13, RGBA.white)
...> box = Box.init(Point.init(10,10), Point.init(20,20))
...>   |> Vivid.Transform.center(Bounds.init(0, 0, 12, 12))
...>   |> Vivid.Transform.apply
...> Frame.push(frame, box, RGBA.black)
...> |> to_string
"@@@@@@@@@@@@@\n" <>
"@           @\n" <>
"@ @@@@@@@@@ @\n" <>
"@ @@@@@@@@@ @\n" <>
"@ @@@@@@@@@ @\n" <>
"@ @@@@@@@@@ @\n" <>
"@ @@@@@@@@@ @\n" <>
"@ @@@@@@@@@ @\n" <>
"@ @@@@@@@@@ @\n" <>
"@ @@@@@@@@@ @\n" <>
"@ @@@@@@@@@ @\n" <>
"@           @\n" <>
"@@@@@@@@@@@@@\n"
@spec fill(shape_or_transform(), Vivid.Shape.t()) :: t()

Scale a shape to the maximum size within bounds, respecting the shape's aspect ratio.

Examples

iex> Vivid.Box.init(Vivid.Point.init(10,10), Vivid.Point.init(20,20))
...> |> Vivid.Transform.fill(Vivid.Bounds.init(0, 0, 40, 80))
...> |> Vivid.Transform.apply
Vivid.Polygon.init([Vivid.Point.init(40.0, 0.0), Vivid.Point.init(40.0, 40.0), Vivid.Point.init(0.0, 40.0), Vivid.Point.init(0.0, 0.0)])
@spec overflow(shape_or_transform(), Vivid.Shape.t()) :: t()

Scale a shape to completely fill bounds, respecting the shape's aspect ratio. Thus overflowing the bounds if the shape's aspect ratio doesn't match that of the bounds.

Examples

iex> Vivid.Box.init(Vivid.Point.init(10,10), Vivid.Point.init(20,20))
...> |> Vivid.Transform.overflow(Vivid.Bounds.init(0, 0, 40, 80))
...> |> Vivid.Transform.apply
Vivid.Polygon.init([Vivid.Point.init(80.0, 0.0), Vivid.Point.init(80.0, 80.0), Vivid.Point.init(0.0, 80.0), Vivid.Point.init(0.0, 0.0)])
@spec rotate(shape_or_transform(), degrees()) :: t()

Rotate a shape around it's center point.

Example

iex> Vivid.Box.init(Vivid.Point.init(10,10), Vivid.Point.init(20,20))
...> |> Vivid.Transform.rotate(45)
...> |> Vivid.Transform.apply
...> |> to_string
"@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@ @@@@@@@@\n" <>
"@@@@@@@ @ @@@@@@@\n" <>
"@@@@@@ @@@ @@@@@@\n" <>
"@@@@@ @@@@@ @@@@@\n" <>
"@@@@ @@@@@@@ @@@@\n" <>
"@@@ @@@@@@@@@ @@@\n" <>
"@@ @@@@@@@@@@@ @@\n" <>
"@ @@@@@@@@@@@@@ @\n" <>
"@@ @@@@@@@@@@@ @@\n" <>
"@@@ @@@@@@@@@ @@@\n" <>
"@@@@ @@@@@@@ @@@@\n" <>
"@@@@@ @@@@@ @@@@@\n" <>
"@@@@@@ @@@ @@@@@@\n" <>
"@@@@@@@ @ @@@@@@@\n" <>
"@@@@@@@@ @@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@\n"
Link to this function

rotate(shape, degrees, origin)

View Source
@spec rotate(shape_or_transform(), degrees(), Vivid.Point.t()) :: t()

Rotate a shape around an origin point.

Example

iex> Vivid.Box.init(Vivid.Point.init(10,10), Vivid.Point.init(20,20))
...> |> Vivid.Transform.rotate(45, Vivid.Point.init(5,5))
...> |> Vivid.Transform.apply
...> |> to_string
"@@@@@@@@@@@@@@@@@\n" <>
"@@@@@@@@ @@@@@@@@\n" <>
"@@@@@@@ @ @@@@@@@\n" <>
"@@@@@@ @@@ @@@@@@\n" <>
"@@@@@ @@@@@ @@@@@\n" <>
"@@@@ @@@@@@@ @@@@\n" <>
"@@@ @@@@@@@@@ @@@\n" <>
"@@ @@@@@@@@@@@ @@\n" <>
"@ @@@@@@@@@@@@@ @\n" <>
"@@ @@@@@@@@@@@ @@\n" <>
"@@@ @@@@@@@@@ @@@\n" <>
"@@@@ @@@@@@@ @@@@\n" <>
"@@@@@ @@@@@ @@@@@\n" <>
"@@@@@@ @@@ @@@@@@\n" <>
"@@@@@@@ @ @@@@@@@\n" <>
"@@@@@@@@ @@@@@@@@\n" <>
"@@@@@@@@@@@@@@@@@\n"
@spec scale(shape_or_transform(), number()) :: t()

Uniformly scale a shape around it's center point.

Examples

iex> Vivid.Box.init(Vivid.Point.init(5,5), Vivid.Point.init(10,10))
...> |> Vivid.Transform.scale(2)
...> |> Vivid.Transform.apply
Vivid.Polygon.init([Vivid.Point.init(12.5, 2.5), Vivid.Point.init(12.5, 12.5), Vivid.Point.init(2.5, 12.5), Vivid.Point.init(2.5, 2.5)])
@spec scale(shape_or_transform(), number(), number()) :: t()

Scale a shape around it's center point using the given x and y multipliers.

Examples

iex> Vivid.Box.init(Vivid.Point.init(5,5), Vivid.Point.init(10,10))
...> |> Vivid.Transform.scale(2, 4)
...> |> Vivid.Transform.apply
Vivid.Polygon.init([Vivid.Point.init(12.5, -2.5), Vivid.Point.init(12.5, 17.5), Vivid.Point.init(2.5, 17.5), Vivid.Point.init(2.5, -2.5)])
@spec stretch(shape_or_transform(), Vivid.Shape.t()) :: t()

Stretch a shape to the maximum size within bounds, ignoring the shape's original aspect ratio.

Examples

iex> Vivid.Box.init(Vivid.Point.init(10,10), Vivid.Point.init(20,20))
...> |> Vivid.Transform.stretch(Vivid.Bounds.init(0, 0, 40, 80))
...> |> Vivid.Transform.apply
Vivid.Polygon.init([Vivid.Point.init(40.0, 0.0), Vivid.Point.init(40.0, 80.0), Vivid.Point.init(0.0, 80.0), Vivid.Point.init(0.0, 0.0)])
@spec transform(shape_or_transform(), function()) :: t()

Create an arbitrary transformation.

Takes a shape and a function which is called with a shape argument (not necessarily the shape passed-in, depending on where this transformation is in the transformation pipeline).

The function must return another function which takes and manipulates a point.

Example

The example below translates a point right by half it's width.

iex> Vivid.Box.init(Vivid.Point.init(10,10), Vivid.Point.init(20,20))
...> |> Vivid.Transform.transform(fn shape ->
...>   width = Vivid.Bounds.width(shape)
...>   fn point ->
...>     x = point |> Vivid.Point.x
...>     y = point |> Vivid.Point.y
...>     x = x + (width / 2) |> round
...>     Vivid.Point.init(x, y)
...>   end
...> end)
...> |> Vivid.Transform.apply
Vivid.Polygon.init([Vivid.Point.init(25, 10), Vivid.Point.init(25, 20), Vivid.Point.init(15, 20), Vivid.Point.init(15, 10)])
@spec translate(shape_or_transform(), number(), number()) :: t()

Translate (ie move) a shape by adding x and y to each Point.

Example

iex> Vivid.Box.init(Vivid.Point.init(5,5), Vivid.Point.init(10,10))
...> |> Vivid.Transform.translate(5, 5)
...> |> Vivid.Transform.apply
Vivid.Polygon.init([Vivid.Point.init(15, 10), Vivid.Point.init(15, 15), Vivid.Point.init(10, 15), Vivid.Point.init(10, 10)])