# `Curves`
[🔗](https://github.com/greetingsfellowhumans/curves/blob/main/lib/curves.ex#L1)

The best way to explore this library is through the interactive [livebook](bezier_curves.html).

## Quickstart

The fastest way to get started is with the predefined bezier curves.
```elixir
bezier_type = :ease_in
curve = Curves.define_bezier(bezier_type)

t = 0.24 # i.e. 24%  from the beginning to the end of the curve.
{x, y} = Curves.solve!(curve, t)

assert is_float(x)
assert is_float(y)
```

For a list of all predefined bezier_types, use `Curves.Bezier.Predefined.list/0`

## Custom curves

You can also create a custom bezier curve by passing in a list of `{x, y}` tuples. They can be any combination of floats and integers.

```elixir
curve = Curves.define_bezier([
# {x,   y}
  {0,   0},
  {0,   0.5},
  {0.8, 0.4},
  {1,   1}
])

t = 0.248

{x, y} = Curves.solve!(curve, t)

assert is_float(x)
assert is_float(y)
```

# `t`

```elixir
@type t() :: float()
```

Float between 0.0 and 1.0, representing a percentage of progress from the first to last point.

# `define_bezier`

```elixir
@spec define_bezier(
  points ::
    Curves.Utils.Types.point_list() | Curves.Bezier.Predefined.curve_key(),
  Curves.Utils.Types.opts()
) :: Curves.Bezier.Curve.t()
```

Build a new Bezier Curve struct.

## Examples
    iex> c = Curves.define_bezier([{0.1, 0.9}, {0.5, 0.9}, {0.5, 0.1}, {0.75, 0.1}])
    iex> is_struct(c, Curves.Bezier.Curve)
    true

# `solve`

```elixir
@spec solve(Curves.Bezier.Curve.t(), t(), Curves.Utils.Types.opts()) ::
  {:ok, Curves.Utils.Types.point_tuple()} | {:error, term()}
```

Given a struct, and t, find the point along the curve

## Examples
    iex> c = Curves.define_bezier([{0.1, 0.9}, {0.5, 0.9}, {0.5, 0.1}, {0.75, 0.1}])
    iex> Curves.solve(c, 0.3)
    {:ok, {0.3695499897003174, 0.727199912071228}}

## Options
* `:float_dtype` (default: nil) | If set to an integer, passes results to Float.round(_, precision)

# `solve!`

```elixir
@spec solve!(Curves.Bezier.Curve.t(), t(), Curves.Utils.Types.opts()) ::
  Curves.Utils.Types.point_tuple()
```

The raising version of `solve/3`

# `take`

```elixir
@spec take(Curves.Bezier.Curve.t(), n :: pos_integer(), Curves.Utils.Types.opts()) ::
  {:ok, Curves.Utils.Types.point_list()} | {:error, term()}
```

Take `n` samples, evenly spaced, from the curve.

# `take!`

```elixir
@spec take!(Curves.Bezier.Curve.t(), n :: pos_integer(), Curves.Utils.Types.opts()) ::
  Curves.Utils.Types.point_list()
```

The raising version of `take/3`

---

*Consult [api-reference.md](api-reference.md) for complete listing*
