rust/integral-geometry/src/lib.rs
changeset 13935 75eaf7c71789
child 13937 7f1c178506bb
equal deleted inserted replaced
13934:9c112f2ae02d 13935:75eaf7c71789
       
     1 use std::cmp;
       
     2 
       
     3 pub struct LinePoints {
       
     4     e_x: i32,
       
     5     e_y: i32,
       
     6     d_x: i32,
       
     7     d_y: i32,
       
     8     s_x: i32,
       
     9     s_y: i32,
       
    10     x: i32,
       
    11     y: i32,
       
    12     d: i32,
       
    13     i: i32,
       
    14 }
       
    15 
       
    16 impl LinePoints {
       
    17     pub fn new(x1: i32, y1: i32, x2: i32, y2: i32) -> Self {
       
    18         let mut d_x: i32 = x2 - x1;
       
    19         let mut d_y: i32 = y2 - y1;
       
    20         let s_x: i32;
       
    21         let s_y: i32;
       
    22 
       
    23         if d_x > 0 {
       
    24             s_x = 1;
       
    25         } else if d_x < 0 {
       
    26             s_x = -1;
       
    27             d_x = -d_x;
       
    28         } else {
       
    29             s_x = d_x;
       
    30         }
       
    31 
       
    32         if d_y > 0 {
       
    33             s_y = 1;
       
    34         } else if d_y < 0 {
       
    35             s_y = -1;
       
    36             d_y = -d_y;
       
    37         } else {
       
    38             s_y = d_y;
       
    39         }
       
    40 
       
    41         Self {
       
    42             e_x: 0,
       
    43             e_y: 0,
       
    44             d_x,
       
    45             d_y,
       
    46             s_x,
       
    47             s_y,
       
    48             x: x1,
       
    49             y: y1,
       
    50             d: cmp::max(d_x, d_y),
       
    51             i: 0,
       
    52         }
       
    53     }
       
    54 }
       
    55 
       
    56 impl Iterator for LinePoints {
       
    57     type Item = (i32, i32);
       
    58 
       
    59     fn next(&mut self) -> Option<Self::Item> {
       
    60         if self.i <= self.d {
       
    61             self.e_x += self.d_x;
       
    62             self.e_y += self.d_y;
       
    63 
       
    64             if self.e_x > self.d {
       
    65                 self.e_x -= self.d;
       
    66                 self.x += self.s_x;
       
    67             }
       
    68             if self.e_y > self.d {
       
    69                 self.e_y -= self.d;
       
    70                 self.y += self.s_y;
       
    71             }
       
    72 
       
    73             self.i += 1;
       
    74 
       
    75             Some((self.x, self.y))
       
    76         } else {
       
    77             None
       
    78         }
       
    79     }
       
    80 }
       
    81 
       
    82 #[cfg(test)]
       
    83 mod tests {
       
    84     use super::*;
       
    85 
       
    86     #[test]
       
    87     fn basic() {
       
    88         let v = vec![(0, 0), (1, 1), (2, 2), (3, 3)];
       
    89 
       
    90         for (&a, b) in v.iter().zip(LinePoints::new(0, 0, 3, 3)) {
       
    91             assert_eq!(a, b);
       
    92         }
       
    93     }
       
    94 }