Curves (curves v0.2.5)

Copy Markdown View Source

Usage

# Create a bezier curve
curve = Curves.define_bezier(:ease_in)

# Find the {x, y} coordinate at 24% from the start
{x, y} = Curves.solve!(curve, 0.24)

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.

curve = Curves.define_bezier([
# {x,   y}
  {0,   0},    # Knot 0. AKA the start point
  {0,   0.5},  # Control Point 0
  {0.8, 0.4},  # Control Point 1
  {1,   1}     # Knot 1. AKA the stop point
])

t = 0.1234

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

Interactive tutorial

Be sure to check out the livebooks to see these points turn into graphs.

  1. Bezier Curves.
  2. Splines.

Options

All define_*, solve*, and take* functions can receive the following opts.

keydefaultdescription
:origin{0, 0}Provides an offset. every point in the curve will automatically be increased by this {x, y} coordinate
:float_dtype16One of 8, 16, 32, 64. Passed into Nx tensors as {:f, dtype}.
:force_percentfalseIf true, all results from take and solve are normalized as percentages of the max y coordinate defined

Summary

Functions

Define a new Curves.Spline.Type.CatmullRom. Only the joins need to be defined, the control points are calculated automatically.

Define a new Curves.Spline.Type.Hermite spline. Control points are calculated automatically based on the first derivative of each knot.

Given a Curves.Bezier.Curve or Curves.Spline.Curve struct, and t, find the point along the curve.

The raising version of solve/3

Take n samples, evenly spaced, from the curve.

The raising version of take/3

Functions

define_b_spline(points, opts \\ [])

Define a spline struct of type: Curves.Spline.Type.BSpline.

Only the knots need to be defined, the control points are calculated automatically.

Options

See available opts

curve = Curves.define_b_spline([
  {0, 0},
  {1, 0},
  {1, 1},
  {0, 1},
  {0, 2},
  {1, 2},
])

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

define_bezier(points, opts \\ [])

Build a new Curves.Bezier.Curve

Options

See available opts

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

define_bezier_spline(points, opts \\ [])

@spec define_bezier_spline(
  points :: [Curves.Utils.Types.point_list()],
  opts :: Curves.Utils.Types.define_opts()
) :: Curves.Spline.Curve.t()

Return a Curves.Spline.Curve struct representing a Curves.Spline.Type.BezierSpline. Can later be passed into solve/2.

Options

See available opts

points = [
  # P0
  [{5.0, 10.0},  # Knot
  {10.0, 10.0}], # control point 0

  # P1
  [{10.0, 5.0},  # Knot
    {5.0, 5.0},  # control point 0
    {15.0, 5.0}],# control point 1

  # P2
  [{15.0, 10.0}, # Knot
  {15.0, 6.0},  # control point 0
  {15.0, 14.0}  # control point 1
  ],

  # P3
  [{20.0, 15.0}, # Knot
  {18.0, 15.0}, # control point 0
  {23.0, 15.0}],# control point 1

  # P4
  [{30.0, 10.0}, # Knot
    {32.0, 5.0}] # control point 0
]
curves = Curves.define_bezier_spline(points)
{x, y} = Curves.solve!(curves, 0.518)

define_catmull_rom(points, opts \\ [])

Define a new Curves.Spline.Type.CatmullRom. Only the joins need to be defined, the control points are calculated automatically.

Options

See available opts

curve = Curves.define_catmull_rom([
  {0, 0},
  {1, 0},
  {1, 1},
  {0, 1},
  {0, 2},
  {1, 2},
])

{x, y} = Curves.solve!(curves, 0.5)

define_hermite(points, opts \\ [])

Define a new Curves.Spline.Type.Hermite spline. Control points are calculated automatically based on the first derivative of each knot.

Options

See available opts

Example

curve = Curves.define_hermite([
  {5, 10},
  {10, 5},
  {15, 10},
  {20, 10},
  {25, 5},
  {30, 15},
])

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

solve(curve, t, opts \\ [])

Given a Curves.Bezier.Curve or Curves.Spline.Curve struct, and t, find the point along the curve.

For a bezier curve, t must be between 0.0 and 1.0.

e.g. t = 0.5 means the coordinate at 50% through the bezier curve.

For splines, the range of t depends on the number of segments (number of knots - 1).

e.g. t = 0.5 means the coordinate at 50% through the first segment. But t = 1.5 is 50% through the next segment.

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!(curve, t, opts \\ [])

The raising version of solve/3

take(curve, n, opts \\ [])

Take n samples, evenly spaced, from the curve.

take!(curve, n, opts \\ [])

The raising version of take/3