rust/landgen/src/wavefront_collapse/tile_image.rs
branchtransitional_engine
changeset 15916 e82de0410da5
parent 15915 8f093b1b18bc
child 15917 60b5639cc3a5
equal deleted inserted replaced
15915:8f093b1b18bc 15916:e82de0410da5
       
     1 use super::transform::RotationTransform;
       
     2 use std::rc::Rc;
     1 use vec2d::Vec2D;
     3 use vec2d::Vec2D;
     2 use std::rc::Rc;
       
     3 use integral_geometry::Size;
       
     4 
     4 
     5 pub struct TileImage<T> {
     5 #[derive(PartialEq, Clone)]
     6     image: Rc<Vec2D<T>>,
     6 pub struct Edge<I: PartialEq + Clone> {
     7     flip: bool,
     7     id: I,
     8     mirror: bool,
     8     symmetrical: bool,
       
     9     reverse: bool,
     9 }
    10 }
    10 
    11 
    11 impl<T: Copy> TileImage<T> {
    12 impl<I: PartialEq + Clone> Edge<I> {
    12     pub fn new(image: Vec2D<T>) -> Self {
    13     pub fn new(id: I, symmetrical: bool) -> Self {
       
    14         Self {
       
    15             id,
       
    16             symmetrical,
       
    17             reverse: false,
       
    18         }
       
    19     }
       
    20 
       
    21     pub fn reversed(&self) -> Self {
       
    22         Self {
       
    23             id: self.id.clone(),
       
    24             symmetrical: self.symmetrical,
       
    25             reverse: !self.symmetrical && !self.reverse,
       
    26         }
       
    27     }
       
    28 }
       
    29 
       
    30 #[derive(Clone)]
       
    31 pub struct TileImage<T, I: PartialEq + Clone> {
       
    32     image: Rc<Vec2D<T>>,
       
    33     transform: RotationTransform,
       
    34     top: Edge<I>,
       
    35     right: Edge<I>,
       
    36     bottom: Edge<I>,
       
    37     left: Edge<I>,
       
    38 }
       
    39 
       
    40 impl<T: Copy, I: PartialEq + Clone> TileImage<T, I> {
       
    41     pub fn new(
       
    42         image: Vec2D<T>,
       
    43         top: Edge<I>,
       
    44         right: Edge<I>,
       
    45         bottom: Edge<I>,
       
    46         left: Edge<I>,
       
    47     ) -> Self {
    13         Self {
    48         Self {
    14             image: Rc::new(image),
    49             image: Rc::new(image),
    15             flip: false,
    50             transform: RotationTransform::default(),
    16             mirror: false,
    51             top,
       
    52             right,
       
    53             bottom,
       
    54             left,
    17         }
    55         }
    18     }
    56     }
    19 
    57 
    20     pub fn mirrored(&self) -> Self {
    58     pub fn mirrored(&self) -> Self {
    21         Self {
    59         Self {
    22             image: self.image.clone(),
    60             image: self.image.clone(),
    23             flip: self.flip,
    61             transform: self.transform.mirror(),
    24             mirror: !self.mirror,
    62             top: self.top.reversed(),
       
    63             right: self.left.reversed(),
       
    64             bottom: self.bottom.reversed(),
       
    65             left: self.right.reversed(),
    25         }
    66         }
    26     }
    67     }
    27 
    68 
    28     pub fn flipped(&self) -> Self {
    69     pub fn flipped(&self) -> Self {
    29         Self {
    70         Self {
    30             image: self.image.clone(),
    71             image: self.image.clone(),
    31             flip: !self.flip,
    72             transform: self.transform.flip(),
    32             mirror: self.mirror,
    73             top: self.bottom.reversed(),
       
    74             right: self.right.reversed(),
       
    75             bottom: self.top.reversed(),
       
    76             left: self.left.reversed(),
    33         }
    77         }
    34     }
    78     }
    35 
    79 
    36     pub fn split(&self, rows: usize, columns: usize) -> Vec<TileImage<T>> {
    80     pub fn rotated90(&self) -> Self {
    37         let mut result = Vec::new();
    81         Self {
    38         let self_image = self.image.as_ref();
    82             image: self.image.clone(),
    39         let (result_width, result_height) = (self_image.width() / columns, self.image.height() / rows);
    83             transform: self.transform.rotate90(),
       
    84             top: self.left.clone(),
       
    85             right: self.top.clone(),
       
    86             bottom: self.right.clone(),
       
    87             left: self.bottom.clone(),
       
    88         }
       
    89     }
    40 
    90 
    41         for row in 0..rows {
    91     pub fn rotated180(&self) -> Self {
    42             for column in 0..columns {
    92         Self {
    43                 let mut tile_pixels = Vec::new();
    93             image: self.image.clone(),
       
    94             transform: self.transform.rotate90(),
       
    95             top: self.bottom.clone(),
       
    96             right: self.left.clone(),
       
    97             bottom: self.top.clone(),
       
    98             left: self.right.clone(),
       
    99         }
       
   100     }
    44 
   101 
    45                 for out_row in 0..result_height {
   102     pub fn rotated270(&self) -> Self {
    46                     tile_pixels.push(self_image[row * result_height + out_row][column*result_width..(column+1)*result_width].iter());
   103         Self {
    47                 }
   104             image: self.image.clone(),
    48 
   105             transform: self.transform.rotate90(),
    49                 let tile_image = Vec2D::from_iter(tile_pixels.into_iter().flatten().map(|p| *p), &Size::new(result_width, result_height));
   106             top: self.left.clone(),
    50 
   107             right: self.top.clone(),
    51                 result.push(TileImage::new(tile_image.expect("correct calculation of tile dimensions")));
   108             bottom: self.right.clone(),
    52             }
   109             left: self.bottom.clone(),
    53         }
   110         }
    54 
       
    55         result
       
    56     }
   111     }
    57 }
   112 }
    58 
   113 
    59 #[cfg(test)]
   114 #[cfg(test)]
    60 mod tests {
   115 mod tests {}
    61     use super::TileImage;
       
    62     use integral_geometry::Size;
       
    63     use vec2d::Vec2D;
       
    64 
       
    65     #[test]
       
    66     fn test_split() {
       
    67         let size = Size::new(6, 4);
       
    68         let sample_data = Vec2D::from_iter((0..24).into_iter(), &size);
       
    69 
       
    70         assert!(sample_data.is_some());
       
    71 
       
    72         let sample_data = sample_data.unwrap();
       
    73         let big_tile = TileImage::new(sample_data);
       
    74         let subtiles = big_tile.split(2, 2);
       
    75 
       
    76         assert_eq!(subtiles.len(), 4);
       
    77     }
       
    78 }