rust/landgen/src/wavefront_collapse/tile_image.rs
branchtransitional_engine
changeset 15915 8f093b1b18bc
parent 15913 c5684cc62de8
child 15916 e82de0410da5
--- a/rust/landgen/src/wavefront_collapse/tile_image.rs	Wed Feb 01 11:19:45 2023 +0100
+++ b/rust/landgen/src/wavefront_collapse/tile_image.rs	Thu Feb 02 08:41:31 2023 +0100
@@ -1,18 +1,19 @@
-use land2d::Land2D;
+use vec2d::Vec2D;
 use std::rc::Rc;
+use integral_geometry::Size;
 
-pub struct TileImage {
-    image: Rc<Land2D<u8>>,
+pub struct TileImage<T> {
+    image: Rc<Vec2D<T>>,
     flip: bool,
     mirror: bool,
 }
 
-impl TileImage {
-    pub fn new(flip: bool, mirror: bool) -> Self {
+impl<T: Copy> TileImage<T> {
+    pub fn new(image: Vec2D<T>) -> Self {
         Self {
-            image: todo!(),
-            flip,
-            mirror,
+            image: Rc::new(image),
+            flip: false,
+            mirror: false,
         }
     }
 
@@ -20,7 +21,7 @@
         Self {
             image: self.image.clone(),
             flip: self.flip,
-            mirror: !self.mirror
+            mirror: !self.mirror,
         }
     }
 
@@ -28,7 +29,50 @@
         Self {
             image: self.image.clone(),
             flip: !self.flip,
-            mirror: self.mirror
+            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);
+    }
+}