refactored line drawing, broke out code.
broke the line drawing driver into seperate module.
This commit is contained in:
		
							parent
							
								
									0b363ed8e7
								
							
						
					
					
						commit
						1afb386f04
					
				
					 3 changed files with 115 additions and 30 deletions
				
			
		
							
								
								
									
										31
									
								
								src/heading_drawing.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/heading_drawing.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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<const X: usize, const Y: usize>(
 | 
			
		||||
    heading: f32,
 | 
			
		||||
    sectors: u8,
 | 
			
		||||
) -> FourQuadrantMatrix<{ X }, { Y }, u8> {
 | 
			
		||||
    let mut ret = FourQuadrantMatrix::new(UPoint { x: X / 2, y: Y / 2 });
 | 
			
		||||
    draw_line::<X, Y>(
 | 
			
		||||
        §or_to_line(heading_to_sector(sectors, heading), X.max(Y)),
 | 
			
		||||
        &mut ret,
 | 
			
		||||
    );
 | 
			
		||||
    ret
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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<UPoint> {
 | 
			
		||||
    pub fn to_upoint(self, zero_coord: &UPoint) -> Option<UPoint> {
 | 
			
		||||
        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<const X: usize, const Y: usize>(
 | 
			
		||||
    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<const X: usize, const Y: usize, T> {
 | 
			
		||||
    matrix: [[T; X]; Y],
 | 
			
		||||
    pub zero_coord: UPoint,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<const X: usize, const Y: usize, T> 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<T, const X: usize, const Y: usize> IndexMut<Point> 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<T, const X: usize, const Y: usize> Index<Point> 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<T, const X: usize, const Y: usize> From<FourQuadrantMatrix<{ X }, { Y }, T>> 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<const X: usize, const Y: usize>(
 | 
			
		||||
    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!()
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,7 @@ mod calibration;
 | 
			
		|||
mod led;
 | 
			
		||||
mod tilt_compensation;
 | 
			
		||||
mod line_drawing;
 | 
			
		||||
mod heading_drawing;
 | 
			
		||||
 | 
			
		||||
use microbit::{display::blocking::Display, hal::Timer};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue