Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement linear interpolation for some of the types. #203

Merged
merged 1 commit into from Jun 1, 2017
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Implement linear interpolation for some of the types.

  • Loading branch information
nical committed Jun 1, 2017
commit 7be629d634f3a7b939a57501cd15ba4169047fe9
@@ -13,6 +13,7 @@ use num::Zero;

use heapsize::HeapSizeOf;
use num_traits::{NumCast, Saturating};
use num::One;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::cmp::Ordering;
use std::ops::{Add, Sub, Mul, Div, Neg};
@@ -193,6 +194,18 @@ impl<Unit, T: Zero> Zero for Length<T, Unit> {
}
}

impl<T, U> Length<T, U>
where T: Copy + One + Add<Output=T> + Sub<Output=T> + Mul<Output=T> {
/// Linearly interpolate between this length and another length.
///
/// `t` is expected to be between zero and one.

This comment has been minimized.

@kvark

kvark Jun 1, 2017

Member

let's lift this expectation from a comment to a real debug_assert

This comment has been minimized.

@nical

nical Jun 1, 2017

Author Collaborator

I'd rather not. [0..1] is the range that "makes sense" but going beyond is common when when animating things that give a "spring" kind of effect (like the common over-scroll effects on mac). I don't know how to phrase that in a succinct way in the comment, but for most use use cases the interval [0..1] is the one that makes most sense.

#[inline]
pub fn lerp(&self, other: Self, t: T) -> Self {
let one_t = T::one() - t;
Length::new(one_t * self.get() + t * other.get())
}
}

#[cfg(test)]
mod tests {
use super::Length;
@@ -310,6 +310,21 @@ impl<T: NumCast + Copy, U> TypedPoint2D<T, U> {
}
}

impl<T, U> TypedPoint2D<T, U>
where T: Copy + One + Add<Output=T> + Sub<Output=T> + Mul<Output=T> {
/// Linearly interpolate between this point and another point.
///
/// `t` is expected to be between zero and one.
#[inline]
pub fn lerp(&self, other: Self, t: T) -> Self {
let one_t = T::one() - t;
point2(
one_t * self.x + t * other.x,
one_t * self.y + t * other.y,
)
}
}

impl<T: Copy+ApproxEq<T>, U> ApproxEq<Self> for TypedPoint2D<T, U> {
#[inline]
fn approx_epsilon() -> Self {
@@ -369,6 +384,22 @@ impl<T: Copy + One, U> TypedPoint3D<T, U> {
}
}

impl<T, U> TypedPoint3D<T, U>
where T: Copy + One + Add<Output=T> + Sub<Output=T> + Mul<Output=T> {
/// Linearly interpolate between this point and another point.
///
/// `t` is expected to be between zero and one.
#[inline]
pub fn lerp(&self, other: Self, t: T) -> Self {
let one_t = T::one() - t;
point3(
one_t * self.x + t * other.x,
one_t * self.y + t * other.y,
one_t * self.z + t * other.z,
)
}
}

impl<T: fmt::Debug, U> fmt::Debug for TypedPoint3D<T, U> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({:?},{:?},{:?})", self.x, self.y, self.z)
@@ -252,6 +252,20 @@ where T: Copy + Clone + Zero + PartialOrd + PartialEq + Add<T, Output=T> + Sub<T
}
}

impl<T, U> TypedRect<T, U>
where T: Copy + One + Add<Output=T> + Sub<Output=T> + Mul<Output=T> {
/// Linearly interpolate between this rectangle and another rectange.
///
/// `t` is expected to be between zero and one.
#[inline]
pub fn lerp(&self, other: Self, t: T) -> Self {
Self::new(
self.origin.lerp(other.origin, t),
self.size.lerp(other.size, t),
)
}
}

impl<T, U> TypedRect<T, U>
where T: Copy + Clone + PartialOrd + Add<T, Output=T> + Sub<T, Output=T> + Zero {
#[inline]
@@ -106,6 +106,21 @@ impl<T: Copy + Clone + Mul<T, Output=U>, U> TypedSize2D<T, U> {
pub fn area(&self) -> U { self.width * self.height }
}

impl<T, U> TypedSize2D<T, U>
where T: Copy + One + Add<Output=T> + Sub<Output=T> + Mul<Output=T> {
/// Linearly interpolate between this size and another size.
///
/// `t` is expected to be between zero and one.
#[inline]
pub fn lerp(&self, other: Self, t: T) -> Self {
let one_t = T::one() - t;
size2(
one_t * self.width + t * other.width,
one_t * self.height + t * other.height,
)
}
}

impl<T: Zero, U> TypedSize2D<T, U> {
pub fn zero() -> TypedSize2D<T, U> {
TypedSize2D::new(
@@ -147,6 +147,18 @@ where T: Copy + Mul<T, Output=T> + Add<T, Output=T> + Sub<T, Output=T> {
}
}

impl<T, U> TypedVector2D<T, U>
where T: Copy + One + Add<Output=T> + Sub<Output=T> + Mul<Output=T> {
/// Linearly interpolate between this vector and another vector.
///
/// `t` is expected to be between zero and one.
#[inline]
pub fn lerp(&self, other: Self, t: T) -> Self {
let one_t = T::one() - t;
(*self) * one_t + other * t
}
}

impl<T: Copy + Add<T, Output=T>, U> Add for TypedVector2D<T, U> {
type Output = Self;
fn add(self, other: Self) -> Self {
@@ -498,6 +510,18 @@ impl<T: Mul<T, Output=T> +
}
}

impl<T, U> TypedVector3D<T, U>
where T: Copy + One + Add<Output=T> + Sub<Output=T> + Mul<Output=T> {
/// Linearly interpolate between this vector and another vector.
///
/// `t` is expected to be between zero and one.
#[inline]
pub fn lerp(&self, other: Self, t: T) -> Self {
let one_t = T::one() - t;
(*self) * one_t + other * t
}
}

impl<T: Copy + Add<T, Output=T>, U> Add for TypedVector3D<T, U> {
type Output = TypedVector3D<T, U>;
#[inline]
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.