eazy_data/interpolation/linear/
lerp.rs

1//! ## The Lerp Interpolating Linear Curve.
2
3// --- START of derived from `interpolation`.
4// origin: MIT https://github.com/PistonDevelopers/interpolation/blob/master/src/lerp.rs
5//
6// Copyright (c) 2015 PistonDevelopers, invisageable
7//
8// Permission is hereby granted, free of charge, to any person obtaining a
9// copy of this software and associated documentation files (the "Software"),
10// to deal in the Software without restriction, including without limitation
11// the rights to use, copy, modify, merge, publish, distribute, sublicense,
12// and/or sell copies of the Software, and to permit persons to whom the
13// Software is furnished to do so, subject to the following conditions:
14
15/// ### The Linear Interpolation.
16///
17/// Interpolates linearly a value between two floats with a linear easing.
18/// Useful to tweak a value from point A to point B. The progress value can be
19/// whatever you want — time, percentage, etc. in a range of `[0,1]`.
20///
21/// #### params.
22///
23/// |     |                            |
24/// |:----|:---------------------------|
25/// | `p` | The progress.              |
26/// | `a` | The `start` initial value. |
27/// | `b` | The `end` final value.     |
28///
29/// #### returns.
30///
31/// `f32` — The interpolated result between the two float values.
32///
33/// #### examples.
34///
35/// ```
36/// use eazy::interpolation::lerp::lerp;
37///
38/// let start   = 2.0;
39/// let end     = 8.0;
40/// let p       = lerp(0.1, start, end);
41///
42/// assert_eq!(p, 2.6);
43/// ```
44#[inline(always)]
45pub fn lerp<T: Lerp>(p: T::Scalar, a: T, b: T) -> T {
46  a.lerp(&b, &p)
47}
48
49/// Describes a type that can linearly interpolate between two points.
50pub trait Lerp {
51  /// The scaling type for linear interpolation.
52  type Scalar;
53
54  /// Given `self` and another point `other`, return a point on a line running
55  /// between the two that is `scalar` fraction of the distance between the
56  /// two points.
57  fn lerp(&self, other: &Self, scalar: &Self::Scalar) -> Self;
58}
59
60/// Implementation of `Lerp` for floats.
61macro_rules! impl_lerp_for_float {
62  ($($float: ident),*) => {
63    $(
64      impl Lerp for $float {
65        type Scalar = $float;
66
67        #[inline(always)]
68        fn lerp(&self, other: &$float, scalar: &$float) -> $float {
69          self + (other - self) * scalar
70        }
71      }
72    )*
73  };
74}
75
76impl_lerp_for_float!(f32, f64);
77
78/// Transitive impl of `Lerp` for arrays, given a length and index list
79macro_rules! impl_lerp_for_array {
80  ($len:expr; $($i:expr),*) => {
81    impl<T> Lerp for [T; $len] where T: Lerp {
82      type Scalar = T::Scalar;
83
84      #[inline(always)]
85      fn lerp(&self, other: &Self, scalar: &Self::Scalar) -> Self {
86        [
87          $(self[$i].lerp(&other[$i], scalar)),*
88        ]
89      }
90    }
91  }
92}
93
94impl_lerp_for_array!(1; 0);
95impl_lerp_for_array!(2; 0, 1);
96impl_lerp_for_array!(3; 0, 1, 2);
97impl_lerp_for_array!(4; 0, 1, 2, 3);
98impl_lerp_for_array!(5; 0, 1, 2, 3, 4);
99
100// --- END of derived from `interpolation`.