quadrant 0.0.0

A small utility library for sampling matrices.
Documentation
use nav::Direction;
use ndarray::{Array2, s};

pub trait Mosaic {
    fn copy_region(&self, start: [usize; 2], size: [usize; 2]) -> Self;

    fn copy_border(&self, direction: Direction, size: usize) -> Self;

    fn tiles(&self, tile_size: usize, overlap: usize) -> Array2<Self>
    where
        Self: Sized;
}

impl<T: Clone> Mosaic for Array2<T> {
    fn copy_region(&self, start: [usize; 2], size: [usize; 2]) -> Self {
        let (height, width) = self.dim();
        debug_assert!(start[0] + size[0] <= height);
        debug_assert!(start[1] + size[1] <= width);
        debug_assert!(size.iter().all(|&s| s > 0));

        self.slice(s![
            start[0]..start[0] + size[0],
            start[1]..start[1] + size[1]
        ])
        .to_owned()
    }

    fn copy_border(&self, direction: Direction, size: usize) -> Self {
        let (height, width) = self.dim();
        debug_assert!(size > 0);

        let view = match direction {
            Direction::North => self.slice(s![0..size, ..]),
            Direction::East => self.slice(s![.., (width - size)..]),
            Direction::South => self.slice(s![(height - size).., ..]),
            Direction::West => self.slice(s![.., 0..size]),
        };

        view.to_owned()
    }

    fn tiles(&self, tile_size: usize, overlap: usize) -> Array2<Self> {
        let (height, width) = self.dim();
        debug_assert!(overlap < tile_size);
        debug_assert!(height >= tile_size);
        debug_assert!(width >= tile_size);
        debug_assert_eq!(
            (width - overlap) % (tile_size - overlap),
            0,
            "Image must contain an integer number of tiles"
        );
        debug_assert_eq!(
            (height - overlap) % (tile_size - overlap),
            0,
            "Image must contain an integer number of tiles"
        );

        let num_horizontal_tiles = (width - overlap) / (tile_size - overlap);
        let num_vertical_tiles = (height - overlap) / (tile_size - overlap);

        let step_size = tile_size - overlap;
        Array2::from_shape_fn((num_vertical_tiles, num_horizontal_tiles), |(y, x)| {
            let start_y = y * step_size;
            let start_x = x * step_size;
            self.copy_region([start_y, start_x], [tile_size, tile_size])
        })
    }
}