move more grid functionality into trait

This commit is contained in:
Vinzenz Schroeter 2024-05-18 14:11:20 +02:00
parent 79e963d045
commit 8adf563320
4 changed files with 99 additions and 32 deletions

View file

@ -9,17 +9,6 @@ pub struct ByteGrid {
}
impl ByteGrid {
/// Creates a new byte grid with the specified dimensions.
///
/// returns: ByteGrid initialized to 0.
pub fn new(width: usize, height: usize) -> Self {
Self {
data: vec![0; width * height],
width,
height,
}
}
/// Loads a byte grid with the specified dimensions from the provided data.
///
/// returns: ByteGrid that contains a copy of the provided data
@ -47,6 +36,17 @@ impl ByteGrid {
}
impl Grid<u8> for ByteGrid {
/// Creates a new byte grid with the specified dimensions.
///
/// returns: ByteGrid initialized to 0.
fn new(width: usize, height: usize) -> Self {
Self {
data: vec![0; width * height],
width,
height,
}
}
fn set(&mut self, x: usize, y: usize, value: u8) -> u8 {
self.check_indexes(x, y);
let pos = &mut self.data[x + y * self.width];
@ -71,6 +71,17 @@ impl Grid<u8> for ByteGrid {
fn height(&self) -> usize {
self.height
}
fn window(&self, x: usize, y: usize, w: usize, h: usize) -> Self {
let mut win = Self::new(w, h);
for win_x in 0..w {
for win_y in 0..h {
let value = self.get(x + win_x, y + win_y);
win.set(win_x, win_y, value);
}
}
win
}
}
impl DataRef for ByteGrid {

View file

@ -9,6 +9,16 @@ use crate::{
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Origin(pub u16, pub u16);
impl std::ops::Add<Origin> for Origin {
type Output = Origin;
fn add(self, rhs: Origin) -> Self::Output {
let Origin(x1, y1) = self;
let Origin(x2, y2) = rhs;
Origin(x1 + x2, y1 + y2)
}
}
/// Size defines the width and height of a window
#[derive(Debug, Clone, Copy)]
pub struct Size(pub u16, pub u16);

View file

@ -1,4 +1,6 @@
pub trait Grid<T> {
fn new(width: usize, height: usize) -> Self;
/// Sets the value at the specified position
///
/// returns: the old value
@ -15,4 +17,35 @@ pub trait Grid<T> {
/// the height in y-direction
fn height(&self) -> usize;
/// Creates a new instance containing the specified window.
///
/// Use concrete types to avoid boxing.
///
/// # Arguments
///
/// * `x`: column of the top left cell
/// * `y`: row of the top left cell
/// * `w`: size of window in x-direction
/// * `h`: size of window in y-direction
///
/// returns: Self
///
/// # Examples
/// To avoid boxing, this example is using the concrete type `ByteGrid`.
/// ```
/// use servicepoint2::{ByteGrid, Grid};
/// fn split(grid: ByteGrid) -> (ByteGrid, ByteGrid) {
/// assert!(grid.width() >= 2);
/// let split_x = grid.width() / 2;
/// let right_w = grid.width() - split_x;
///
/// let left = grid.window(0, 0, split_x, grid.height());
/// let right = grid.window(split_x, 0, right_w, grid.height());
/// (left, right)
/// }
///
/// let (l, r) = split(ByteGrid::new(9, 5));
/// ```
fn window(&self, x: usize, y: usize, w: usize, h: usize) -> Self;
}

View file

@ -9,27 +9,6 @@ pub struct PixelGrid {
}
impl PixelGrid {
/// Creates a new pixel grid with the specified dimensions.
///
/// # Arguments
///
/// * `width`: size in pixels in x-direction
/// * `height`: size in pixels in y-direction
///
/// returns: PixelGrid initialized to all pixels off
///
/// # Panics
///
/// - when the width is not dividable by 8
pub fn new(width: usize, height: usize) -> Self {
assert_eq!(width % 8, 0);
Self {
width,
height,
bit_vec: BitVec::new(width * height),
}
}
/// Creates a new pixel grid with the size of the whole screen.
pub fn max_sized() -> Self {
Self::new(PIXEL_WIDTH as usize, PIXEL_HEIGHT as usize)
@ -69,6 +48,27 @@ impl PixelGrid {
}
impl Grid<bool> for PixelGrid {
/// Creates a new pixel grid with the specified dimensions.
///
/// # Arguments
///
/// * `width`: size in pixels in x-direction
/// * `height`: size in pixels in y-direction
///
/// returns: PixelGrid initialized to all pixels off
///
/// # Panics
///
/// - when the width is not dividable by 8
fn new(width: usize, height: usize) -> Self {
assert_eq!(width % 8, 0);
Self {
width,
height,
bit_vec: BitVec::new(width * height),
}
}
fn set(&mut self, x: usize, y: usize, value: bool) -> bool {
self.check_indexes(x, y);
self.bit_vec.set(x + y * self.width, value)
@ -89,6 +89,19 @@ impl Grid<bool> for PixelGrid {
fn height(&self) -> usize {
self.height
}
fn window(&self, x: usize, y: usize, w: usize, h: usize) -> Self {
// TODO: how to deduplicate?
// this cannot be moved into the trait because there, Self is not Sized
let mut win = Self::new(w, h);
for win_x in 0..w {
for win_y in 0..h {
let value = self.get(x + win_x, y + win_y);
win.set(win_x, win_y, value);
}
}
win
}
}
impl DataRef for PixelGrid {