/// Iterator providing points on a line (using bresenham's algorithm) /// /// The iterator supplies coordinates of pixels relative to the /// line's start point. /// /// constraint: `du` >= `dv`, `start_u` < `du` /// /// for p in line_points(du, dv, start_u) { /// println!("{}, {}", p.u, p.v); // coordinates <0,radius>.. /// println!("{}", p.frac); // distance from the line <0..255> /// println!("{}", p.first); // `v` has changed /// println!("{}", p.last); // next `v` will change /// } /// /// `u` axis is the main and increments at each iteration. pub fn line_points(du: i16, dv: i16, start_u: i16) -> LinePoints { let mut d = 2 * du - 2 * dv; let mut y = 0; for _ in 0..start_u { if d <= 0 { d += 2 * du - 2 * dv; y += 1; } else { d -= 2 * dv; } } LinePoints { du, dv, d, u: start_u, v: y, first: true, } } pub struct LinePoints { du: i16, dv: i16, d: i16, u: i16, v: i16, first: bool, } #[derive(Copy, Clone)] pub struct LinePointsItem { pub u: i16, pub v: i16, pub frac: u8, pub first: bool, pub last: bool, } impl Iterator for LinePoints { type Item = LinePointsItem; #[inline(always)] fn next(&mut self) -> Option { if self.u < self.du { let frac = if self.dv < self.du { 255 - ((self.d + 2 * self.dv - 1) as i32 * 255 / (2 * self.du - 1) as i32) as u8 } else { 0 }; let next = LinePointsItem { u: self.u, v: self.v, frac, first: self.first, last: self.d <= 0, }; if self.d <= 0 { self.d += 2 * self.du - 2 * self.dv; self.v += 1; self.first = true; } else { self.d -= 2 * self.dv; self.first = false; } self.u += 1; Some(next) } else { None } } }