mod common; use ccvl::*; fn main() -> std::process::ExitCode { common::process_image(|mut img| { let greyscale = img.map(|p| image::Luminance::from(p)); let edges = filter::canny(greyscale); for line in hough::lines(10.0, edges) { let ((x0, y0), (x1, y1)) = endpoints(line, img.extent); draw::line(x0, y0, x1, y1, &mut img, colours::RED); } img }) } fn endpoints( l: hough::Line, lim: image::Extent, ) -> ((usize, usize), (usize, usize)) { if l.theta.abs() < 1e-3 { ((l.rho as usize, 0), (l.rho as usize, lim.y - 1)) } else if l.theta - std::f32::consts::PI / 2.0 < 1e-3 { ((0, l.rho as usize), (lim.x - 1, l.rho as usize)) } else { let w = lim.x as f32 - 1e-3; let h = lim.y as f32 - 1e-3; let ros = l.rho / l.theta.sin(); let roc = l.rho / l.theta.cos(); let t = l.theta.tan(); let candidates: [(f32, f32); 4] = [(roc - h * t, h), (0.0, ros), (roc, 0.0), (w, ros - w / t)]; let res = candidates .into_iter() .filter(|p| in_bounds(p, lim)) .map(|(x, y)| (x as usize, y as usize)) .collect::>(); if res.len() != 2 { panic!("Unexpected number of endpoints for {:?}", l); } (res[0], res[1]) } } fn in_bounds(q: &(f32, f32), lim: image::Extent) -> bool { let x_in = 0.0 <= q.0 && q.0 < lim.x as f32; let y_in = 0.0 <= q.1 && q.1 < lim.y as f32; x_in && y_in }