bevy_math::curve

Trait Curve

Source
pub trait Curve<T> {
Show 26 methods // Required methods fn domain(&self) -> Interval; fn sample_unchecked(&self, t: f32) -> T; // Provided methods fn sample(&self, t: f32) -> Option<T> { ... } fn sample_clamped(&self, t: f32) -> T { ... } fn sample_iter( &self, iter: impl IntoIterator<Item = f32>, ) -> impl Iterator<Item = Option<T>> where Self: Sized { ... } fn sample_iter_unchecked( &self, iter: impl IntoIterator<Item = f32>, ) -> impl Iterator<Item = T> where Self: Sized { ... } fn sample_iter_clamped( &self, iter: impl IntoIterator<Item = f32>, ) -> impl Iterator<Item = T> where Self: Sized { ... } fn map<S, F>(self, f: F) -> MapCurve<T, S, Self, F> where Self: Sized, F: Fn(T) -> S { ... } fn reparametrize<F>( self, domain: Interval, f: F, ) -> ReparamCurve<T, Self, F> where Self: Sized, F: Fn(f32) -> f32 { ... } fn reparametrize_linear( self, domain: Interval, ) -> Result<LinearReparamCurve<T, Self>, LinearReparamError> where Self: Sized { ... } fn reparametrize_by_curve<C>( self, other: C, ) -> CurveReparamCurve<T, Self, C> where Self: Sized, C: Curve<f32> { ... } fn graph(self) -> GraphCurve<T, Self> where Self: Sized { ... } fn zip<S, C>( self, other: C, ) -> Result<ZipCurve<T, S, Self, C>, InvalidIntervalError> where Self: Sized, C: Curve<S> + Sized { ... } fn chain<C>(self, other: C) -> Result<ChainCurve<T, Self, C>, ChainError> where Self: Sized, C: Curve<T> { ... } fn reverse(self) -> Result<ReverseCurve<T, Self>, ReverseError> where Self: Sized { ... } fn repeat(self, count: usize) -> Result<RepeatCurve<T, Self>, RepeatError> where Self: Sized { ... } fn forever(self) -> Result<ForeverCurve<T, Self>, RepeatError> where Self: Sized { ... } fn ping_pong(self) -> Result<PingPongCurve<T, Self>, PingPongError> where Self: Sized { ... } fn chain_continue<C>( self, other: C, ) -> Result<ContinuationCurve<T, Self, C>, ChainError> where Self: Sized, T: VectorSpace, C: Curve<T> { ... } fn resample<I>( &self, segments: usize, interpolation: I, ) -> Result<SampleCurve<T, I>, ResamplingError> where Self: Sized, I: Fn(&T, &T, f32) -> T { ... } fn resample_auto( &self, segments: usize, ) -> Result<SampleAutoCurve<T>, ResamplingError> where Self: Sized, T: StableInterpolate { ... } fn samples( &self, samples: usize, ) -> Result<impl Iterator<Item = T>, ResamplingError> where Self: Sized { ... } fn resample_uneven<I>( &self, sample_times: impl IntoIterator<Item = f32>, interpolation: I, ) -> Result<UnevenSampleCurve<T, I>, ResamplingError> where Self: Sized, I: Fn(&T, &T, f32) -> T { ... } fn resample_uneven_auto( &self, sample_times: impl IntoIterator<Item = f32>, ) -> Result<UnevenSampleAutoCurve<T>, ResamplingError> where Self: Sized, T: StableInterpolate { ... } fn by_ref(&self) -> &Self where Self: Sized { ... } fn flip<U, V>(self) -> impl Curve<(V, U)> where Self: Sized + Curve<(U, V)> { ... }
}
Available on crate feature curve only.
Expand description

A trait for a type that can represent values of type T parametrized over a fixed interval.

Typical examples of this are actual geometric curves where T: VectorSpace, but other kinds of output data can be represented as well. See the module-level documentation for details.

Required Methods§

Source

fn domain(&self) -> Interval

The interval over which this curve is parametrized.

This is the range of values of t where we can sample the curve and receive valid output.

Source

fn sample_unchecked(&self, t: f32) -> T

Sample a point on this curve at the parameter value t, extracting the associated value. This is the unchecked version of sampling, which should only be used if the sample time t is already known to lie within the curve’s domain.

Values sampled from outside of a curve’s domain are generally considered invalid; data which is nonsensical or otherwise useless may be returned in such a circumstance, and extrapolation beyond a curve’s domain should not be relied upon.

Provided Methods§

Source

fn sample(&self, t: f32) -> Option<T>

Sample a point on this curve at the parameter value t, returning None if the point is outside of the curve’s domain.

Source

fn sample_clamped(&self, t: f32) -> T

Sample a point on this curve at the parameter value t, clamping t to lie inside the domain of the curve.

Source

fn sample_iter( &self, iter: impl IntoIterator<Item = f32>, ) -> impl Iterator<Item = Option<T>>
where Self: Sized,

Sample a collection of n >= 0 points on this curve at the parameter values t_n, returning None if the point is outside of the curve’s domain.

The samples are returned in the same order as the parameter values t_n were provided and will include all results. This leaves the responsibility for things like filtering and sorting to the user for maximum flexibility.

Source

fn sample_iter_unchecked( &self, iter: impl IntoIterator<Item = f32>, ) -> impl Iterator<Item = T>
where Self: Sized,

Sample a collection of n >= 0 points on this curve at the parameter values t_n, extracting the associated values. This is the unchecked version of sampling, which should only be used if the sample times t_n are already known to lie within the curve’s domain.

Values sampled from outside of a curve’s domain are generally considered invalid; data which is nonsensical or otherwise useless may be returned in such a circumstance, and extrapolation beyond a curve’s domain should not be relied upon.

The samples are returned in the same order as the parameter values t_n were provided and will include all results. This leaves the responsibility for things like filtering and sorting to the user for maximum flexibility.

Source

fn sample_iter_clamped( &self, iter: impl IntoIterator<Item = f32>, ) -> impl Iterator<Item = T>
where Self: Sized,

Sample a collection of n >= 0 points on this curve at the parameter values t_n, clamping t_n to lie inside the domain of the curve.

The samples are returned in the same order as the parameter values t_n were provided and will include all results. This leaves the responsibility for things like filtering and sorting to the user for maximum flexibility.

Source

fn map<S, F>(self, f: F) -> MapCurve<T, S, Self, F>
where Self: Sized, F: Fn(T) -> S,

Create a new curve by mapping the values of this curve via a function f; i.e., if the sample at time t for this curve is x, the value at time t on the new curve will be f(x).

Source

fn reparametrize<F>(self, domain: Interval, f: F) -> ReparamCurve<T, Self, F>
where Self: Sized, F: Fn(f32) -> f32,

Create a new Curve whose parameter space is related to the parameter space of this curve by f. For each time t, the sample from the new curve at time t is the sample from this curve at time f(t). The given domain will be the domain of the new curve. The function f is expected to take domain into self.domain().

Note that this is the opposite of what one might expect intuitively; for example, if this curve has a parameter domain of [0, 1], then stretching the parameter domain to [0, 2] would be performed as follows, dividing by what might be perceived as the scaling factor rather than multiplying:

let my_curve = ConstantCurve::new(Interval::UNIT, 1.0);
let scaled_curve = my_curve.reparametrize(interval(0.0, 2.0).unwrap(), |t| t / 2.0);

This kind of linear remapping is provided by the convenience method Curve::reparametrize_linear, which requires only the desired domain for the new curve.

§Examples
// Reverse a curve:
let my_curve = ConstantCurve::new(Interval::UNIT, 1.0);
let domain = my_curve.domain();
let reversed_curve = my_curve.reparametrize(domain, |t| domain.end() - (t - domain.start()));

// Take a segment of a curve:
let curve_segment = my_curve.reparametrize(interval(0.0, 0.5).unwrap(), |t| 0.5 + t);
Source

fn reparametrize_linear( self, domain: Interval, ) -> Result<LinearReparamCurve<T, Self>, LinearReparamError>
where Self: Sized,

Linearly reparametrize this Curve, producing a new curve whose domain is the given domain instead of the current one. This operation is only valid for curves with bounded domains; if either this curve’s domain or the given domain is unbounded, an error is returned.

Source

fn reparametrize_by_curve<C>(self, other: C) -> CurveReparamCurve<T, Self, C>
where Self: Sized, C: Curve<f32>,

Reparametrize this Curve by sampling from another curve.

The resulting curve samples at time t by first sampling other at time t, which produces another sample time s which is then used to sample this curve. The domain of the resulting curve is the domain of other.

Source

fn graph(self) -> GraphCurve<T, Self>
where Self: Sized,

Create a new Curve which is the graph of this one; that is, its output echoes the sample time as part of a tuple.

For example, if this curve outputs x at time t, then the produced curve will produce (t, x) at time t. In particular, if this curve is a Curve<T>, the output of this method is a Curve<(f32, T)>.

Source

fn zip<S, C>( self, other: C, ) -> Result<ZipCurve<T, S, Self, C>, InvalidIntervalError>
where Self: Sized, C: Curve<S> + Sized,

Create a new Curve by zipping this curve together with another.

The sample at time t in the new curve is (x, y), where x is the sample of self at time t and y is the sample of other at time t. The domain of the new curve is the intersection of the domains of its constituents. If the domain intersection would be empty, an error is returned.

Source

fn chain<C>(self, other: C) -> Result<ChainCurve<T, Self, C>, ChainError>
where Self: Sized, C: Curve<T>,

Create a new Curve by composing this curve end-to-start with another, producing another curve with outputs of the same type. The domain of the other curve is translated so that its start coincides with where this curve ends.

§Errors

A ChainError is returned if this curve’s domain doesn’t have a finite end or if other’s domain doesn’t have a finite start.

Source

fn reverse(self) -> Result<ReverseCurve<T, Self>, ReverseError>
where Self: Sized,

Create a new Curve inverting this curve on the x-axis, producing another curve with outputs of the same type, effectively playing backwards starting at self.domain().end() and transitioning over to self.domain().start(). The domain of the new curve is still the same.

§Error

A ReverseError is returned if this curve’s domain isn’t bounded.

Source

fn repeat(self, count: usize) -> Result<RepeatCurve<T, Self>, RepeatError>
where Self: Sized,

Create a new Curve repeating this curve N times, producing another curve with outputs of the same type. The domain of the new curve will be bigger by a factor of n + 1.

§Notes
  • this doesn’t guarantee a smooth transition from one occurrence of the curve to its next iteration. The curve will make a jump if self.domain().start() != self.domain().end()!
  • for count == 0 the output of this adaptor is basically identical to the previous curve
  • the value at the transitioning points (domain.end() * n for n >= 1) in the results is the value at domain.end() in the original curve
§Error

A RepeatError is returned if this curve’s domain isn’t bounded.

Source

fn forever(self) -> Result<ForeverCurve<T, Self>, RepeatError>
where Self: Sized,

Create a new Curve repeating this curve forever, producing another curve with outputs of the same type. The domain of the new curve will be unbounded.

§Notes
  • this doesn’t guarantee a smooth transition from one occurrence of the curve to its next iteration. The curve will make a jump if self.domain().start() != self.domain().end()!
  • the value at the transitioning points (domain.end() * n for n >= 1) in the results is the value at domain.end() in the original curve
§Error

A RepeatError is returned if this curve’s domain isn’t bounded.

Source

fn ping_pong(self) -> Result<PingPongCurve<T, Self>, PingPongError>
where Self: Sized,

Create a new Curve chaining the original curve with its inverse, producing another curve with outputs of the same type. The domain of the new curve will be twice as long. The transition point is guaranteed to not make any jumps.

§Error

A PingPongError is returned if this curve’s domain isn’t right-finite.

Source

fn chain_continue<C>( self, other: C, ) -> Result<ContinuationCurve<T, Self, C>, ChainError>
where Self: Sized, T: VectorSpace, C: Curve<T>,

Create a new Curve by composing this curve end-to-start with another, producing another curve with outputs of the same type. The domain of the other curve is translated so that its start coincides with where this curve ends.

Additionally the transition of the samples is guaranteed to make no sudden jumps. This is useful if you really just know about the shapes of your curves and don’t want to deal with stitching them together properly when it would just introduce useless complexity. It is realized by translating the other curve so that its start sample point coincides with the current curves’ end sample point.

§Error

A ChainError is returned if this curve’s domain doesn’t have a finite end or if other’s domain doesn’t have a finite start.

Source

fn resample<I>( &self, segments: usize, interpolation: I, ) -> Result<SampleCurve<T, I>, ResamplingError>
where Self: Sized, I: Fn(&T, &T, f32) -> T,

Resample this Curve to produce a new one that is defined by interpolation over equally spaced sample values, using the provided interpolation to interpolate between adjacent samples. The curve is interpolated on segments segments between samples. For example, if segments is 1, only the start and end points of the curve are used as samples; if segments is 2, a sample at the midpoint is taken as well, and so on. If segments is zero, or if this curve has an unbounded domain, then a ResamplingError is returned.

The interpolation takes two values by reference together with a scalar parameter and produces an owned value. The expectation is that interpolation(&x, &y, 0.0) and interpolation(&x, &y, 1.0) are equivalent to x and y respectively.

§Example
let quarter_rotation = FunctionCurve::new(interval(0.0, 90.0).unwrap(), |t| Rot2::degrees(t));
// A curve which only stores three data points and uses `nlerp` to interpolate them:
let resampled_rotation = quarter_rotation.resample(3, |x, y, t| x.nlerp(*y, t));
Source

fn resample_auto( &self, segments: usize, ) -> Result<SampleAutoCurve<T>, ResamplingError>
where Self: Sized, T: StableInterpolate,

Resample this Curve to produce a new one that is defined by interpolation over equally spaced sample values, using automatic interpolation to interpolate between adjacent samples. The curve is interpolated on segments segments between samples. For example, if segments is 1, only the start and end points of the curve are used as samples; if segments is 2, a sample at the midpoint is taken as well, and so on. If segments is zero, or if this curve has an unbounded domain, then a ResamplingError is returned.

Source

fn samples( &self, samples: usize, ) -> Result<impl Iterator<Item = T>, ResamplingError>
where Self: Sized,

Extract an iterator over evenly-spaced samples from this curve. If samples is less than 2 or if this curve has unbounded domain, then an error is returned instead.

Source

fn resample_uneven<I>( &self, sample_times: impl IntoIterator<Item = f32>, interpolation: I, ) -> Result<UnevenSampleCurve<T, I>, ResamplingError>
where Self: Sized, I: Fn(&T, &T, f32) -> T,

Resample this Curve to produce a new one that is defined by interpolation over samples taken at a given set of times. The given interpolation is used to interpolate adjacent samples, and the sample_times are expected to contain at least two valid times within the curve’s domain interval.

Redundant sample times, non-finite sample times, and sample times outside of the domain are simply filtered out. With an insufficient quantity of data, a ResamplingError is returned.

The domain of the produced curve stretches between the first and last sample times of the iterator.

The interpolation takes two values by reference together with a scalar parameter and produces an owned value. The expectation is that interpolation(&x, &y, 0.0) and interpolation(&x, &y, 1.0) are equivalent to x and y respectively.

Source

fn resample_uneven_auto( &self, sample_times: impl IntoIterator<Item = f32>, ) -> Result<UnevenSampleAutoCurve<T>, ResamplingError>
where Self: Sized, T: StableInterpolate,

Resample this Curve to produce a new one that is defined by automatic interpolation over samples taken at the given set of times. The given sample_times are expected to contain at least two valid times within the curve’s domain interval.

Redundant sample times, non-finite sample times, and sample times outside of the domain are simply filtered out. With an insufficient quantity of data, a ResamplingError is returned.

The domain of the produced UnevenSampleAutoCurve stretches between the first and last sample times of the iterator.

Source

fn by_ref(&self) -> &Self
where Self: Sized,

Borrow this curve rather than taking ownership of it. This is essentially an alias for a prefix &; the point is that intermediate operations can be performed while retaining access to the original curve.

§Example
let my_curve = FunctionCurve::new(Interval::UNIT, |t| t * t + 1.0);

// Borrow `my_curve` long enough to resample a mapped version. Note that `map` takes
// ownership of its input.
let samples = my_curve.by_ref().map(|x| x * 2.0).resample_auto(100).unwrap();

// Do something else with `my_curve` since we retained ownership:
let new_curve = my_curve.reparametrize_linear(interval(-1.0, 1.0).unwrap()).unwrap();
Source

fn flip<U, V>(self) -> impl Curve<(V, U)>
where Self: Sized + Curve<(U, V)>,

Flip this curve so that its tuple output is arranged the other way.

Implementors§

Source§

impl<P: VectorSpace> Curve<P> for CubicCurve<P>

Source§

impl<P: VectorSpace> Curve<P> for CubicSegment<P>

Source§

impl<P: VectorSpace> Curve<P> for RationalCurve<P>

Source§

impl<P: VectorSpace> Curve<P> for RationalSegment<P>

Source§

impl<S, T, C, D> Curve<(S, T)> for ZipCurve<S, T, C, D>
where C: Curve<S>, D: Curve<T>,

Source§

impl<S, T, C, F> Curve<T> for MapCurve<S, T, C, F>
where C: Curve<S>, F: Fn(S) -> T,

Source§

impl<T> Curve<T> for ConstantCurve<T>
where T: Clone,

Source§

impl<T> Curve<T> for EasingCurve<T>
where T: Ease + Clone,

Source§

impl<T> Curve<T> for SampleAutoCurve<T>

Source§

impl<T> Curve<T> for UnevenSampleAutoCurve<T>

Source§

impl<T, C> Curve<(f32, T)> for GraphCurve<T, C>
where C: Curve<T>,

Source§

impl<T, C> Curve<T> for ForeverCurve<T, C>
where C: Curve<T>,

Source§

impl<T, C> Curve<T> for LinearReparamCurve<T, C>
where C: Curve<T>,

Source§

impl<T, C> Curve<T> for PingPongCurve<T, C>
where C: Curve<T>,

Source§

impl<T, C> Curve<T> for RepeatCurve<T, C>
where C: Curve<T>,

Source§

impl<T, C> Curve<T> for ReverseCurve<T, C>
where C: Curve<T>,

Source§

impl<T, C, D> Curve<T> for ChainCurve<T, C, D>
where C: Curve<T>, D: Curve<T>,

Source§

impl<T, C, D> Curve<T> for ContinuationCurve<T, C, D>
where T: VectorSpace, C: Curve<T>, D: Curve<T>,

Source§

impl<T, C, D> Curve<T> for CurveReparamCurve<T, C, D>
where C: Curve<T>, D: Curve<f32>,

Source§

impl<T, C, D> Curve<T> for D
where C: Curve<T> + ?Sized, D: Deref<Target = C>,

Source§

impl<T, C, F> Curve<T> for ReparamCurve<T, C, F>
where C: Curve<T>, F: Fn(f32) -> f32,

Source§

impl<T, F> Curve<T> for FunctionCurve<T, F>
where F: Fn(f32) -> T,

Source§

impl<T, I> Curve<T> for SampleCurve<T, I>
where T: Clone, I: Fn(&T, &T, f32) -> T,

Source§

impl<T, I> Curve<T> for UnevenSampleCurve<T, I>
where T: Clone, I: Fn(&T, &T, f32) -> T,