Blendend.Matrix2D (blendend v0.2.0)

View Source

Thin wrapper around blend2d's BLMatrix2D.

Internally this is a NIF resource representing an affine transform:

| m00  m01  tx |
| m10  m11  ty |
|  0    0   1  |

Functions in this module either create such a matrix or combine it with other transforms.

  • m00, m01, m10, m11 – linear part (scale, rotation, skew)
  • tx, ty – translation

Summary

Types

t()

Opaque affine transform matrix (BLMatrix2D).

Functions

Returns the identity transform matrix.

Same as identity/0, but returns the matrix directly.

Inverts the matrix, returning a new matrix.

Same as invert/1, but returns the matrix directly.

Constructs a matrix from precomputed sin/cos and optional translation tx/ty.

Same as make_sin_cos/4, but returns the matrix directly.

Maps a point {x, y} through the matrix, returning {ok, {x, y}}.

Same as map_point/3, but returns the tuple directly.

Maps a vector {x, y} through the matrix (ignores translation), returning {ok, {x, y}}.

Same as map_vector/3, but returns the tuple directly.

Creates a matrix from a 6-element list [m00, m01, m10, m11, tx, ty].

Same as new/1, but returns the matrix directly.

Returns rotation * matrix, applying the rotation about {cx, cy} before the existing transform.

Same as post_rotate/4, but returns the rotated matrix directly.

Returns scale * matrix, applying the scale before the existing transform.

Same as post_scale/3, but returns the scaled matrix directly.

Returns skew * matrix, applying the shear before the existing transforms.

Same as post_skew/3, but returns the skewed matrix directly.

Returns other * matrix, i.e. the other transform is applied before matrix.

Same as post_transform/2, but returns the matrix directly.

Returns translation * matrix, applying (tx, ty) before the existing transforms.

Same as post_translate/3, but raises on error and returns the matrix.

Rotates the matrix by angle radians around the origin, returning a new matrix.

Same as rotate/2, but returns the rotated matrix directly.

Rotates the matrix by angle radians about {cx, cy}, returning a new matrix.

Same as rotate_at/4, but returns the rotated matrix directly.

Scales the matrix by sx and sy, returning a new matrix.

Same as scale/3, but returns the scaled matrix directly.

Skews (shears) the matrix by angles kx and ky (radians) and returns a new matrix.

Same as skew/3, but returns the skewed matrix directly.

Reads the matrix as [m00, m01, m10, m11, tx, ty].

Same as to_list/1, but returns the list directly.

Returns matrix * other, i.e. the other transform is applied after matrix.

Same as transform/2, but returns the matrix directly.

Translates the matrix by {tx, ty} and returns a new matrix.

Same as translate/3, but returns the translated matrix directly.

Types

t()

@opaque t()

Opaque affine transform matrix (BLMatrix2D).

Functions

identity()

@spec identity() :: {:ok, t()} | {:error, term()}

Returns the identity transform matrix.

On success, returns {:ok, matrix}.

On failure, returns {:error, reason}.

identity!()

@spec identity!() :: t()

Same as identity/0, but returns the matrix directly.

On success, returns matrix.

On failure, raises Blendend.Error.

invert(m)

@spec invert(t()) :: {:ok, t()} | {:error, term()}

Inverts the matrix, returning a new matrix.

Examples:

iex> use Blendend.Draw
iex> scale = matrix(do: scale(2, 1))
iex> Blendend.Matrix2D.invert!(scale) |> Blendend.Matrix2D.to_list!
[0.5, -0.0, -0.0, 1.0, -0.0, -0.0]

invert!(m)

@spec invert!(t()) :: t()

Same as invert/1, but returns the matrix directly.

make_sin_cos(sin, cos, tx \\ 0.0, ty \\ 0.0)

@spec make_sin_cos(number(), number(), number(), number()) ::
  {:ok, t()} | {:error, term()}

Constructs a matrix from precomputed sin/cos and optional translation tx/ty.

make_sin_cos!(sin, cos, tx \\ 0.0, ty \\ 0.0)

@spec make_sin_cos!(number(), number(), number(), number()) :: t()

Same as make_sin_cos/4, but returns the matrix directly.

map_point(m, x, y)

@spec map_point(t(), number(), number()) ::
  {:ok, {number(), number()}} | {:error, term()}

Maps a point {x, y} through the matrix, returning {ok, {x, y}}.

map_point!(m, x, y)

@spec map_point!(t(), number(), number()) :: {number(), number()}

Same as map_point/3, but returns the tuple directly.

map_vector(m, x, y)

@spec map_vector(t(), number(), number()) ::
  {:ok, {number(), number()}} | {:error, term()}

Maps a vector {x, y} through the matrix (ignores translation), returning {ok, {x, y}}.

Examples:

iex> use Blendend.Draw
iex> scale = matrix(do: scale(2, 1))
iex> Blendend.Matrix2D.map_vector!(scale, 2, 3)
{4.0, 3.0}

iex> translate = matrix(do: translate(10, 10))
iex> Blendend.Matrix2D.map_vector!(translate, 2, 3)
{2.0, 3.0}

map_vector!(m, x, y)

@spec map_vector!(t(), number(), number()) :: {number(), number()}

Same as map_vector/3, but returns the tuple directly.

new(lst)

@spec new([number()]) :: {:ok, t()} | {:error, term()}

Creates a matrix from a 6-element list [m00, m01, m10, m11, tx, ty].

On success, returns {:ok, matrix} where matrix is a Blendend.Matrix2D.t().

On failure, returns {:error, reason}.

new!(lst)

@spec new!([number()]) :: t()

Same as new/1, but returns the matrix directly.

On success, returns matrix.

On failure, raises Blendend.Error.

post_rotate(m, angle_rad, cx, cy)

@spec post_rotate(t(), number(), number(), number()) :: {:ok, t()} | {:error, term()}

Returns rotation * matrix, applying the rotation about {cx, cy} before the existing transform.

post_rotate!(m, angle_rad, cx, cy)

@spec post_rotate!(t(), number(), number(), number()) :: t()

Same as post_rotate/4, but returns the rotated matrix directly.

post_scale(m, sx, sy)

@spec post_scale(t(), number(), number()) :: {:ok, t()} | {:error, term()}

Returns scale * matrix, applying the scale before the existing transform.

post_scale!(m, sx, sy)

@spec post_scale!(t(), number(), number()) :: t()

Same as post_scale/3, but returns the scaled matrix directly.

post_skew(m, kx, ky)

@spec post_skew(t(), number(), number()) :: {:ok, t()} | {:error, term()}

Returns skew * matrix, applying the shear before the existing transforms.

post_skew!(m, kx, ky)

@spec post_skew!(t(), number(), number()) :: t()

Same as post_skew/3, but returns the skewed matrix directly.

post_transform(m, other)

@spec post_transform(t(), t()) :: {:ok, t()} | {:error, term()}

Returns other * matrix, i.e. the other transform is applied before matrix.

Examples:

iex> use Blendend.Draw
iex> translate = matrix(do: translate(10, 0))
iex> scale = matrix(do: scale(2, 1))
iex> {:ok, m} = Blendend.Matrix2D.post_transform(translate, scale)
iex> {:ok, list} = Blendend.Matrix2D.to_list(m)
iex> list
[2.0, 0.0, 0.0, 1.0, 20.0, 0.0]  # scale first, then translate (x translation doubled)

post_transform!(m, other)

@spec post_transform!(t(), t()) :: t()

Same as post_transform/2, but returns the matrix directly.

post_translate(m, tx, ty)

@spec post_translate(t(), number(), number()) :: {:ok, t()} | {:error, term()}

Returns translation * matrix, applying (tx, ty) before the existing transforms.

post_translate!(m, tx, ty)

@spec post_translate!(t(), number(), number()) :: t()

Same as post_translate/3, but raises on error and returns the matrix.

rotate(m, angle_rad)

@spec rotate(t(), number()) :: {:ok, t()} | {:error, term()}

Rotates the matrix by angle radians around the origin, returning a new matrix.

On success, returns {:ok, matrix}.

On failure, returns {:error, reason}.

rotate!(m, angle_rad)

@spec rotate!(t(), number()) :: t()

Same as rotate/2, but returns the rotated matrix directly.

On success, returns matrix.

On failure, raises Blendend.Error.

rotate_at(m, angle_rad, cx, cy)

@spec rotate_at(t(), number(), number(), number()) :: {:ok, t()} | {:error, term()}

Rotates the matrix by angle radians about {cx, cy}, returning a new matrix.

rotate_at!(m, angle_rad, cx, cy)

@spec rotate_at!(t(), number(), number(), number()) :: t()

Same as rotate_at/4, but returns the rotated matrix directly.

scale(m, sx, sy)

@spec scale(t(), number(), number()) :: {:ok, t()} | {:error, term()}

Scales the matrix by sx and sy, returning a new matrix.

On success, returns {:ok, matrix}.

On failure, returns {:error, reason}.

scale!(m, sx, sy)

@spec scale!(t(), number(), number()) :: t()

Same as scale/3, but returns the scaled matrix directly.

On success, returns matrix.

On failure, raises Blendend.Error.

skew(matrix, kx, ky)

@spec skew(t(), number(), number()) :: {:ok, t()} | {:error, term()}

Skews (shears) the matrix by angles kx and ky (radians) and returns a new matrix.

On success, returns {:ok, matrix}.

On failure, returns {:error, reason}.

skew!(m, kx, ky)

@spec skew!(t(), number(), number()) :: t()

Same as skew/3, but returns the skewed matrix directly.

On success, returns matrix.

On failure, raises Blendend.Error.

to_list(m)

@spec to_list(t()) :: {:ok, [number()]} | {:error, term()}

Reads the matrix as [m00, m01, m10, m11, tx, ty].

On success, returns {:ok, list}.

On failure, returns {:error, reason}.

Examples:

use Blendend.Draw
m = matrix do
 rotate :math.pi
end

{:ok, ml} = Blendend.Matrix2D.to_list(m)
[-1.0, 0, 0, -1.0, 0.0, 0.0] # floating point noise discarded

to_list!(m)

@spec to_list!(t()) :: [number()]

Same as to_list/1, but returns the list directly.

On success, returns [m00, m01, m10, m11, tx, ty].

On failure, raises Blendend.Error.

transform(m, other)

@spec transform(t(), t()) :: {:ok, t()} | {:error, term()}

Returns matrix * other, i.e. the other transform is applied after matrix.

Examples:

iex> use Blendend.Draw
iex> translate = matrix(do: translate(10, 0))
iex> scale = matrix(do: scale(2, 1))
iex> {:ok, m} = Blendend.Matrix2D.transform(translate, scale)
iex> {:ok, list} = Blendend.Matrix2D.to_list(m)
iex> list
[2.0, 0.0, 0.0, 1.0, 10.0, 0.0]  # translate first, then scale (translation unchanged)

transform!(m, other)

@spec transform!(t(), t()) :: t()

Same as transform/2, but returns the matrix directly.

translate(m, x, y)

@spec translate(t(), number(), number()) :: {:ok, t()} | {:error, term()}

Translates the matrix by {tx, ty} and returns a new matrix.

On success, returns {:ok, matrix}.

On failure, returns {:error, reason}.

translate!(m, x, y)

@spec translate!(t(), number(), number()) :: t()

Same as translate/3, but returns the translated matrix directly.

On success, returns matrix.

On failure, raises Blendend.Error.