diff --git a/fractional/.swp b/fractional/.swp new file mode 100644 index 0000000..78dff2c Binary files /dev/null and b/fractional/.swp differ diff --git a/fractional/src/easel.rs b/fractional/src/easel.rs index 1a19379..f72a27e 100644 --- a/fractional/src/easel.rs +++ b/fractional/src/easel.rs @@ -56,46 +56,136 @@ pub struct Coordinate(pub i32, pub i32, pub T); #[derive(Debug, Clone)] pub struct Coordinates(pub Vec>); +#[derive(Debug, Clone)] +pub struct LineIterator where T: Debug { + a :Option> + , b :Coordinate + , dx :i32 + , dy :i32 + , dzx :T + , dzy :T + , sx :i32 + , sy :i32 + , err :i32 + , only_edges :bool +} + +impl Iterator for LineIterator +where T: Add + Debug + Copy + From { + type Item = Coordinate; + + fn next(&mut self) -> Option { + let Coordinate(ax, ay, az) = match self.a { + None => self.b, + Some(a) => a, + }; + let Coordinate(bx, by, _) = self.b; + + //println!("== {:?}", self); + + if ax != bx || ay != by { + match (2 * self.err >= self.dy, 2 * self.err <= self.dx ) { + (true, false) => { + let r = self.a; + self.a = Some(Coordinate(ax+self.sx, ay, az+self.dzx)); + self.err = self.err + self.dy; + if self.only_edges { self.next() } else { r } + }, + (false, true) => { + let r = self.a; + self.a = Some(Coordinate(ax, ay+self.sy, az+self.dzy)); + self.err = self.err + self.dx; + r + }, + _ => { + let r = self.a; + self.a = Some(Coordinate( ax + self.sx + , ay + self.sy + , az + self.dzy )); + self.err = self.err + self.dx + self.dy; + r + }, + } + } else { + match self.a { + None => None, + Some(a) => { self.a = None; Some(a) } + } + } + } +} + impl Coordinate where T: Add + Sub + Div - + Clone + Copy + From { + + Debug + Clone + Copy + From { + fn iter(self, b :&Self, only_edges :bool) -> LineIterator { + let Coordinate(ax, ay, az) = self; + let Coordinate(bx, by, bz) = *b; + + let dx = (bx - ax).abs(); + let dy = -(by - ay).abs(); + let size = cmp::min(dx, -dy); + let dz = (bz - az) / size.into(); + + LineIterator { a: Some(self) + , b: *b + , dx: dx + , dy: dy + , dzx: if size == dx { dz } else { 0.into() } + , dzy: if size == -dy { dz } else { 0.into() } + , sx: if ax < bx { 1 } else { -1 } + , sy: if ay < by { 1 } else { -1 } + , err: dx + dy + , only_edges: only_edges + } + } + // Tail recursive Bresenham line with integer incremental error. fn line(self, b :&Self) -> Vec { - fn inner( v :&mut [Coordinate] - , bx :i32, by :i32 - , dx :i32, dy :i32 - , sx :i32, sy :i32 - , dz :T, err :i32) - where T: Add + Copy { - - let Coordinate(x, y, z) = v[0]; - - if x != bx || y != by { - let (x, y, z, err) = match (2*err >= dy, 2*err <= dx) { - (true, false) => (x + sx, y, z + dz, err + dy ), - (false, true) => ( x, y + sy, z + dz, err + dx ), - _ => (x + sx, y + sy, z + dz, err + dx + dy ), - }; - v[1] = Coordinate(x, y, z); - inner(&mut v[1..], bx, by, dx, dy, sx, sy, dz, err); + self.iter(b, false).collect() + } + + /* + * Special line algorithm just putting the outermost x values per + * line into the resulting Vector. + * This expects y of b larger than y of self. + */ + fn edge(self, b :&Self) -> Vec { + println!("== New edge: {:?} - {:?}", self, b); + self.iter(b, true).collect() + /* + let Coordinate(mut x, mut y, mut z) = self; + let Coordinate( bx, by, bz) = *b; + + // next should be called with the negative of this… but dz depends + // on the positive this. + let dy = -(by - y).abs(); + let dx = (bx - x).abs(); + let sx = if x < bx { 1 } else { -1 }; + let dz = (bz - z) / (-dy).into(); + let mut err = dx + dy; + + let mut v = Vec::>::with_capacity((-dy) as usize); + + while y != by { + match (2*err >= dy, 2*err <= dx) { + (true, false) => { x = x + sx + ; err = err + dy }, + (false, true) => { v.push(Coordinate(x, y, z)) + ; y = y + 1 + ; z = z + dz + ; err = err + dx }, + _ => { v.push(Coordinate(x, y, z)) + ; x = x + sx + ; y = y + 1 + ; z = z + dz + ; err = err + dx + dy }, } } - let Coordinate(ax, ay, az) = self; - let Coordinate(bx, by, bz) = *b; - - let dx = (bx - ax).abs(); - let sx :i32 = if ax < bx { 1 } else { -1 }; - let dy = (by - ay).abs(); - let sy :i32 = if ay < by { 1 } else { -1 }; - let size = cmp::max(dx, dy); - let dz = (bz - az) / size.into(); - - let mut v :Vec = vec!( Coordinate(0, 0, 0.into()) - ; (size as usize) + 1); - v[0] = Coordinate(ax, ay, az); - inner(&mut v, bx, by, dx, -dy, sx, sy, dz, dx - dy); + v.push(*b); v + */ } } @@ -148,7 +238,7 @@ pub struct Line(pub Coordinate, pub Coordinate); impl Drawable for Line where T: Add + Sub + Div - + Clone + Copy + From { + + Debug + Clone + Copy + From { fn plot(&self) -> Coordinates { let Line(a, b) = *self; Coordinates(a.line(&b)) @@ -201,7 +291,7 @@ pub struct Polyline(pub Coordinates); impl Drawable for Polyline where T: Add + Sub + Div - + Clone + Copy + From { + + Debug + Clone + Copy + From { fn plot(&self) -> Coordinates { let Polyline(Coordinates(cs)) = self; @@ -235,7 +325,7 @@ pub struct Polygon(pub Coordinates); impl Drawable for Polygon where T: Add + Sub + Div - + Clone + Copy + From { + + Debug + Clone + Copy + From { fn plot(&self) -> Coordinates { let Polygon(Coordinates(cs)) = self; @@ -267,45 +357,6 @@ where T: Add + Sub + Div + Debug + Clone + Copy + From { fn fill(&self) -> Coordinates { - /* bresenham kind of thing to get the outer x values for each y of one - * edge of the polygon. */ - fn walk_edge( a :Coordinate - , b :Coordinate ) -> Vec> - where T: Add + Sub + Div - + From + Debug + Copy { - - let Coordinate(mut x, mut y, mut z) = a; - let Coordinate( bx, by, bz) = b; - - // next should be called with the negative of this… but dz depends - // on the positive this. - let dy = -(by - y).abs(); - let dx = (bx - x).abs(); - let sx = if x < bx { 1 } else { -1 }; - let dz = (bz - z) / (-dy).into(); - let mut err = dx + dy; - - let mut v = Vec::>::with_capacity((-dy) as usize); - - while y != by { - match (2*err >= dy, 2*err <= dx) { - (true, false) => { x = x + sx - ; err = err + dy }, - (false, true) => { v.push(Coordinate(x, y, z)) - ; y = y + 1 - ; z = z + dz - ; err = err + dx }, - _ => { v.push(Coordinate(x, y, z)) - ; x = x + sx - ; y = y + 1 - ; z = z + dz - ; err = err + dx + dy }, - } - } - - v - } - fn next_y( cs :&[Coordinate] , c :usize , f :&dyn Fn(usize) -> usize) -> Option { @@ -353,24 +404,22 @@ where T: Add + Sub + Div let mut l_edge :Vec> = Vec::new(); let mut r_edge :Vec> = Vec::new(); - while l.1 != None || r.1 != None { - match l.1 { - None => {}, - Some(a) => { - println!("== l: [{:?}] - {:?}", l, cs[a]); - l_edge.append(&mut walk_edge(cs[l.0], cs[a])); - l = (a, next_y(cs, a, &left)); + let append_edge = | v :&mut Vec> + , e :&(usize, Option) | { + match *e { + (_, None) => *e, + (a, Some(b)) => { + println!("== l: [{:?}] - {:?}", e, cs[b]); + let mut edge = cs[a].edge(&cs[b]); + v.append(&mut edge); + (b, next_y(cs, b, &left)) }, } + }; - match r.1 { - None => {}, - Some(a) => { - println!("== r: [{:?}] - {:?}", r, cs[a]); - r_edge.append(&mut walk_edge(cs[r.0], cs[a])); - r = (a, next_y(cs, a, &right)); - } - } + while l.1 != None || r.1 != None { + l = append_edge(&mut l_edge, &l); + r = append_edge(&mut r_edge, &r); } println!("== [{}] {:?}", l_edge.len(), l_edge); diff --git a/fractional/src/geometry.rs b/fractional/src/geometry.rs index 47d0bf0..74fca4d 100644 --- a/fractional/src/geometry.rs +++ b/fractional/src/geometry.rs @@ -379,11 +379,11 @@ where T: Add + Sub + Neg None }}; - let ps :Vec<(Polygon, u32)> = self.faces.iter() + let mut ps :Vec<(Polygon, u32)> = self.faces.iter() . filter_map(to_poly).collect(); // this sorts by the color value which is no longer neccessary as soon // as the z-buffer is complete. - // ps.sort_by(|a, b| a.1.cmp(&b.1)); + ps.sort_by(|a, b| a.1.cmp(&b.1)); ps } }