diff options
| author | Juan Manuel Tomás <jtomas1815@gmail.com> | 2021-01-17 20:14:18 -0300 | 
|---|---|---|
| committer | Juan Manuel Tomás <jtomas1815@gmail.com> | 2021-01-17 20:14:18 -0300 | 
| commit | 7141f388113f7ac0c8e8718826dd821fd6607434 (patch) | |
| tree | 04acfd7b5f84d9344964bfb102617c611e1cd7fa /src/lerp | |
| parent | b25771270f0fd1fe20432ce2c1a671a04bb57a50 (diff) | |
| download | bezier-7141f388113f7ac0c8e8718826dd821fd6607434.tar.gz bezier-7141f388113f7ac0c8e8718826dd821fd6607434.zip | |
Render control points
Diffstat (limited to 'src/lerp')
| -rw-r--r-- | src/lerp/poly.rs | 119 | ||||
| -rw-r--r-- | src/lerp/poly/iter.rs | 38 | 
2 files changed, 157 insertions, 0 deletions
| diff --git a/src/lerp/poly.rs b/src/lerp/poly.rs new file mode 100644 index 0000000..961c56c --- /dev/null +++ b/src/lerp/poly.rs @@ -0,0 +1,119 @@ +mod iter; + +use iter::Iter; +use std::fmt; +use std::ops::{Add, Mul, Sub}; + +#[derive(PartialEq, Debug, Clone)] +pub struct Poly { +    data: Vec<f32>, +    degree: usize, +} + +impl Poly { +    pub fn new(data: Vec<f32>) -> Poly { +        if data.len() > 0 { +            let mut i = data.len() - 1; +            while data[i] == 0.0 && i > 0 { +                i -= 1; +            } +            Poly { data, degree: i } +        } else { +            Poly { data, degree: 0 } +        } +    } + +    pub fn degree(&self) -> usize { +        self.degree +    } + +    fn iter(&self) -> Iter { +        Iter::new(self.data.clone(), self.degree()) +    } +} + +impl Add for &Poly { +    type Output = Poly; + +    fn add(self, other: Self) -> Poly { +        Poly::new(self.iter().zip(other.iter()).map(|(x, y)| x + y).collect()) +    } +} + +impl Sub for &Poly { +    type Output = Poly; + +    fn sub(self, other: Self) -> Poly { +        Poly::new(self.iter().zip(other.iter()).map(|(x, y)| x - y).collect()) +    } +} + +impl Mul for &Poly { +    type Output = Poly; + +    fn mul(self, other: Self) -> Poly { +        let mut r = Vec::new(); +        for i in 0..other.degree() + 1 { +            let mut prefix = vec![0.0; i]; +            let mut suffix: Vec<f32> = self +                .iter() +                .take(self.degree() + 1) +                .map(|x| x * other.data[i]) +                .collect(); +            prefix.append(&mut suffix); +            r.push(Poly::new(prefix)); +        } +        r.iter().fold(Poly::new(vec![0.0]), |acc, x| &acc + x) +    } +} + +impl fmt::Display for &Poly { +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +        let mut s = String::new(); +        for i in 0..self.data.len() { +            s.push_str(&self.data[i].clone().to_string()); +            if i < self.data.len() - 1 { +                s.push_str(", "); +            } +        } +        write!(f, "{}", s) +    } +} + +#[cfg(test)] +mod tests { +    use super::*; + +    #[test] +    fn mul_test() { +        let a = Poly::new(vec![1.0, 2.0, 3.0]); +        let b = Poly::new(vec![1.0, 2.0]); +        assert_eq!(&a * &b, Poly::new(vec![1.0, 4.0, 7.0, 6.0])); +    } + +    #[test] +    fn add_test() { +        let a = Poly::new(vec![1.0]); +        let b = Poly::new(vec![0.0, 0.0, 0.0, 1.0]); +        assert_eq!(&a + &b, Poly::new(vec![1.0, 0.0, 0.0, 1.0])); +    } + +    #[test] +    fn sub_test() { +        let a = Poly::new(vec![1.0, 2.0, 3.0]); +        let b = Poly::new(vec![1.0, 1.0, 1.0]); +        assert_eq!(&a - &b, Poly::new(vec![0.0, 1.0, 2.0])); +    } + +    #[test] +    fn degree_is_five() { +        let p = Poly::new(vec![0.0, 0.0, 0.0, 0.0, 0.0, 2.0]); +        assert_eq!(p.degree(), 5); +    } + +    #[test] +    fn degree_is_zero() { +        let p = Poly::new(vec![0.0; 6]); +        assert_eq!(p.degree(), 0); +    } +} diff --git a/src/lerp/poly/iter.rs b/src/lerp/poly/iter.rs new file mode 100644 index 0000000..90cc4b5 --- /dev/null +++ b/src/lerp/poly/iter.rs @@ -0,0 +1,38 @@ +use std::cmp; +use std::iter::{Take, Zip}; + +pub struct Iter { +    index: usize, +    data: Vec<f32>, +    degree: usize, +} + +impl Iter { +    pub fn new(data: Vec<f32>, degree: usize) -> Iter { +        Iter { +            index: 0, +            data, +            degree, +        } +    } + +    pub fn zip(self, other: Self) -> Zip<Take<Iter>, Take<Iter>> { +        let deg = cmp::max(self.degree, other.degree) + 1; +        let a = self.take(deg); +        let b = other.take(deg); +        a.zip(b) +    } +} + +impl Iterator for Iter { +    type Item = f32; + +    fn next(&mut self) -> Option<f32> { +        self.index += 1; +        if self.index <= self.data.len() { +            Some(self.data[self.index - 1]) +        } else { +            Some(0.0) +        } +    } +} | 
