rust/land2d/src/lib.rs
changeset 13938 a83ba9ba1566
child 13945 a140f28decc4
equal deleted inserted replaced
13937:cd437d76978a 13938:a83ba9ba1566
       
     1 extern crate vec2d;
       
     2 
       
     3 use std::cmp;
       
     4 
       
     5 pub struct Land2D<T> {
       
     6     pixels: vec2d::Vec2D<T>,
       
     7     width_mask: usize,
       
     8     height_mask: usize,
       
     9 }
       
    10 
       
    11 impl<T: Default + Copy> Land2D<T> {
       
    12     pub fn new(width: usize, height: usize) -> Self {
       
    13         assert!(width.is_power_of_two());
       
    14         assert!(height.is_power_of_two());
       
    15 
       
    16         Self {
       
    17             pixels: vec2d::Vec2D::new(width, height, T::default()),
       
    18             width_mask: !(width - 1),
       
    19             height_mask: !(height - 1),
       
    20         }
       
    21     }
       
    22 
       
    23     #[inline]
       
    24     fn is_valid_coordinate(&self, x: i32, y: i32) -> bool {
       
    25         (x as usize & self.width_mask) == 0 && (y as usize & self.height_mask) == 0
       
    26     }
       
    27 
       
    28     #[inline]
       
    29     pub fn map<U, F: FnOnce(&mut T) -> U>(&mut self, y: i32, x: i32, f: F) {
       
    30         if self.is_valid_coordinate(x, y) {
       
    31             self.pixels.get_mut(y as usize, x as usize).map(f);
       
    32         }
       
    33     }
       
    34 
       
    35     pub fn draw_line(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, value: T) {
       
    36         let mut e_x: i32 = 0;
       
    37         let mut e_y: i32 = 0;
       
    38         let mut d_x: i32 = x2 - x1;
       
    39         let mut d_y: i32 = y2 - y1;
       
    40 
       
    41         let s_x: i32;
       
    42         let s_y: i32;
       
    43 
       
    44         if d_x > 0 {
       
    45             s_x = 1;
       
    46         } else if d_x < 0 {
       
    47             s_x = -1;
       
    48             d_x = -d_x;
       
    49         } else {
       
    50             s_x = d_x;
       
    51         }
       
    52 
       
    53         if d_y > 0 {
       
    54             s_y = 1;
       
    55         } else if d_y < 0 {
       
    56             s_y = -1;
       
    57             d_y = -d_y;
       
    58         } else {
       
    59             s_y = d_y;
       
    60         }
       
    61 
       
    62         let d = cmp::max(d_x, d_y);
       
    63 
       
    64         let mut x = x1;
       
    65         let mut y = y1;
       
    66 
       
    67         for _i in 0..=d {
       
    68             e_x += d_x;
       
    69             e_y += d_y;
       
    70 
       
    71             if e_x > d {
       
    72                 e_x -= d;
       
    73                 x += s_x;
       
    74             }
       
    75             if e_y > d {
       
    76                 e_y -= d;
       
    77                 y += s_y;
       
    78             }
       
    79 
       
    80             self.map(y, x, |p| *p = value);
       
    81         }
       
    82     }
       
    83 }
       
    84 
       
    85 #[cfg(test)]
       
    86 mod tests {
       
    87     use super::*;
       
    88 
       
    89     #[test]
       
    90     fn basics() {
       
    91         let  l:Land2D<u8> = Land2D::new(32, 64);
       
    92 
       
    93         assert!(l.is_valid_coordinate(0, 0));
       
    94         assert!(!l.is_valid_coordinate(-1, -1));
       
    95 
       
    96         assert!(l.is_valid_coordinate(31, 63));
       
    97         assert!(!l.is_valid_coordinate(32, 63));
       
    98         assert!(!l.is_valid_coordinate(31, 64));
       
    99     }
       
   100 
       
   101 }