rust/landgen/src/wavefront_collapse/tile_image.rs
author unC0Rr
Thu, 02 Feb 2023 08:41:31 +0100
branchtransitional_engine
changeset 15915 8f093b1b18bc
parent 15913 c5684cc62de8
child 15916 e82de0410da5
permissions -rw-r--r--
Add loading of tiles from png

use vec2d::Vec2D;
use std::rc::Rc;
use integral_geometry::Size;

pub struct TileImage<T> {
    image: Rc<Vec2D<T>>,
    flip: bool,
    mirror: bool,
}

impl<T: Copy> TileImage<T> {
    pub fn new(image: Vec2D<T>) -> Self {
        Self {
            image: Rc::new(image),
            flip: false,
            mirror: false,
        }
    }

    pub fn mirrored(&self) -> Self {
        Self {
            image: self.image.clone(),
            flip: self.flip,
            mirror: !self.mirror,
        }
    }

    pub fn flipped(&self) -> Self {
        Self {
            image: self.image.clone(),
            flip: !self.flip,
            mirror: self.mirror,
        }
    }

    pub fn split(&self, rows: usize, columns: usize) -> Vec<TileImage<T>> {
        let mut result = Vec::new();
        let self_image = self.image.as_ref();
        let (result_width, result_height) = (self_image.width() / columns, self.image.height() / rows);

        for row in 0..rows {
            for column in 0..columns {
                let mut tile_pixels = Vec::new();

                for out_row in 0..result_height {
                    tile_pixels.push(self_image[row * result_height + out_row][column*result_width..(column+1)*result_width].iter());
                }

                let tile_image = Vec2D::from_iter(tile_pixels.into_iter().flatten().map(|p| *p), &Size::new(result_width, result_height));

                result.push(TileImage::new(tile_image.expect("correct calculation of tile dimensions")));
            }
        }

        result
    }
}

#[cfg(test)]
mod tests {
    use super::TileImage;
    use integral_geometry::Size;
    use vec2d::Vec2D;

    #[test]
    fn test_split() {
        let size = Size::new(6, 4);
        let sample_data = Vec2D::from_iter((0..24).into_iter(), &size);

        assert!(sample_data.is_some());

        let sample_data = sample_data.unwrap();
        let big_tile = TileImage::new(sample_data);
        let subtiles = big_tile.split(2, 2);

        assert_eq!(subtiles.len(), 4);
    }
}