e2rcore/implement/math/
linearinterp.rs

1extern crate mazth;
2
3use std::cmp;
4
5use self::mazth::mat::*;
6use interface::i_interpolate::*;
7
8#[derive(Debug)]
9#[derive(Clone)]
10pub struct LinearInterp {
11    pub _ctl: [ Mat4x1< f64 > ; 2 ],
12    pub _point: Mat4x1< f64 >,
13    pub _steps: i64,
14    pub _step_current: i64,
15}
16
17impl LinearInterp {
18    pub fn init( s: i64, cp0: Mat4x1< f64 >, cp1: Mat4x1< f64 > ) -> LinearInterp {
19        assert!( s > 2 );
20        LinearInterp {
21            _ctl: [ cp0, cp1 ],
22            _point: cp0, //start point
23            _steps: s,
24            _step_current: -1i64,
25        }
26    }
27}
28
29#[allow(unused_variables)]
30impl IInterpolate< Mat4x1< f64 > > for LinearInterp {
31    fn num_steps( & self ) -> u64 {
32        self._steps as u64
33    }
34    fn interp_delta( & mut self, steps: i64 ) -> Option< Mat4x1< f64 > > {
35        self._step_current = cmp::min( self._step_current + steps, self._steps );
36        self._step_current = cmp::max( self._step_current, -1 );
37
38        let clamp = if self._step_current < 0 {
39            0
40        } else if self._step_current >= self._steps {
41            self._steps - 1
42        } else {
43            self._step_current
44        };
45        let fraction = clamp as f64 / ( self._steps - 1 ) as f64;
46        let d = self._ctl[1].minus( &self._ctl[0] ).unwrap();
47        let offset = d.scale( fraction ).unwrap();
48        self._point = self._ctl[0].plus( &offset ).unwrap();
49        Some( self._point )
50    }
51    fn interp_current( & self ) -> Mat4x1< f64 > {
52        self._point
53    }
54    fn interp_is_end( & self ) -> bool {
55        self._step_current == self._steps
56    }
57    fn interp_is_start( & self ) -> bool {
58        self._step_current == -1
59    }
60    fn reset( & mut self ){
61        self._step_current = -1i64;
62    }
63}
64
65impl Iterator for LinearInterp { //required by IInterpolate
66    type Item = Mat4x1< f64 >;
67    fn next( & mut self ) -> Option< Mat4x1< f64 > > {
68        self._step_current = cmp::min( self._step_current + 1, self._steps );
69        if self._step_current == self._steps {
70            None
71        } else {
72            let clamp = if self._step_current < 0 {
73                0
74            } else if self._step_current >= self._steps {
75                self._steps
76            } else {
77                self._step_current
78            };
79            
80            let fraction = clamp as f64 / ( self._steps - 1 ) as f64;
81            let d = self._ctl[1].minus( &self._ctl[0] ).unwrap();
82            let offset = d.scale( fraction ).unwrap();
83            self._point = self._ctl[0].plus( &offset ).unwrap();
84            Some( self._point )
85        }
86    }
87}
88
89impl DoubleEndedIterator for LinearInterp {
90    fn next_back( & mut self ) -> Option< Mat4x1< f64 > > {
91        self._step_current = cmp::max( self._step_current - 1, -1 );
92        if self._step_current == -1 {
93            None 
94        } else {
95            let clamp = if self._step_current < 0 {
96                0
97            } else if self._step_current >= self._steps {
98                self._steps
99            } else {
100                self._step_current
101            };
102            
103            let fraction = clamp as f64 / ( self._steps - 1 ) as f64;
104            let d = self._ctl[1].minus( &self._ctl[0] ).unwrap();
105            let offset = d.scale( fraction ).unwrap();
106            self._point = self._ctl[0].plus( &offset ).unwrap();
107            Some( self._point )
108        }
109    }
110}