Use integral-geometry iterators to implement Land2D::draw_thick_line, remove no longer unused functions from Land2D
authorunc0rr
Thu, 18 Oct 2018 22:45:14 +0200
changeset 13949 4162ea9ae333
parent 13948 a325ed57ebfe
child 13950 2354264ab0b0
Use integral-geometry iterators to implement Land2D::draw_thick_line, remove no longer unused functions from Land2D
rust/land2d/src/lib.rs
--- a/rust/land2d/src/lib.rs	Thu Oct 18 22:34:09 2018 +0200
+++ b/rust/land2d/src/lib.rs	Thu Oct 18 22:45:14 2018 +0200
@@ -4,7 +4,7 @@
 use std::cmp;
 use std::ops;
 
-use integral_geometry::{LinePoints, ArcPoints, Point};
+use integral_geometry::{ArcPoints, EquidistantPoints, LinePoints, Point};
 
 pub struct Land2D<T> {
     pixels: vec2d::Vec2D<T>,
@@ -61,91 +61,9 @@
         }
     }
 
-    fn apply_along_line<U: Default + ops::AddAssign, F: FnMut(i32, i32) -> U>(
-        x1: i32,
-        y1: i32,
-        x2: i32,
-        y2: i32,
-        f: &mut F,
-    ) -> U {
-        let mut result = U::default();
-        let mut e_x: i32 = 0;
-        let mut e_y: i32 = 0;
-        let mut d_x: i32 = x2 - x1;
-        let mut d_y: i32 = y2 - y1;
-
-        let s_x: i32;
-        let s_y: i32;
-
-        if d_x > 0 {
-            s_x = 1;
-        } else if d_x < 0 {
-            s_x = -1;
-            d_x = -d_x;
-        } else {
-            s_x = d_x;
-        }
-
-        if d_y > 0 {
-            s_y = 1;
-        } else if d_y < 0 {
-            s_y = -1;
-            d_y = -d_y;
-        } else {
-            s_y = d_y;
-        }
-
-        let d = cmp::max(d_x, d_y);
-
-        let mut x = x1;
-        let mut y = y1;
-
-        for _i in 0..=d {
-            e_x += d_x;
-            e_y += d_y;
-
-            if e_x > d {
-                e_x -= d;
-                x += s_x;
-            }
-            if e_y > d {
-                e_y -= d;
-                y += s_y;
-            }
-
-            result += f(x, y);
-        }
-
-        result
-    }
-
-    fn apply_around_circle<U: Default + ops::AddAssign, F: FnMut(i32, i32) -> U>(
-        radius: i32,
-        f: &mut F,
-    ) -> U {
-        let mut dx: i32 = 0;
-        let mut dy: i32 = radius;
-        let mut d = 3 - 2 * radius;
-        let mut result = U::default();
-
-        while dx < dy {
-            result += f(dx, dy);
-
-            if d < 0 {
-                d += 4 * dx + 6;
-            } else {
-                d += 4 * (dx - dy) + 10;
-                dy -= 1;
-            }
-
-            dx += 1;
-        }
-
-        if dx == dy {
-            result += f(dx, dy);
-        }
-
-        result
+    #[inline]
+    pub fn map_point<U: Default, F: FnOnce(&mut T) -> U>(&mut self, point: Point, f: F) -> U {
+        self.map(point.y, point.x, f)
     }
 
     pub fn fill_from_iter<I>(&mut self, i: I, value: T) -> usize
@@ -290,53 +208,23 @@
             .sum()
     }
 
-    #[inline]
-    fn change_dots_around<U: Default + ops::AddAssign, F: FnMut(i32, i32) -> U>(
-        x: i32,
-        y: i32,
-        xx: i32,
-        yy: i32,
-        f: &mut F,
-    ) -> U {
-        let mut result = U::default();
-        result += f(y + yy, x + xx);
-        result += f(y - yy, x + xx);
-        result += f(y + yy, x - xx);
-        result += f(y - yy, x - xx);
-        result += f(y + xx, x + yy);
-        result += f(y - xx, x + yy);
-        result += f(y + xx, x - yy);
-        result += f(y - xx, x - yy);
+    pub fn draw_thick_line(&mut self, from: Point, to: Point, radius: i32, value: T) -> usize {
+        let mut result = 0;
 
-        result
-    }
-
-    pub fn draw_thick_line(
-        &mut self,
-        from: Point, to: Point,
-        radius: i32,
-        value: T,
-    ) -> usize {
-        for deltas in ArcPoints::new(radius) {
-            for points in LinePoints::new(from, to) {
-
+        for point in LinePoints::new(from, to) {
+            for vector in ArcPoints::new(radius) {
+                for delta in EquidistantPoints::new(vector) {
+                    self.map_point(point + delta, |p| {
+                        if *p != value {
+                            *p = value;
+                            result += 1;
+                        }
+                    })
+                }
             }
         }
 
-        <Land2D<T>>::apply_around_circle(radius, &mut |dx, dy| {
-            <Land2D<T>>::apply_along_line(x1, y1, x2, y2, &mut |x, y| {
-                <Land2D<T>>::change_dots_around(x, y, dx, dy, &mut |x, y| {
-                    self.map(x, y, |p| {
-                        if *p != value {
-                            *p = value;
-                            1
-                        } else {
-                            0
-                        }
-                    })
-                })
-            })
-        })
+        result
     }
 }