Class Channel

Class Documentation

class Channel

A named, time-ordered sequence of keyframes that can be evaluated as a curve.

A Channel owns its keyframes, keeps them sorted by time, and applies the appropriate handle constraints as they are added or edited. Evaluating the channel at a given time interpolates between the surrounding keyframes according to each keyframe’s Function; times outside the keyframe range are resolved using the channel’s Extend settings.

Channels are created and owned by an Animation (the constructor is not public) via Animation::create_channel, which assigns each channel a unique, immutable Id. Channels are non-copyable; use Animation::copy_channel to duplicate one.

Public Functions

inline const std::string &name() const

The channel’s name.

inline void set_name(const std::string &name)

Renames the channel.

inline Id id() const

The channel’s unique, immutable identifier.

const Keyframe &create_keyframe(double time, double value, Function function = Function::Bezier, HandleMode handle_mode = HandleMode::Smooth)

Creates a keyframe at a time and value and inserts it in time order.

If a keyframe already exists within ~1/200s of time it is replaced rather than duplicated. The handles are computed from handle_mode.

Returns:

A reference to the stored keyframe.

const Keyframe &create_keyframe(const Point &position, Function function = Function::Bezier, HandleMode handle_mode = HandleMode::Smooth)

Creates a keyframe from a position point.

const Keyframe &create_keyframe(double time, double value, const Point &in_handle, const Point &out_handle, Function function = Function::Bezier, HandleMode handle_mode = HandleMode::Aligned)

Creates a keyframe with explicit in/out handles (defaults to HandleMode::Aligned).

const Keyframe &create_keyframe(const Point &position, const Point &in_handle, const Point &out_handle, Function function = Function::Bezier, HandleMode handle_mode = HandleMode::Aligned)

Creates a keyframe from a position point with explicit in/out handles.

const Keyframe &create_keyframe(const Keyframe &reference_keyframe)

Creates a keyframe by copying an existing one (replacing any keyframe at the same time).

const Keyframe &emplace_keyframe(Keyframe &&keyframe)

Inserts a keyframe by move, in time order.

See also

create_keyframe

bool has_keyframe(double time) const

True if a keyframe exists at (approximately) time.

void delete_keyframe(size_t index)

Removes the keyframe at index.

Throws:

std::out_of_range – if index is out of range.

const Keyframe &keyframe(size_t index) const

Returns the keyframe at index.

Throws:

std::out_of_range – if index is out of range.

inline const Keyframe &operator[](size_t index) const

Indexed access, equivalent to keyframe(index).

Throws:

std::out_of_range – if out of range.

const Keyframe &prev_keyframe(double time) const

Returns the last keyframe strictly before time.

Throws:

std::out_of_range – if the channel is empty or no earlier keyframe exists.

const Keyframe &next_keyframe(double time) const

Returns the first keyframe strictly after time.

Throws:

std::out_of_range – if the channel is empty or no later keyframe exists.

const Keyframe &closest_keyframe(double time) const

Returns the keyframe nearest time.

Throws:

std::out_of_range – if the channel is empty.

const std::vector<Keyframe> &keyframes() const

Direct read access to the time-ordered keyframe vector.

inline size_t size() const

Number of keyframes.

inline size_t num_keyframes() const

Number of keyframes (alias for size()).

inline bool empty() const

True if the channel has no keyframes.

void update_keyframe(size_t index, const Keyframe &keyframe)

Replaces the keyframe at index, re-sorting and re-applying constraints.

Throws:

std::out_of_range – if out of range.

void set_keyframe_time(size_t index, double time)

Sets the time of keyframe index, clamped between its neighbours.

Throws:

std::out_of_range – if out of range.

void set_keyframe_value(size_t index, double value)

Sets the value of keyframe index.

Throws:

std::out_of_range – if out of range.

void set_keyframe_position(size_t index, const Point &position)

Sets the position of keyframe index (time clamped between neighbours).

Throws:

std::out_of_range – if out of range.

void set_keyframe_position(size_t index, double time, double value)

Sets the position of keyframe index from a time and value.

Throws:

std::out_of_range – if out of range.

void set_keyframe_in_handle(size_t index, const Point &in_handle)

Sets the in-handle of keyframe index (re-applying handle constraints).

Throws:

std::out_of_range – if out of range.

void set_keyframe_out_handle(size_t index, const Point &out_handle)

Sets the out-handle of keyframe index (re-applying handle constraints).

Throws:

std::out_of_range – if out of range.

void set_keyframe_function(size_t index, Function function)

Sets the interpolation function of keyframe index.

Throws:

std::out_of_range – if out of range.

void set_keyframe_handle_mode(size_t index, HandleMode handle_mode)

Sets the handle mode of keyframe index.

Throws:

std::out_of_range – if out of range.

double evaluate(double time, double *prev_t = nullptr) const

Evaluates the channel’s value at time.

Interpolates between the surrounding keyframes; times outside the keyframe range follow the channel’s Extend settings. An empty channel returns 0.

Parameters:
  • time – The time to evaluate at.

  • prev_t – Optional Bézier solver seed (a previous parameter in [0,1]) used only as a convergence hint; it is not modified.

Returns:

The interpolated value.

std::vector<double> evaluate_range(double start_time, double end_time, int num_samples, RangeEnd range_end = RangeEnd::Exclusive) const

Evaluates num_samples evenly spaced values from start_time to end_time.

By default the range is half-open, as in evaluate_range_by_rate(): sample i is at start_time + i * (end_time - start_time) / num_samples, so the last sample is one step short of end_time and end_time itself is not sampled. Sampling 0 to 4 with 5 samples gives 0.0, 0.8, 1.6, 2.4 and 3.2.

Pass RangeEnd::Inclusive to divide the span by one less and land the last sample on end_time, giving 0.0, 1.0, 2.0, 3.0 and 4.0 for the same call. That is what plotting a curve or building a lookup table wants, where a sample is a point rather than the interval that follows it.

Exactly num_samples values are returned, including when start_time and end_time are equal, in which case they are all the value at that time.

Parameters:

range_end – Whether end_time is sampled; half-open by default.

Throws:

std::invalid_argument – if num_samples is negative, or if start_time is after end_time.

Returns:

A vector of num_samples values; empty if num_samples is 0.

std::vector<double> evaluate_range_by_rate(double start_time, double end_time, double sample_rate, RangeEnd range_end = RangeEnd::Exclusive) const

Evaluates values from start_time to end_time at a fixed sample rate.

Sample i is at start_time + i / sample_rate, so the spacing is exactly one sample period no matter what the range is.

By default the range is half-open and end_time is not sampled, so a span of n periods gives n samples: 4 seconds at 30 Hz yields 120 values, the last at 3.9667, not 121 ending on 4.0. Pass RangeEnd::Inclusive for the closing sample, giving 121.

The two differ only when the span is a whole number of periods, since that is the only case where a sample lands on end_time. A span that is not is rounded up either way, so the whole range is covered.

Parameters:
  • start_time – First time to sample.

  • end_time – Upper bound of the range, sampled only if range_end is RangeEnd::Inclusive.

  • sample_rate – Samples per unit time; must be positive.

  • range_end – Whether end_time is sampled; half-open by default.

Throws:

std::invalid_argument – if sample_rate is not positive, or if start_time is after end_time.

Returns:

A vector of num_samples() values, or a single value if start_time and end_time are equal.

double start_time() const

Time of the first keyframe (0 if empty).

double end_time() const

Time of the last keyframe (0 if empty).

double length() const

Duration spanned by the keyframes (end_time() - start_time()).

Extend extend_start() const

Extend behavior for times before the first keyframe.

Extend extend_end() const

Extend behavior for times after the last keyframe.

void set_extend_start(Extend extend)

Sets the extend behavior for times before the first keyframe.

void set_extend_end(Extend extend)

Sets the extend behavior for times after the last keyframe.

void copy_keyframes_from(const Channel &source)

Replaces this channel’s keyframes with a copy of source's keyframes.

Used by Animation::copy_channel; the channel’s own name and id are left unchanged.

bool operator==(const Channel &other) const

Equality across name and keyframes (the id is intentionally ignored).

bool operator!=(const Channel &other) const

Negation of operator==.

Protected Functions

Channel() = delete
Channel(const Channel&) = delete
Channel &operator=(const Channel&) = delete
Channel(Channel&&) = default
Channel &operator=(Channel&&) = default
inline explicit Channel(const std::string &name, uint64_t id)

Creates a channel with a name and unique id; used only by Animation.