From 8f0edfaa14775e387ad3cbf852ce94e90a589790 Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Tue, 7 Jan 2020 07:05:08 +0100 Subject: [PATCH] Start making an iterator from the line algorithm --- fractional/.swp | Bin 0 -> 45056 bytes fractional/src/easel.rs | 227 ++++++++++++++++++++++--------------- fractional/src/geometry.rs | 4 +- 3 files changed, 140 insertions(+), 91 deletions(-) create mode 100644 fractional/.swp diff --git a/fractional/.swp b/fractional/.swp new file mode 100644 index 0000000000000000000000000000000000000000..78dff2cade354113b2f76d49b52d5b9ffc9828e4 GIT binary patch literal 45056 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 literal 0 HcmV?d00001 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 } }