pub use super::{SuperCover, Line, Vector, TileNet, TileSet};
pub use interleave::{IterList, MultiIter};
pub struct Points<'a> {
index: usize,
offset: Vector,
points: &'a [(f32, f32)],
}
impl<'a> Points<'a> {
pub fn new(offset: Vector, points: &'a [(f32, f32)]) -> Points {
Points {
index: 0,
offset: offset,
points: points,
}
}
}
impl<'a> Iterator for Points<'a> {
type Item = (f32, f32);
fn next(&mut self) -> Option<Self::Item> {
let ret = self.points
.get(self.index)
.cloned()
.map(|x| Vector::from_tuple(x) + self.offset)
.map(|x| (x.0, x.1));
self.index += 1;
ret
}
}
pub trait Collable<T, S> {
fn points(&self) -> Points;
fn queued(&self) -> Vector;
fn resolve<I>(&mut self, set: TileSet<T, I>, state: &mut S) -> bool
where I: Iterator<Item = (i32, i32)>;
fn presolve(&mut self, _state: &mut S) {}
fn postsolve(&mut self, _collided_once: bool, _resolved: bool, _state: &mut S) {}
fn solve(&mut self, net: &TileNet<T>, state: &mut S) {
self.presolve(state);
static MAX_ITERATIONS: usize = 30;
let mut collided_once = false;
let mut resolved = false;
for _ in 0..MAX_ITERATIONS {
let tiles = net.collide_set(self.tiles());
if self.resolve(tiles, state) {
resolved = true;
break;
}
collided_once = true;
}
self.postsolve(collided_once, resolved, state);
}
fn tiles(&self) -> MultiIter<(i32, i32)> {
let origin = self.points();
let mut destination = self.points();
destination.offset += self.queued();
let mut multi = interleave!((i32, i32););
for point1 in origin {
let point2 = destination.next().unwrap();
let point1 = Vector::from_tuple(point1);
let point2 = Vector::from_tuple(point2);
let line = Line(point1, point2);
multi.push(Box::new(line.supercover()));
}
multi
}
}