lineic

Struct LinearInterpolator

Source
pub struct LinearInterpolator<'a, const N: usize, S: Numeric, T: Numeric> { /* private fields */ }
Expand description

A linear interpolator for a set of values.
Interpolates between a series of discrete value sets based on a range.

For example a traffic light system could be represented as:

use lineic::LinearInterpolator;

const RED: [u8; 3] = [0xB8, 0x1D, 0x13];
const YLW: [u8; 3] = [0xEF, 0xB7, 0x00];
const GRN: [u8; 3] = [0x00, 0x84, 0x50];

let interpolator = LinearInterpolator::new(0.0..=100.0, &[RED, YLW, GRN]);

/*
The result will be a linear interpolation between:
0..=50 => RED->YLW
50..=100 => YLW->GRN
*/

§Generics

This type has 3 generics:

  • N: The number of values in each set
  • S: The numeric type representing the range for inputs
  • T: The numeric type representing the values to interpolate between

S and T can be any type implementing the Numeric trait.

Implementations§

Source§

impl<'a, const N: usize, S: Numeric, T: Numeric> LinearInterpolator<'a, N, S, T>

Source

pub fn new(range: impl Into<ReversibleRange<S>>, value_sets: &[[T; N]]) -> Self

Create a new linear interpolator with the given range and value sets.
The provided range will be divided into equal segments based on the number of value sets.

§Panics

Panics if the number of value sets is too large to be represented by type S
For a non-panic variant, see Self::try_new

Examples found in repository?
examples/custom_types.rs (line 9)
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fn main() {
    //
    // An interpolator using the NumericUnicode type
    let interpolator: LinearInterpolator<1, u8, NumericUnicode> =
        LinearInterpolator::new(0..=26, &[['a'.into()], ['z'.into()]]);

    //
    // Perform an interpolation
    let result = interpolator.interpolate(17);
    println!(
        "The 17th letter of the alphabet is: {:?}",
        NumericUnicode::to_string(&result)
    );
}
More examples
Hide additional examples
examples/start_here.rs (lines 21-24)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
fn main() {
    // The simplest possible use of the library is mapping one range to another
    // Here we can map values in the range 0.0..=10.0 to the range 30.0..=35.0
    let interpolator = F32InterpolationBucket::new(0.0..=10.0, [30.0], [35.0]);
    assert_eq!(interpolator.interpolate(5.0), [32.5]);

    // The target does not have to be a single value - here we interpolate across a pair of RGB values
    // The result is a smooth gradient from red to green for values in the range 0.0..=10.0
    let interpolator =
        F32InterpolationBucket::new(0.0..=10.0, [255.0, 0.0, 0.0], [0.0, 255.0, 0.0]);
    assert_eq!(interpolator.interpolate(5.0), [127.5, 127.5, 0.0]);

    // The library can also interpolate smoothly across multiple buckets
    // This example forms a sort of traffic light sequence, interpolating between red, yellow, and green
    // The range is reversed here to demonstrate that the library can handle that
    let interpolator = F32LinearInterpolator::new(
        10.0..=0.0,
        &[[0.0, 255.0, 0.0], [255.0, 255.0, 0.0], [255.0, 0.0, 0.0]],
    );
    assert_eq!(interpolator.interpolate(5.0), [255.0, 255.0, 0.0]);
    assert_eq!(interpolator.interpolate(0.0), [255.0, 0.0, 0.0]);

    // The types for the range and values do not need to the same
    // Here a f64 range is used to interpolate between u8 values
    let interpolator: LinearInterpolator<'_, 3, f64, u8> =
        LinearInterpolator::new(0.0..=10.0, &[[0, 255, 0], [255, 255, 0], [255, 0, 0]]);
    assert_eq!(interpolator.interpolate(5.0), [127, 127, 0]);
    assert_eq!(interpolator.interpolate(0.0), [0, 255, 0]);
}
Source

pub fn try_new( range: impl Into<ReversibleRange<S>>, value_sets: &[[T; N]], ) -> Option<Self>

Create a new linear interpolator with the given range and value sets.
The provided range will be divided into equal segments based on the number of value sets.

Returns None if the number of value sets is too large to be represented by type S.
This is the non-panic variant of Self::new

Source

pub const fn new_from_raw(buckets: &'a [InterpolationBucket<N, S, T>]) -> Self

Create a new linear interpolator from a raw slice of buckets.

Primarily used for static or const interpolators.

Another way to create a const interpolator is with the [static_interpolator!] macro.

§Example
use lineic::{InterpolationBucket, LinearInterpolator};
const INTERPOLATOR: LinearInterpolator<3, f32, f32> = LinearInterpolator::new_from_raw(&[
    InterpolationBucket::new_const((0.0, 50.0), [0.0, 0.0, 0.0], [1.0, 1.0, 1.0]),
    InterpolationBucket::new_const((50.0, 100.0), [1.0, 1.0, 1.0], [2.0, 2.0, 2.0]),
]);
§Safety

Results will be unpredictable if the following are not enforced:

  • The range for the buckets must form a continuous range
  • The buckets must be sorted by range
Source

pub fn is_reversed(&self) -> bool

Returns true if the range for this interpolator has start > end

Source

pub fn buckets(&self) -> &[InterpolationBucket<N, S, T>]

Get the set of discrete interpolations this interpolator will use.

Source

pub fn get_bucket(&self, s: S) -> &InterpolationBucket<N, S, T>

Returns the bucket that contains the given value.

Source

pub fn interpolate(&self, s: S) -> [T; N]

Interpolate between the value sets based on the given value.
This will return a new set of values interpolated across the given range

Uses a binary search to locate the appropriate pair of values to interpolate between

Examples found in repository?
examples/custom_types.rs (line 13)
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fn main() {
    //
    // An interpolator using the NumericUnicode type
    let interpolator: LinearInterpolator<1, u8, NumericUnicode> =
        LinearInterpolator::new(0..=26, &[['a'.into()], ['z'.into()]]);

    //
    // Perform an interpolation
    let result = interpolator.interpolate(17);
    println!(
        "The 17th letter of the alphabet is: {:?}",
        NumericUnicode::to_string(&result)
    );
}
More examples
Hide additional examples
examples/start_here.rs (line 25)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
fn main() {
    // The simplest possible use of the library is mapping one range to another
    // Here we can map values in the range 0.0..=10.0 to the range 30.0..=35.0
    let interpolator = F32InterpolationBucket::new(0.0..=10.0, [30.0], [35.0]);
    assert_eq!(interpolator.interpolate(5.0), [32.5]);

    // The target does not have to be a single value - here we interpolate across a pair of RGB values
    // The result is a smooth gradient from red to green for values in the range 0.0..=10.0
    let interpolator =
        F32InterpolationBucket::new(0.0..=10.0, [255.0, 0.0, 0.0], [0.0, 255.0, 0.0]);
    assert_eq!(interpolator.interpolate(5.0), [127.5, 127.5, 0.0]);

    // The library can also interpolate smoothly across multiple buckets
    // This example forms a sort of traffic light sequence, interpolating between red, yellow, and green
    // The range is reversed here to demonstrate that the library can handle that
    let interpolator = F32LinearInterpolator::new(
        10.0..=0.0,
        &[[0.0, 255.0, 0.0], [255.0, 255.0, 0.0], [255.0, 0.0, 0.0]],
    );
    assert_eq!(interpolator.interpolate(5.0), [255.0, 255.0, 0.0]);
    assert_eq!(interpolator.interpolate(0.0), [255.0, 0.0, 0.0]);

    // The types for the range and values do not need to the same
    // Here a f64 range is used to interpolate between u8 values
    let interpolator: LinearInterpolator<'_, 3, f64, u8> =
        LinearInterpolator::new(0.0..=10.0, &[[0, 255, 0], [255, 255, 0], [255, 0, 0]]);
    assert_eq!(interpolator.interpolate(5.0), [127, 127, 0]);
    assert_eq!(interpolator.interpolate(0.0), [0, 255, 0]);
}
Source

pub fn reverse_interpolate(&self, values: &[T; N]) -> Option<S>

Attempt to find a value in the valid range that could produce the given set of values.

This may be slow, since all buckets may be checked

Trait Implementations§

Source§

impl<'a, const N: usize, S: Clone + Numeric, T: Clone + Numeric> Clone for LinearInterpolator<'a, N, S, T>

Source§

fn clone(&self) -> LinearInterpolator<'a, N, S, T>

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'a, const N: usize, S: Debug + Numeric, T: Debug + Numeric> Debug for LinearInterpolator<'a, N, S, T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a, const N: usize, S: PartialEq + Numeric, T: PartialEq + Numeric> PartialEq for LinearInterpolator<'a, N, S, T>

Source§

fn eq(&self, other: &LinearInterpolator<'a, N, S, T>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<'a, const N: usize, S: Numeric, T: Numeric> StructuralPartialEq for LinearInterpolator<'a, N, S, T>

Auto Trait Implementations§

§

impl<'a, const N: usize, S, T> Freeze for LinearInterpolator<'a, N, S, T>

§

impl<'a, const N: usize, S, T> RefUnwindSafe for LinearInterpolator<'a, N, S, T>

§

impl<'a, const N: usize, S, T> Send for LinearInterpolator<'a, N, S, T>
where S: Sync + Send, T: Sync + Send,

§

impl<'a, const N: usize, S, T> Sync for LinearInterpolator<'a, N, S, T>
where S: Sync, T: Sync,

§

impl<'a, const N: usize, S, T> Unpin for LinearInterpolator<'a, N, S, T>
where S: Unpin, T: Unpin,

§

impl<'a, const N: usize, S, T> UnwindSafe for LinearInterpolator<'a, N, S, T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dst: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.