pub struct EvenCore<T> {
pub domain: Interval,
pub samples: Vec<T>,
}Expand description
The data core of a curve derived from evenly-spaced samples. The intention is to use this
in addition to explicit or inferred interpolation information in user-space in order to
implement curves using domain and sample_with.
The internals are made transparent to give curve authors freedom, but the provided constructor enforces the required invariants, and the methods maintain those invariants.
§Example
// Let's make a curve that interpolates evenly spaced samples using either linear interpolation
// or step "interpolation" — i.e. just using the most recent sample as the source of truth.
enum InterpolationMode {
Linear,
Step,
}
// Linear interpolation mode is driven by a trait.
trait LinearInterpolate {
fn lerp(&self, other: &Self, t: f32) -> Self;
}
// Step interpolation just uses an explicit function.
fn step<T: Clone>(first: &T, second: &T, t: f32) -> T {
if t >= 1.0 {
second.clone()
} else {
first.clone()
}
}
// Omitted: Implementing `LinearInterpolate` on relevant types; e.g. `f32`, `Vec3`, and so on.
// The curve itself uses `EvenCore` to hold the evenly-spaced samples, and the `sample_with`
// function will do all the work of interpolating once given a function to do it with.
struct MyCurve<T> {
core: EvenCore<T>,
interpolation_mode: InterpolationMode,
}
impl<T> Curve<T> for MyCurve<T>
where
T: LinearInterpolate + Clone,
{
fn domain(&self) -> Interval {
self.core.domain()
}
fn sample_unchecked(&self, t: f32) -> T {
// To sample this curve, check the interpolation mode and dispatch accordingly.
match self.interpolation_mode {
InterpolationMode::Linear => self.core.sample_with(t, <T as LinearInterpolate>::lerp),
InterpolationMode::Step => self.core.sample_with(t, step),
}
}
}Fields§
§domain: IntervalThe domain over which the samples are taken, which corresponds to the domain of the curve formed by interpolating them.
§Invariants
This must always be a bounded interval; i.e. its endpoints must be finite.
samples: Vec<T>The samples that are interpolated to extract values.
§Invariants
This must always have a length of at least 2.
Implementations§
Source§impl<T> EvenCore<T>
impl<T> EvenCore<T>
Sourcepub fn new(
domain: Interval,
samples: impl IntoIterator<Item = T>,
) -> Result<Self, EvenCoreError>
pub fn new( domain: Interval, samples: impl IntoIterator<Item = T>, ) -> Result<Self, EvenCoreError>
Create a new EvenCore from the specified domain and samples. The samples are
regarded to be evenly spaced within the given domain interval, so that the outermost
samples form the boundary of that interval. An error is returned if there are not at
least 2 samples or if the given domain is unbounded.
Sourcepub fn sample_with<I>(&self, t: f32, interpolation: I) -> T
pub fn sample_with<I>(&self, t: f32, interpolation: I) -> T
Obtain a value from the held samples using the given interpolation to interpolate
between adjacent samples.
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.
Sourcepub fn sample_interp(&self, t: f32) -> InterpolationDatum<&T>
pub fn sample_interp(&self, t: f32) -> InterpolationDatum<&T>
Given a time t, obtain a InterpolationDatum which governs how interpolation might recover
a sample at time t. For example, when a Between value is returned, its contents can
be used to interpolate between the two contained values with the given parameter. The other
variants give additional context about where the value is relative to the family of samples.
Sourcepub fn sample_interp_timed(&self, t: f32) -> InterpolationDatum<(f32, &T)>
pub fn sample_interp_timed(&self, t: f32) -> InterpolationDatum<(f32, &T)>
Like sample_interp, but the returned values include the sample times. This can be
useful when sample interpolation is not scale-invariant.
Trait Implementations§
Source§impl<'de, T> Deserialize<'de> for EvenCore<T>where
T: Deserialize<'de>,
impl<'de, T> Deserialize<'de> for EvenCore<T>where
T: Deserialize<'de>,
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl<T: PartialEq> StructuralPartialEq for EvenCore<T>
Auto Trait Implementations§
impl<T> Freeze for EvenCore<T>
impl<T> RefUnwindSafe for EvenCore<T>where
T: RefUnwindSafe,
impl<T> Send for EvenCore<T>where
T: Send,
impl<T> Sync for EvenCore<T>where
T: Sync,
impl<T> Unpin for EvenCore<T>where
T: Unpin,
impl<T> UnsafeUnpin for EvenCore<T>
impl<T> UnwindSafe for EvenCore<T>where
T: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
Source§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Serialize for T
impl<T> Serialize for T
fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>
fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>
Source§impl<T> TypeData for T
impl<T> TypeData for T
Source§fn clone_type_data(&self) -> Box<dyn TypeData>
fn clone_type_data(&self) -> Box<dyn TypeData>
self.