You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
2.1 KiB
95 lines
2.1 KiB
3 months ago
|
/// 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>..<du-1, dv-1>
|
||
|
/// 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<Self::Item> {
|
||
|
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
|
||
|
}
|
||
|
}
|
||
|
}
|