rust/integral-geometry/src/lib.rs
changeset 14076 e5904ead4864
parent 14059 c6745a1c827a
child 14077 5ade484f3351
equal deleted inserted replaced
14075:df0e86b2630f 14076:e5904ead4864
     1 use std::cmp;
       
     2 use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
     1 use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
     3 
     2 
     4 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
     3 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
     5 pub struct Point {
     4 pub struct Point {
     6     pub x: i32,
     5     pub x: i32,
    38         std::cmp::max(self.x.abs(), self.y.abs())
    37         std::cmp::max(self.x.abs(), self.y.abs())
    39     }
    38     }
    40 
    39 
    41     #[inline]
    40     #[inline]
    42     pub fn transform(self, matrix: &[i32; 4]) -> Self {
    41     pub fn transform(self, matrix: &[i32; 4]) -> Self {
    43         Point::new(matrix[0] * self.x + matrix[1] * self.y,
    42         Point::new(
    44                    matrix[2] * self.x + matrix[3] * self.y)
    43             matrix[0] * self.x + matrix[1] * self.y,
       
    44             matrix[2] * self.x + matrix[3] * self.y,
       
    45         )
    45     }
    46     }
    46 }
    47 }
    47 
    48 
    48 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
    49 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
    49 pub struct Size {
    50 pub struct Size {
    57         Size { width, height }
    58         Size { width, height }
    58     }
    59     }
    59 
    60 
    60     #[inline]
    61     #[inline]
    61     pub fn square(size: usize) -> Self {
    62     pub fn square(size: usize) -> Self {
    62         Size { width: size, height: size }
    63         Size {
       
    64             width: size,
       
    65             height: size,
       
    66         }
    63     }
    67     }
    64 
    68 
    65     #[inline]
    69     #[inline]
    66     pub fn area(&self) -> usize {
    70     pub fn area(&self) -> usize {
    67         self.width * self.height
    71         self.width * self.height
    79 
    83 
    80     #[inline]
    84     #[inline]
    81     pub fn next_power_of_two(&self) -> Self {
    85     pub fn next_power_of_two(&self) -> Self {
    82         Self {
    86         Self {
    83             width: self.width.next_power_of_two(),
    87             width: self.width.next_power_of_two(),
    84             height: self.height.next_power_of_two()
    88             height: self.height.next_power_of_two(),
    85         }
    89         }
    86     }
    90     }
    87 
    91 
    88     #[inline]
    92     #[inline]
    89     pub fn to_mask(&self) -> SizeMask {
    93     pub fn to_mask(&self) -> SizeMask {
    93     pub fn to_grid_index(&self) -> GridIndex {
    97     pub fn to_grid_index(&self) -> GridIndex {
    94         GridIndex::new(*self)
    98         GridIndex::new(*self)
    95     }
    99     }
    96 }
   100 }
    97 
   101 
    98 pub struct SizeMask{ size: Size }
   102 pub struct SizeMask {
       
   103     size: Size,
       
   104 }
    99 
   105 
   100 impl SizeMask {
   106 impl SizeMask {
   101     #[inline]
   107     #[inline]
   102     pub fn new(size: Size) -> Self {
   108     pub fn new(size: Size) -> Self {
   103         assert!(size.is_power_of_two());
   109         assert!(size.is_power_of_two());
   104         let size = Size {
   110         let size = Size {
   105             width: !(size.width - 1),
   111             width: !(size.width - 1),
   106             height: !(size.height - 1)
   112             height: !(size.height - 1),
   107         };
   113         };
   108         Self { size }
   114         Self { size }
   109     }
   115     }
   110 
   116 
   111     #[inline]
   117     #[inline]
   122     pub fn contains(&self, point: Point) -> bool {
   128     pub fn contains(&self, point: Point) -> bool {
   123         self.contains_x(point.x as usize) && self.contains_y(point.y as usize)
   129         self.contains_x(point.x as usize) && self.contains_y(point.y as usize)
   124     }
   130     }
   125 }
   131 }
   126 
   132 
   127 pub struct GridIndex{ shift: Point }
   133 pub struct GridIndex {
       
   134     shift: Point,
       
   135 }
   128 
   136 
   129 impl GridIndex {
   137 impl GridIndex {
   130     pub fn new(size: Size) -> Self {
   138     pub fn new(size: Size) -> Self {
   131         assert!(size.is_power_of_two());
   139         assert!(size.is_power_of_two());
   132         let shift = Point::new(size.width.trailing_zeros() as i32,
   140         let shift = Point::new(
   133                                size.height.trailing_zeros() as i32);
   141             size.width.trailing_zeros() as i32,
       
   142             size.height.trailing_zeros() as i32,
       
   143         );
   134         Self { shift }
   144         Self { shift }
   135     }
   145     }
   136 
   146 
   137     pub fn map(&self, position: Point) -> Point {
   147     pub fn map(&self, position: Point) -> Point {
   138         Point::new(position.x >> self.shift.x,
   148         Point::new(position.x >> self.shift.x, position.y >> self.shift.y)
   139                    position.y >> self.shift.y)
       
   140     }
   149     }
   141 }
   150 }
   142 
   151 
   143 macro_rules! bin_op_impl {
   152 macro_rules! bin_op_impl {
   144     ($op: ty, $name: tt) => {
   153     ($op: ty, $name: tt) => {
   183 }
   192 }
   184 
   193 
   185 impl Rect {
   194 impl Rect {
   186     #[inline]
   195     #[inline]
   187     pub fn new(x: i32, y: i32, width: u32, height: u32) -> Self {
   196     pub fn new(x: i32, y: i32, width: u32, height: u32) -> Self {
   188         Self { x, y, width, height }
   197         Self {
       
   198             x,
       
   199             y,
       
   200             width,
       
   201             height,
       
   202         }
   189     }
   203     }
   190 
   204 
   191     #[inline]
   205     #[inline]
   192     pub fn size(&self) -> Size {
   206     pub fn size(&self) -> Size {
   193         Size::new(self.width as usize, self.height as usize)
   207         Size::new(self.width as usize, self.height as usize)
   197     pub fn area(&self) -> usize {
   211     pub fn area(&self) -> usize {
   198         self.size().area()
   212         self.size().area()
   199     }
   213     }
   200 }
   214 }
   201 
   215 
       
   216 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
       
   217 pub struct Line {
       
   218     pub start: Point,
       
   219     pub end: Point,
       
   220 }
       
   221 
       
   222 impl Line {
       
   223     #[inline]
       
   224     pub fn new(start: Point, end: Point) -> Self {
       
   225         Self { start, end }
       
   226     }
       
   227 
       
   228     #[inline]
       
   229     pub fn zero() -> Self {
       
   230         Self::new(Point::zero(), Point::zero())
       
   231     }
       
   232 }
       
   233 
       
   234 impl IntoIterator for Line {
       
   235     type Item = Point;
       
   236     type IntoIter = LinePoints;
       
   237 
       
   238     fn into_iter(self) -> Self::IntoIter {
       
   239         LinePoints::new(self)
       
   240     }
       
   241 }
   202 
   242 
   203 pub struct LinePoints {
   243 pub struct LinePoints {
   204     accumulator: Point,
   244     accumulator: Point,
   205     direction: Point,
   245     direction: Point,
   206     sign: Point,
   246     sign: Point,
   208     total_steps: i32,
   248     total_steps: i32,
   209     step: i32,
   249     step: i32,
   210 }
   250 }
   211 
   251 
   212 impl LinePoints {
   252 impl LinePoints {
   213     pub fn new(from: Point, to: Point) -> Self {
   253     pub fn new(line: Line) -> Self {
   214         let dir = to - from;
   254         let dir = line.end - line.start;
   215 
   255 
   216         Self {
   256         Self {
   217             accumulator: Point::zero(),
   257             accumulator: Point::zero(),
   218             direction: dir.abs(),
   258             direction: dir.abs(),
   219             sign: dir.signum(),
   259             sign: dir.signum(),
   220             current: from,
   260             current: line.start,
   221             total_steps: dir.max_norm(),
   261             total_steps: dir.max_norm(),
   222             step: 0,
   262             step: 0,
   223         }
   263         }
   224     }
   264     }
   225 }
   265 }
   335         coords.iter().map(|(x, y)| Point::new(*x, *y)).collect()
   375         coords.iter().map(|(x, y)| Point::new(*x, *y)).collect()
   336     }
   376     }
   337 
   377 
   338     #[test]
   378     #[test]
   339     fn line_basic() {
   379     fn line_basic() {
   340         let line = LinePoints::new(Point::new(0, 0), Point::new(3, 3));
   380         let line = Line::new(Point::new(0, 0), Point::new(3, 3)).into_iter();
   341         let v = get_points(&[(0, 0), (1, 1), (2, 2), (3, 3), (123, 456)]);
   381         let v = get_points(&[(0, 0), (1, 1), (2, 2), (3, 3), (123, 456)]);
   342 
   382 
   343         for (&a, b) in v.iter().zip(line) {
   383         for (&a, b) in v.iter().zip(line) {
   344             assert_eq!(a, b);
   384             assert_eq!(a, b);
   345         }
   385         }
   346     }
   386     }
   347 
   387 
   348     #[test]
   388     #[test]
   349     fn line_skewed() {
   389     fn line_skewed() {
   350         let line = LinePoints::new(Point::new(0, 0), Point::new(5, -7));
   390         let line = Line::new(Point::new(0, 0), Point::new(5, -7)).into_iter();
   351         let v = get_points(&[
   391         let v = get_points(&[
   352             (0, 0),
   392             (0, 0),
   353             (1, -1),
   393             (1, -1),
   354             (2, -2),
   394             (2, -2),
   355             (2, -3),
   395             (2, -3),