implicit 0.1.0

A library for playing with 2d implicit geometry
Documentation
use ::{OutputMode, RenderMode, SyncImplicit, Implicit, render, OutputDevice};
use ::geom::{Point, Rect, Matrix};

pub struct Scene {
    shapes: Vec<(Rect, Matrix, OutputMode)>,
    pub resolution: f32,
    total_bounding_box: Rect,
}

impl Scene {
    pub fn new() -> Scene {
        Scene {
            shapes: Vec::new(),
            total_bounding_box: Rect::null_at(&Point{x: 0.0, y: 0.0}),
            resolution: 2.0,
        }
    }

    pub fn add_shape<I: SyncImplicit>(&mut self, shape: &I, rendermode: RenderMode, matrix: Matrix) -> usize {
        let i = self.shapes.len();
        let bb = shape.bounding_box().unwrap();
        let new_bb = transform_bounding_box(bb, matrix);

        self.total_bounding_box = self.total_bounding_box.union_with(&new_bb);
        self.shapes.push((shape.bounding_box().unwrap(), matrix, render(shape, &rendermode, self.resolution, true)));
        i
    }

    pub fn add_again(&mut self, again: usize, matrix: Matrix) {
        let mut old = self.shapes[again].clone();
        old.1 = matrix;
        old.0 = transform_bounding_box(old.0, matrix);

        self.total_bounding_box = self.total_bounding_box.union_with(&old.0);
        self.shapes.push(old);
    }

    pub fn render_all<O: OutputDevice>(&self, out: &mut O) {
        out.set_size(self.total_bounding_box.width(), self.total_bounding_box.height());
        for &(_, matrix, ref rendered) in &self.shapes {
            match rendered {
                &OutputMode::Solid(_) => unimplemented!(),
                &OutputMode::Outline(ref lines) => {
                    for line in lines {
                        out.start_line();
                        let start = line[0];
                        for p in line {
                            out.add_point(matrix.transform_point(p));
                        }
                        out.add_point(matrix.transform_point(&start));
                        out.end_line();
                    }
                },
                &OutputMode::DashedLine(ref dashed) => {
                    for dashed_line in dashed {
                        for segment in dashed_line.segments() {
                            out.start_line();
                            for p in segment {
                                out.add_point(matrix.transform_point(p));
                            }
                            out.end_line();
                        }
                    }
                }
            }
        }
    }
}

pub fn transform_bounding_box(bb: Rect, matrix: Matrix) -> Rect {
    let a = matrix.transform_point(&bb.top_left());
    let b = matrix.transform_point(&bb.top_right());
    let c = matrix.transform_point(&bb.bottom_left());
    let d = matrix.transform_point(&bb.bottom_right());
    let mut new_bb = Rect::null_at(&a);
    new_bb.expand_to_include(&b);
    new_bb.expand_to_include(&c);
    new_bb.expand_to_include(&d);
    new_bb
}