# HG changeset patch # User unc0rr # Date 1539891849 -7200 # Node ID 3f69a70063a581d91077a0a9e39f3e839b73f467 # Parent 1c30793b1cea171f70f88056180784e70d7c98b5 Implement ArcPoints iterator for circles diff -r 1c30793b1cea -r 3f69a70063a5 rust/integral-geometry/src/lib.rs --- a/rust/integral-geometry/src/lib.rs Thu Oct 18 07:27:14 2018 +0300 +++ b/rust/integral-geometry/src/lib.rs Thu Oct 18 21:44:09 2018 +0200 @@ -1,5 +1,5 @@ use std::cmp; -use std::ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; +use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub struct Point { @@ -10,7 +10,7 @@ impl Point { #[inline] pub fn new(x: i32, y: i32) -> Self { - Self {x, y} + Self { x, y } } #[inline] @@ -46,23 +46,22 @@ #[inline] fn $name(self, rhs: Self) -> Self::Output { - Self::new(self.x.$name(rhs.x), - self.y.$name(rhs.y)) + Self::new(self.x.$name(rhs.x), self.y.$name(rhs.y)) } } - } + }; } macro_rules! bin_assign_op_impl { ($op: ty, $name: tt) => { impl $op for Point { #[inline] - fn $name(&mut self, rhs: Self){ + fn $name(&mut self, rhs: Self) { self.x.$name(rhs.x); self.y.$name(rhs.y); } } - } + }; } bin_op_impl!(Add, add); @@ -123,6 +122,45 @@ } } +pub struct ArcPoints { + point: Point, + step: i32, +} + +impl ArcPoints { + pub fn new(radius: i32) -> Self { + Self { + point: Point::new(0, radius), + step: 3 - 2 * radius, + } + } +} + +impl Iterator for ArcPoints { + type Item = Point; + + fn next(&mut self) -> Option { + if self.point.x < self.point.y { + let result = self.point; + + if self.step < 0 { + self.step += self.point.x * 4 + 6; + } else { + self.step += (self.point.x - self.point.y) * 4 + 10; + self.point.y -= 1; + } + + self.point.x += 1; + + Some(result) + } else if self.point.x == self.point.y { + Some(self.point) + } else { + None + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -144,7 +182,16 @@ #[test] fn skewed() { let line = LinePoints::new(Point::new(0, 0), Point::new(5, -7)); - let v = get_points(&[(0, 0), (1, -1), (2, -2), (2, -3), (3, -4), (4, -5), (4, -6), (5, -7)]); + let v = get_points(&[ + (0, 0), + (1, -1), + (2, -2), + (2, -3), + (3, -4), + (4, -5), + (4, -6), + (5, -7), + ]); for (&a, b) in v.iter().zip(line) { assert_eq!(a, b);