|
|
|
@ -261,20 +261,22 @@ enum Direction { Left, Right } |
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct Polygon<T>(pub Coordinates<T>);
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
enum VertexIteratorMode { Vertex, Edge }
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct VertexIterator<'a,T> where T: Debug {
|
|
|
|
p :&'a Polygon<T>,
|
|
|
|
top :usize,
|
|
|
|
current :Option<usize>,
|
|
|
|
edge :Option<LineIterator<T>>,
|
|
|
|
mode :VertexIteratorMode,
|
|
|
|
direction :Direction,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a,T> VertexIterator<'a,T>
|
|
|
|
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
|
|
|
|
+ Debug + Copy + From<i32> {
|
|
|
|
|
|
|
|
fn new(p :&'a Polygon<T>, direction :Direction) -> Self {
|
|
|
|
fn edge(p :&'a Polygon<T>, direction :Direction) -> Self {
|
|
|
|
let top = p.vert_min(direction);
|
|
|
|
let next = p.next_y(top, direction);
|
|
|
|
let edge = match next {
|
|
|
|
@ -286,6 +288,19 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> |
|
|
|
, top: top
|
|
|
|
, current: next
|
|
|
|
, edge: edge
|
|
|
|
, mode: VertexIteratorMode::Edge
|
|
|
|
, direction: direction }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn vertex(p :&'a Polygon<T>, direction :Direction) -> Self {
|
|
|
|
let top = p.vert_min(direction);
|
|
|
|
let next = p.next_y(top, direction);
|
|
|
|
|
|
|
|
VertexIterator { p: p
|
|
|
|
, top: top
|
|
|
|
, current: next
|
|
|
|
, edge: None |
|
|
|
, mode: VertexIteratorMode::Vertex
|
|
|
|
, direction: direction }
|
|
|
|
}
|
|
|
|
|
|
|
|
@ -314,6 +329,8 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> |
|
|
|
type Item = Coordinate<T>;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
match self.mode {
|
|
|
|
VertexIteratorMode::Edge => {
|
|
|
|
// if for whatever reason edge is "None" finish this iterator.
|
|
|
|
let next = self.edge.as_mut()?.next();
|
|
|
|
|
|
|
|
@ -324,41 +341,69 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> |
|
|
|
self.next()
|
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
VertexIteratorMode::Vertex => {
|
|
|
|
let current = self.current?;
|
|
|
|
self.current = self.p.next_y(current, self.direction);
|
|
|
|
Some(self.p.vertex(current))
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Polygon<T>
|
|
|
|
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
|
|
|
|
+ Copy + Debug + From<i32> {
|
|
|
|
#[inline]
|
|
|
|
fn vertex(&self, v :usize) -> Coordinate<T> {
|
|
|
|
let Polygon(Coordinates(cs)) = self;
|
|
|
|
cs[v]
|
|
|
|
}
|
|
|
|
|
|
|
|
fn vert_min<'a>(&'a self, d :Direction) -> usize {
|
|
|
|
let Polygon(Coordinates(cs)) = self;
|
|
|
|
|
|
|
|
type ICoord<'a,T> = (usize, &'a Coordinate<T>);
|
|
|
|
|
|
|
|
// TODO I guess the problem here is that it does not account for the
|
|
|
|
// same y vertex on the beggining and the end. So i guess correct
|
|
|
|
// would be finding the first one and then dependings on the
|
|
|
|
// given direction either search left or right for same y's.
|
|
|
|
let fold = |acc :Option<ICoord<'a,T>>, x :ICoord<'a,T>|
|
|
|
|
match acc {
|
|
|
|
None => Some(x),
|
|
|
|
Some(a) => {
|
|
|
|
let Coordinate(_, ay, _) = a.1;
|
|
|
|
let Coordinate(_, xy, _) = x.1;
|
|
|
|
match d {
|
|
|
|
Direction::Left =>
|
|
|
|
if xy < ay {Some(x)} else {Some(a)},
|
|
|
|
Direction::Right =>
|
|
|
|
if xy <= ay {Some(x)} else {Some(a)},
|
|
|
|
}
|
|
|
|
if xy < ay {Some(x)} else {Some(a)}
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
cs.iter().enumerate().fold(None, fold).unwrap().0
|
|
|
|
let mut min = cs.iter().enumerate().fold(None, fold).unwrap().0;
|
|
|
|
let mut next = self.step(min, d);
|
|
|
|
|
|
|
|
while self.vertex(min).1 == self.vertex(next).1 {
|
|
|
|
min = next;
|
|
|
|
next = self.step(min, d);
|
|
|
|
}
|
|
|
|
|
|
|
|
min
|
|
|
|
}
|
|
|
|
|
|
|
|
fn left_edge(&self) -> VertexIterator<T> {
|
|
|
|
VertexIterator::edge(self, Direction::Left)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn right_edge(&self) -> VertexIterator<T> {
|
|
|
|
VertexIterator::edge(self, Direction::Right)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn left_vertices(&self) -> VertexIterator<T> {
|
|
|
|
VertexIterator::new(self, Direction::Left)
|
|
|
|
VertexIterator::vertex(self, Direction::Left)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn right_vertices(&self) -> VertexIterator<T> {
|
|
|
|
VertexIterator::new(self, Direction::Right)
|
|
|
|
VertexIterator::vertex(self, Direction::Right)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn left(&self, v :usize) -> usize {
|
|
|
|
@ -383,12 +428,6 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn vertex(&self, v :usize) -> Coordinate<T> {
|
|
|
|
let Polygon(Coordinates(cs)) = self;
|
|
|
|
cs[v]
|
|
|
|
}
|
|
|
|
|
|
|
|
fn next_y(&self, c :usize, d :Direction) -> Option<usize> {
|
|
|
|
fn inner<T>( p :&Polygon<T>
|
|
|
|
, c :usize |
|
|
|
@ -402,28 +441,30 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> |
|
|
|
let Coordinate(_, cy, _) = p.vertex(c);
|
|
|
|
let Coordinate(_, ny, _) = p.vertex(n);
|
|
|
|
|
|
|
|
match ny.cmp(&cy) {
|
|
|
|
cmp::Ordering::Less => None,
|
|
|
|
// TODO On equal we need to find out which one of both to
|
|
|
|
// keep in the list… (the outermost)
|
|
|
|
// But how can we find the outermost...
|
|
|
|
// I think it depends on the previous and next one
|
|
|
|
// which means this might not be best suited for
|
|
|
|
// a recursive approach...we could keep both...
|
|
|
|
// Anyway, it looks like this is only a problem
|
|
|
|
// for the first vertex so maybe it is enough
|
|
|
|
// to choose the correct one when starting which
|
|
|
|
// would be in the vert_min method.
|
|
|
|
// Well, after adding some logic to vert_min it
|
|
|
|
// seems it is also relevant for the last one.
|
|
|
|
cmp::Ordering::Equal => inner(p, c, p.step(n, d), d),
|
|
|
|
cmp::Ordering::Greater => Some(n),
|
|
|
|
}
|
|
|
|
if ny < cy { None } else { Some(n) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inner(self, c, self.step(c, d), d)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn debug(&self) {
|
|
|
|
let mut left = self.left_vertices();
|
|
|
|
let mut right = self.right_vertices();
|
|
|
|
|
|
|
|
if left.find(|l| right.find(|r| l.0 == r.0).is_some()).is_some() {
|
|
|
|
let left :Vec<Coordinate<T>> = self.left_vertices().collect();
|
|
|
|
let right :Vec<Coordinate<T>> = self.right_vertices().collect();
|
|
|
|
|
|
|
|
println!("===");
|
|
|
|
println!("== poly : {:?}", self);
|
|
|
|
println!("== ltop : {:?}", self.vert_min(Direction::Left));
|
|
|
|
println!("== rtop : {:?}", self.vert_min(Direction::Right));
|
|
|
|
println!("== left : {:?}", left);
|
|
|
|
println!("== right : {:?}", right);
|
|
|
|
println!("===");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Drawable<T> for Polygon<T>
|
|
|
|
@ -459,7 +500,7 @@ impl<T> Fillable<T> for Polygon<T> |
|
|
|
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
|
|
|
|
+ Debug + Clone + Copy + From<i32> {
|
|
|
|
fn fill(&self, canvas :&mut dyn Canvas<T>, color :u32) {
|
|
|
|
let scanlines = self.left_vertices().zip(self.right_vertices());
|
|
|
|
let scanlines = self.left_edge().zip(self.right_edge());
|
|
|
|
|
|
|
|
for l in scanlines.flat_map(|(l, r)| l.line_iter(&r)) {
|
|
|
|
canvas.set_pixel(l, color);
|
|
|
|
|