rust/land2d/src/lib.rs
changeset 13959 1fa905aa4cdb
parent 13957 78c798d655ad
child 13961 1c30793b1cea
equal deleted inserted replaced
13958:7f1c178506bb 13959:1fa905aa4cdb
     1 extern crate integral_geometry;
     1 extern crate integral_geometry;
     2 extern crate vec2d;
     2 extern crate vec2d;
     3 
     3 
     4 use std::cmp;
     4 use std::cmp;
     5 use std::ops;
     5 use std::ops;
       
     6 
       
     7 use integral_geometry::{Point, LinePoints};
     6 
     8 
     7 pub struct Land2D<T> {
     9 pub struct Land2D<T> {
     8     pixels: vec2d::Vec2D<T>,
    10     pixels: vec2d::Vec2D<T>,
     9     width_mask: usize,
    11     width_mask: usize,
    10     height_mask: usize,
    12     height_mask: usize,
    46     pub fn is_valid_coordinate(&self, x: i32, y: i32) -> bool {
    48     pub fn is_valid_coordinate(&self, x: i32, y: i32) -> bool {
    47         self.is_valid_x(x) && self.is_valid_y(y)
    49         self.is_valid_x(x) && self.is_valid_y(y)
    48     }
    50     }
    49 
    51 
    50     #[inline]
    52     #[inline]
    51     pub fn map<U: Default, F: FnOnce(&mut T) -> U>(&mut self, y: i32, x: i32, f: F) -> U {
    53     pub fn get_mut(&mut self, y: i32, x: i32) -> Option<&mut T> {
    52         if self.is_valid_coordinate(x, y) {
    54         if self.is_valid_coordinate(x, y) {
    53             unsafe {
    55             unsafe {
    54                 // hey, I just checked that coordinates are valid!
    56                 // hey, I just checked that coordinates are valid!
    55                 f(self.pixels.get_unchecked_mut(y as usize, x as usize))
    57                 Some(self.pixels.get_unchecked_mut(y as usize, x as usize))
    56             }
    58             }
    57         } else {
    59         } else {
    58             U::default()
    60             None
    59         }
    61         }
       
    62     }
       
    63 
       
    64     #[inline]
       
    65     pub fn map<U: Default, F: FnOnce(&mut T) -> U>(&mut self, y: i32, x: i32, f: F) -> U {
       
    66         self.get_mut(y, x).map(f).unwrap_or_default()
    60     }
    67     }
    61 
    68 
    62     fn apply_along_line<U: Default + ops::AddAssign, F: FnMut(i32, i32) -> U>(
    69     fn apply_along_line<U: Default + ops::AddAssign, F: FnMut(i32, i32) -> U>(
    63         x1: i32,
    70         x1: i32,
    64         y1: i32,
    71         y1: i32,
   144         }
   151         }
   145 
   152 
   146         result
   153         result
   147     }
   154     }
   148 
   155 
   149     pub fn draw_line(&mut self, x1: i32, y1: i32, x2: i32, y2: i32, value: T) -> usize {
   156     pub fn fill_from_iter<I>(&mut self, i: I, value: T) -> usize
   150         integral_geometry::LinePoints::new(x1, y1, x2, y2)
   157         where I: std::iter::Iterator<Item = Point>
   151             .filter_map(|(x, y)| {
   158     {
   152                 self.map(y, x, |p| {
   159         i.map(|p| self.get_mut(p.y, p.x).map(|v| *v = value)).count()
   153                     *p = value;
   160     }
   154                     Some(1)
   161 
   155                 })
   162     pub fn draw_line(&mut self, from: Point, to: Point, value: T) -> usize {
   156             }).count()
   163         self.fill_from_iter(LinePoints::new(from, to), value)
   157     }
   164     }
   158 
   165 
   159     pub fn fill(&mut self, start_x: i32, start_y: i32, border_value: T, fill_value: T) {
   166     pub fn fill(&mut self, start_x: i32, start_y: i32, border_value: T, fill_value: T) {
   160         debug_assert!(self.is_valid_coordinate(start_x - 1, start_y));
   167         debug_assert!(self.is_valid_coordinate(start_x - 1, start_y));
   161         debug_assert!(self.is_valid_coordinate(start_x, start_y));
   168         debug_assert!(self.is_valid_coordinate(start_x, start_y));
   347 
   354 
   348     #[test]
   355     #[test]
   349     fn fill() {
   356     fn fill() {
   350         let mut l: Land2D<u8> = Land2D::new(128, 128, 0);
   357         let mut l: Land2D<u8> = Land2D::new(128, 128, 0);
   351 
   358 
   352         l.draw_line(0, 0, 32, 96, 1);
   359         l.draw_line(Point::new(0, 0), Point::new(32, 96), 1);
   353         l.draw_line(32, 96, 64, 32, 1);
   360         l.draw_line(Point::new(32, 96), Point::new(64, 32), 1);
   354         l.draw_line(64, 32, 96, 80, 1);
   361         l.draw_line(Point::new(64, 32), Point::new(96, 80), 1);
   355         l.draw_line(96, 80, 128, 0, 1);
   362         l.draw_line(Point::new(96, 80), Point::new(128, 0), 1);
   356 
   363 
   357         l.draw_line(0, 128, 64, 96, 1);
   364         l.draw_line(Point::new(0, 128), Point::new(64, 96), 1);
   358         l.draw_line(128, 128, 64, 96, 1);
   365         l.draw_line(Point::new(128, 128), Point::new(64, 96), 1);
   359 
   366 
   360         l.fill(32, 32, 1, 2);
   367         l.fill(32, 32, 1, 2);
   361         l.fill(16, 96, 1, 3);
   368         l.fill(16, 96, 1, 3);
   362         l.fill(60, 100, 1, 4);
   369         l.fill(60, 100, 1, 4);
   363 
   370