From 1afb386f04df29896cfe2bf6444f831795bccc35 Mon Sep 17 00:00:00 2001 From: Gabe Venberg Date: Fri, 27 Oct 2023 13:45:45 -0500 Subject: [PATCH] refactored line drawing, broke out code. broke the line drawing driver into seperate module. --- src/heading_drawing.rs | 31 +++++++++++ src/line_drawing.rs | 113 ++++++++++++++++++++++++++++++----------- src/main.rs | 1 + 3 files changed, 115 insertions(+), 30 deletions(-) create mode 100644 src/heading_drawing.rs diff --git a/src/heading_drawing.rs b/src/heading_drawing.rs new file mode 100644 index 0000000..52b1dfe --- /dev/null +++ b/src/heading_drawing.rs @@ -0,0 +1,31 @@ +use crate::line_drawing::{draw_line, FourQuadrantMatrix, Line, UPoint}; + +#[derive(Debug, Clone, Copy)] +struct Sector { + total_sectors: u8, + sectors: u8, +} + +//heading starts at north, with the positive direction being clockwise. +//Heading ranges from -pi to pi. +// +//sectors have 0 at north an proceed clockwise, always being positive. +fn heading_to_sector(sectors: u8, heading: f32) -> Sector { + todo!() +} + +fn sector_to_line(sector: Sector, radius: usize) -> Line { + todo!() +} + +pub fn draw_heading( + heading: f32, + sectors: u8, +) -> FourQuadrantMatrix<{ X }, { Y }, u8> { + let mut ret = FourQuadrantMatrix::new(UPoint { x: X / 2, y: Y / 2 }); + draw_line::( + §or_to_line(heading_to_sector(sectors, heading), X.max(Y)), + &mut ret, + ); + ret +} diff --git a/src/line_drawing.rs b/src/line_drawing.rs index d03db08..cd4eceb 100644 --- a/src/line_drawing.rs +++ b/src/line_drawing.rs @@ -1,15 +1,16 @@ -use core::mem::swap; +use core::{mem::swap, ops::Index, ops::IndexMut}; -struct Point { - x: isize, - y: isize, +#[derive(Debug, Clone, Copy)] +pub struct Point { + pub x: isize, + pub y: isize, } impl Point { /// converts a point (representing a point on a 4 quadrant grid) into a upoint (representing a /// point on a 1 quadrant grid with the origin in the bottom-left corner). Returns none if /// the resulting point would have either number negative. - fn to_upoint(&self, zero_coord: &UPoint) -> Option { + pub fn to_upoint(self, zero_coord: &UPoint) -> Option { Some(UPoint { x: zero_coord.x.checked_add_signed(self.x)?, y: zero_coord.y.checked_add_signed(self.y)?, @@ -17,15 +18,16 @@ impl Point { } } -struct UPoint { - x: usize, - y: usize, +#[derive(Debug, Clone, Copy)] +pub struct UPoint { + pub x: usize, + pub y: usize, } impl UPoint { /// converts a upoint (representing a point on a 1 quadrant grid with the origin in the - /// bottom-left corner) into a point( representing a point on a 4 quadrant grid - pub fn to_point(&self, zero_coord: &UPoint) -> Point { + /// bottom-left corner) into a point( representing a point on a 4 quadrant grid) + pub fn to_point(self, zero_coord: &UPoint) -> Point { Point { x: zero_coord.x as isize - self.x as isize, y: zero_coord.y as isize - self.y as isize, @@ -33,44 +35,95 @@ impl UPoint { } } -fn draw_line( - mut p0: Point, - mut p1: Point, - matrix: &mut [[u8; X]; Y], +/// A matrix that allows negative co-oordinates. Will panic if referencing out of bounds, just like +/// a nomral matrix. +pub struct FourQuadrantMatrix { + matrix: [[T; X]; Y], + pub zero_coord: UPoint, +} + +impl FourQuadrantMatrix<{ X }, { Y }, T> +where + T: Copy, + T: Default, +{ + pub fn new(zero_coord: UPoint) -> FourQuadrantMatrix<{ X }, { Y }, T> { + FourQuadrantMatrix { + matrix: [[T::default(); X]; Y], + zero_coord, + } + } +} + +impl IndexMut for FourQuadrantMatrix<{ X }, { Y }, T> { + fn index_mut(&mut self, index: Point) -> &mut Self::Output { + let upoint = index + .to_upoint(&self.zero_coord) + .expect("would result in negative unsigned coordinate!"); + &mut self.matrix[upoint.x][upoint.y] + } +} + +impl Index for FourQuadrantMatrix<{ X }, { Y }, T> { + type Output = T; + + fn index(&self, index: Point) -> &Self::Output { + let upoint = index + .to_upoint(&self.zero_coord) + .expect("would result in negative unsigned coordinate!"); + &self.matrix[upoint.x][upoint.y] + } +} + +impl From> for [[T; X]; Y] { + fn from(value: FourQuadrantMatrix<{ X }, { Y }, T>) -> Self { + value.matrix + } +} + +#[derive(Debug, Clone, Copy)] +pub struct Line(pub Point, pub Point); + +//no boxes here! +#[derive(Debug, Clone, Copy)] +pub struct ULine(pub UPoint, pub UPoint); + +/// Renders a line into a matrix of pixels. +pub fn draw_line( + line: &Line, + matrix: &mut FourQuadrantMatrix<{ X }, { Y }, u8>, ) { - let steep = (p0.x - p1.x).abs() < (p0.y - p1.x).abs(); + let mut line = *line; + let steep = (line.0.x - line.1.x).abs() < (line.0.y - line.1.x).abs(); if steep { - swap(&mut p0.x, &mut p0.y); - swap(&mut p1.x, &mut p1.y); + swap(&mut line.0.x, &mut line.0.y); + swap(&mut line.1.x, &mut line.1.y); } - if p0.x > p1.x { - swap(&mut p0, &mut p1) + if line.0.x > line.1.x { + swap(&mut line.0.x, &mut line.1.x); + swap(&mut line.0.y, &mut line.1.y) } - let dx = p1.x - p0.x; - let dy = p1.y - p0.y; + let dx = line.1.x - line.0.x; + let dy = line.1.y - line.0.y; let derror2 = dy.abs() * 2; let mut error2 = 0; - let mut y = p0.y; + let mut y = line.0.y; - for x in p0.x..=p1.x { + for x in line.0.x..=line.1.x { if steep { - matrix[y as usize][x as usize] = 1; + matrix[Point { x: y, y: x }] = 1; } else { - matrix[x as usize][y as usize] = 1; + matrix[Point { x, y }] = 1; } error2 += derror2; if error2 > dx { - y += if p1.y > p0.y { 1 } else { -1 }; + y += if line.1.y > line.0.y { 1 } else { -1 }; error2 -= dx * 2 } } } - -fn heading_to_sector(sectors: u8, heading: f32) -> u8 { - todo!() -} diff --git a/src/main.rs b/src/main.rs index 5ec174e..4d829a0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,6 +17,7 @@ mod calibration; mod led; mod tilt_compensation; mod line_drawing; +mod heading_drawing; use microbit::{display::blocking::Display, hal::Timer};