simple-chart 0.7.9

Simple line chart in bmp format.
Documentation
use DisplayPoint;
use flatmappairs::FlatMapPairs;
use std::iter::once;

pub struct Line {
    first: DisplayPoint,
    last: DisplayPoint,
    cur: DisplayPoint,
    dx: i32,
    dy: i32,
    x_sign: i32,
    y_sign: i32,
    step: f32,
}

impl Line {
    pub fn new(f: DisplayPoint, l: DisplayPoint) -> Self {
        let dx = (l.x as i32 - f.x as i32).abs() + 1;
        let dy = (l.y as i32 - f.y as i32).abs() + 1;
        let x_sign = if l.x > f.x { 1i32 } else { -1i32 };
        let y_sign = if l.y > f.y { 1i32 } else { -1i32 };
        let step = if dx >= dy {
            dx as f32 / dy as f32
        } else {
            dy as f32 / dx as f32
        };

        Line {
            first: f,
            last: l,
            cur: f,
            dx: dx,
            dy: dy,
            x_sign: x_sign,
            y_sign: y_sign,
            step: step,
        }
    }
}

impl Iterator for Line {
    type Item = DisplayPoint;

    fn next(&mut self) -> Option<Self::Item> {

        if self.first == self.last {
            return None;
        }

        let (x, y) = if self.dx >= self.dy {

            let old_cur = &self.cur;
            let old_x = old_cur.x;
            let old_delta = (old_x as f32 - self.first.x as f32).abs() % self.step;

            let x = old_x as i32 + self.x_sign;
            let new_delta = (x as f32 - self.first.x as f32).abs() % self.step;

            let y = if new_delta > old_delta {
                old_cur.y as i32
            } else {
                old_cur.y as i32 + self.y_sign
            };
            (x, y)
        } else {

            let old_cur = &self.cur;
            let old_y = old_cur.y;
            let old_delta = (old_y as f32 - self.first.y as f32).abs() % self.step;

            let y = old_y as i32 + self.y_sign;
            let new_delta = (y as f32 - self.first.y as f32).abs() % self.step;

            let x = if new_delta > old_delta {
                old_cur.x as i32
            } else {
                old_cur.x as i32 + self.x_sign
            };
            (x, y)
        };

        self.cur = DisplayPoint {
            x: x as usize,
            y: y as usize,
        };

        if self.cur == self.last {
            None
        } else {
            Some(self.cur)
        }
    }
}

pub fn extrapolate<'a>(points: Box<Iterator<Item = DisplayPoint> + 'a>)
                       -> Box<Iterator<Item = DisplayPoint> + 'a> {

    let it = FlatMapPairs::new(points,
                               |a: DisplayPoint, b: DisplayPoint| once(a).chain(Line::new(a, b)));
    Box::new(it)
}