extract size struct for common usage
authoralfadur
Tue, 30 Oct 2018 19:05:52 +0300
changeset 14053 2869c2ccb1b8
parent 14052 c47283feafac
child 14054 bf77c4d2294f
extract size struct for common usage
rust/integral-geometry/src/lib.rs
rust/land2d/src/lib.rs
rust/landgen/src/template_based.rs
rust/vec2d/Cargo.toml
rust/vec2d/src/lib.rs
--- a/rust/integral-geometry/src/lib.rs	Tue Oct 30 05:55:58 2018 +0300
+++ b/rust/integral-geometry/src/lib.rs	Tue Oct 30 19:05:52 2018 +0300
@@ -45,6 +45,73 @@
     }
 }
 
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct Size {
+    pub width: usize,
+    pub height: usize,
+}
+
+impl Size {
+    #[inline]
+    pub fn new(width: usize, height: usize) -> Self {
+        Size { width, height }
+    }
+
+    #[inline]
+    pub fn square(size: usize) -> Self {
+        Size { width: size, height: size }
+    }
+
+    #[inline]
+    pub fn area(&self) -> usize {
+        self.width * self.height
+    }
+
+    #[inline]
+    pub fn linear_index(&self, x: usize, y: usize) -> usize {
+        y * self.width + x
+    }
+
+    #[inline]
+    pub fn is_power_of_two(&self) -> bool {
+        self.width.is_power_of_two() && self.height.is_power_of_two()
+    }
+
+    #[inline]
+    pub fn to_mask(&self) -> SizeMask {
+        SizeMask::new(*self)
+    }
+}
+
+pub struct SizeMask{ size: Size }
+
+impl SizeMask {
+    #[inline]
+    pub fn new(size: Size) -> Self {
+        assert!(size.is_power_of_two());
+        let size = Size {
+            width: !(size.width - 1),
+            height: !(size.height - 1)
+        };
+        SizeMask { size }
+    }
+
+    #[inline]
+    pub fn contains_x<T: Into<usize>>(&self, x: T) -> bool {
+        (self.size.width & x.into()) == 0
+    }
+
+    #[inline]
+    pub fn contains_y<T: Into<usize>>(&self, y: T) -> bool {
+        (self.size.height & y.into()) == 0
+    }
+
+    #[inline]
+    pub fn contains(&self, point: Point) -> bool {
+        self.contains_x(point.x as usize) && self.contains_y(point.y as usize)
+    }
+}
+
 macro_rules! bin_op_impl {
     ($op: ty, $name: tt) => {
         impl $op for Point {
--- a/rust/land2d/src/lib.rs	Tue Oct 30 05:55:58 2018 +0300
+++ b/rust/land2d/src/lib.rs	Tue Oct 30 19:05:52 2018 +0300
@@ -4,23 +4,21 @@
 use std::cmp;
 use std::ops;
 
-use integral_geometry::{ArcPoints, EquidistantPoints, LinePoints, Point};
+use integral_geometry::{
+    ArcPoints, EquidistantPoints, LinePoints,
+    Point, Size, SizeMask
+};
 
 pub struct Land2D<T> {
     pixels: vec2d::Vec2D<T>,
-    width_mask: usize,
-    height_mask: usize,
+    mask: SizeMask
 }
 
 impl<T: Copy + PartialEq> Land2D<T> {
-    pub fn new(width: usize, height: usize, fill_value: T) -> Self {
-        assert!(width.is_power_of_two());
-        assert!(height.is_power_of_two());
-
+    pub fn new(size: Size, fill_value: T) -> Self {
         Self {
-            pixels: vec2d::Vec2D::new(width, height, fill_value),
-            width_mask: !(width - 1),
-            height_mask: !(height - 1),
+            pixels: vec2d::Vec2D::new(size, fill_value),
+            mask: size.to_mask()
         }
     }
 
@@ -36,12 +34,12 @@
 
     #[inline]
     pub fn is_valid_x(&self, x: i32) -> bool {
-        (x as usize & self.width_mask) == 0
+        self.mask.contains_x(x as usize)
     }
 
     #[inline]
     pub fn is_valid_y(&self, y: i32) -> bool {
-        (y as usize & self.height_mask) == 0
+        self.mask.contains_y(y as usize)
     }
 
     #[inline]
@@ -269,7 +267,7 @@
 
     #[test]
     fn basics() {
-        let l: Land2D<u8> = Land2D::new(32, 64, 0);
+        let l: Land2D<u8> = Land2D::new(Size::new(32, 64), 0);
 
         assert!(l.is_valid_coordinate(0, 0));
         assert!(!l.is_valid_coordinate(-1, -1));
@@ -281,7 +279,7 @@
 
     #[test]
     fn fill() {
-        let mut l: Land2D<u8> = Land2D::new(128, 128, 0);
+        let mut l: Land2D<u8> = Land2D::new(Size::square(128), 0);
 
         l.draw_line(Point::new(0, 0), Point::new(32, 96), 1);
         l.draw_line(Point::new(32, 96), Point::new(64, 32), 1);
--- a/rust/landgen/src/template_based.rs	Tue Oct 30 05:55:58 2018 +0300
+++ b/rust/landgen/src/template_based.rs	Tue Oct 30 19:05:52 2018 +0300
@@ -1,4 +1,4 @@
-use integral_geometry::Point;
+use integral_geometry::{Point, Size};
 use land2d::Land2D;
 use LandGenerationParameters;
 use LandGenerator;
@@ -6,8 +6,7 @@
 struct OutlineTemplate {
     islands: Vec<Vec<Point>>,
     fill_points: Vec<Point>,
-    width: usize,
-    height: usize,
+    size: Size,
     can_flip: bool,
     can_invert: bool,
     can_mirror: bool,
@@ -45,8 +44,7 @@
         }
 
         let mut land = Land2D::new(
-            self.outline_template.width,
-            self.outline_template.height,
+            self.outline_template.size,
             parameters.basic,
         );
 
--- a/rust/vec2d/Cargo.toml	Tue Oct 30 05:55:58 2018 +0300
+++ b/rust/vec2d/Cargo.toml	Tue Oct 30 19:05:52 2018 +0300
@@ -4,3 +4,4 @@
 authors = ["Andrey Korotaev <a.korotaev@hedgewars.org>"]
 
 [dependencies]
+integral-geometry = { path = "../integral-geometry" }
--- a/rust/vec2d/src/lib.rs	Tue Oct 30 05:55:58 2018 +0300
+++ b/rust/vec2d/src/lib.rs	Tue Oct 30 19:05:52 2018 +0300
@@ -1,10 +1,12 @@
+extern crate integral_geometry;
+
 use std::ops::{Index, IndexMut};
 use std::slice::SliceIndex;
+use integral_geometry::Size;
 
 pub struct Vec2D<T> {
     data: Vec<T>,
-    width: usize,
-    height: usize,
+    size: Size,
 }
 
 impl<T> Index<usize> for Vec2D<T> {
@@ -12,67 +14,70 @@
 
     #[inline]
     fn index(&self, row: usize) -> &[T] {
-        debug_assert!(row < self.height);
+        debug_assert!(row < self.height());
 
-        let pos = row * self.width;
+        let pos = row * self.width();
 
-        &self.data[pos..pos + self.width]
+        &self.data[pos..pos + self.width()]
     }
 }
 
 impl<T> IndexMut<usize> for Vec2D<T> {
     #[inline]
     fn index_mut(&mut self, row: usize) -> &mut [T] {
-        debug_assert!(row < self.height);
+        debug_assert!(row < self.height());
 
-        let pos = row * self.width;
+        let pos = row * self.width();
 
-        &mut self.data[pos..pos + self.width]
+        &mut self.data[pos..pos + self.size.width]
     }
 }
 
-impl<T: Copy> Vec2D<T> {
-    pub fn new(width: usize, height: usize, value: T) -> Self {
-        Self {
-            data: vec![value; width * height],
-            width,
-            height,
-        }
-    }
-
+impl <T> Vec2D<T> {
     #[inline]
     pub fn width(&self) -> usize {
-        self.width
+        self.size.width
     }
 
     #[inline]
     pub fn height(&self) -> usize {
-        self.height
+        self.size.height
+    }
+
+    #[inline]
+    pub fn size(&self) -> Size {
+        self.size
+    }
+}
+
+impl<T: Copy> Vec2D<T> {
+    pub fn new(size: Size, value: T) -> Self {
+        Self { size, data: vec![value; size.area()] }
     }
 
     #[inline]
     pub fn get(&self, row: usize, column: usize) -> Option<&<usize as SliceIndex<[T]>>::Output> {
-        self.data.get(row * self.width + column)
+        self.data.get(row * self.width() + column)
     }
 
     #[inline]
     pub fn get_mut(&mut self, row: usize, column: usize) -> Option<&mut <usize as SliceIndex<[T]>>::Output> {
-        self.data.get_mut(row * self.width + column)
+        self.data.get_mut(row * self.size.width + column)
     }
 
     #[inline]
     pub unsafe fn get_unchecked(&self, row: usize, column: usize) -> &<usize as SliceIndex<[T]>>::Output {
-        self.data.get_unchecked(row * self.width + column)
+        self.data.get_unchecked(row * self.width() + column)
     }
 
     #[inline]
     pub unsafe fn get_unchecked_mut(&mut self, row: usize, column: usize) -> &mut <usize as SliceIndex<[T]>>::Output {
-        self.data.get_unchecked_mut(row * self.width + column)
+        self.data.get_unchecked_mut(row * self.size.width + column)
     }
 
     #[inline]
     pub fn rows(&self) -> impl Iterator<Item = &[T]> {
-        self.data.chunks(self.width)
+        self.data.chunks(self.width())
     }
 }
 
@@ -82,10 +87,10 @@
 
     #[test]
     fn basics() {
-        let mut v: Vec2D<u8> = Vec2D::new(2, 3, 0xff);
+        let mut v: Vec2D<u8> = Vec2D::new(Size::new(2, 3), 0xff);
 
-        assert_eq!(v.width, 2);
-        assert_eq!(v.height, 3);
+        assert_eq!(v.width(), 2);
+        assert_eq!(v.height(), 3);
 
         assert_eq!(v[0][0], 0xff);
         assert_eq!(v[2][1], 0xff);