rust/integral-geometry/src/lib.rs
author unc0rr
Wed, 31 Oct 2018 23:36:05 +0100
changeset 14051 8a0d69c16cad
parent 13950 48796bef9e69
child 14052 9c817b2eedae
permissions -rw-r--r--
Implement OutlinePoints for land generators, some ground work for template based landgen
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
13935
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
     1
use std::cmp;
13941
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
     2
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
     3
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
     4
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
     5
pub struct Point {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
     6
    pub x: i32,
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
     7
    pub y: i32,
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
     8
}
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
     9
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    10
impl Point {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    11
    #[inline]
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    12
    pub fn new(x: i32, y: i32) -> Self {
13941
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
    13
        Self { x, y }
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    14
    }
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    15
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    16
    #[inline]
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    17
    pub fn zero() -> Self {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    18
        Self::new(0, 0)
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    19
    }
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    20
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    21
    #[inline]
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    22
    pub fn signum(self) -> Self {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    23
        Self::new(self.x.signum(), self.y.signum())
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    24
    }
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    25
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    26
    #[inline]
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    27
    pub fn abs(self) -> Self {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    28
        Self::new(self.x.abs(), self.y.abs())
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    29
    }
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    30
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    31
    #[inline]
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    32
    pub fn dot(self, other: Point) -> i32 {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    33
        self.x * other.x + self.y * other.y
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    34
    }
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    35
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    36
    #[inline]
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    37
    pub fn max_norm(self) -> i32 {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    38
        std::cmp::max(self.x.abs(), self.y.abs())
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    39
    }
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    40
}
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    41
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    42
macro_rules! bin_op_impl {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    43
    ($op: ty, $name: tt) => {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    44
        impl $op for Point {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    45
            type Output = Self;
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    46
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    47
            #[inline]
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    48
            fn $name(self, rhs: Self) -> Self::Output {
13941
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
    49
                Self::new(self.x.$name(rhs.x), self.y.$name(rhs.y))
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    50
            }
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    51
        }
13941
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
    52
    };
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    53
}
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    54
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    55
macro_rules! bin_assign_op_impl {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    56
    ($op: ty, $name: tt) => {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    57
        impl $op for Point {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    58
            #[inline]
13941
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
    59
            fn $name(&mut self, rhs: Self) {
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    60
                self.x.$name(rhs.x);
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    61
                self.y.$name(rhs.y);
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    62
            }
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    63
        }
13941
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
    64
    };
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    65
}
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    66
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    67
bin_op_impl!(Add, add);
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    68
bin_op_impl!(Sub, sub);
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    69
bin_op_impl!(Mul, mul);
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    70
bin_op_impl!(Div, div);
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    71
bin_assign_op_impl!(AddAssign, add_assign);
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    72
bin_assign_op_impl!(SubAssign, sub_assign);
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    73
bin_assign_op_impl!(MulAssign, mul_assign);
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    74
bin_assign_op_impl!(DivAssign, div_assign);
13935
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
    75
14051
8a0d69c16cad Implement OutlinePoints for land generators, some ground work for template based landgen
unc0rr
parents: 13950
diff changeset
    76
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
8a0d69c16cad Implement OutlinePoints for land generators, some ground work for template based landgen
unc0rr
parents: 13950
diff changeset
    77
pub struct Rect {
8a0d69c16cad Implement OutlinePoints for land generators, some ground work for template based landgen
unc0rr
parents: 13950
diff changeset
    78
    pub x: i32,
8a0d69c16cad Implement OutlinePoints for land generators, some ground work for template based landgen
unc0rr
parents: 13950
diff changeset
    79
    pub y: i32,
8a0d69c16cad Implement OutlinePoints for land generators, some ground work for template based landgen
unc0rr
parents: 13950
diff changeset
    80
    pub width: u32,
8a0d69c16cad Implement OutlinePoints for land generators, some ground work for template based landgen
unc0rr
parents: 13950
diff changeset
    81
    pub height: u32,
8a0d69c16cad Implement OutlinePoints for land generators, some ground work for template based landgen
unc0rr
parents: 13950
diff changeset
    82
}
8a0d69c16cad Implement OutlinePoints for land generators, some ground work for template based landgen
unc0rr
parents: 13950
diff changeset
    83
8a0d69c16cad Implement OutlinePoints for land generators, some ground work for template based landgen
unc0rr
parents: 13950
diff changeset
    84
impl Rect {
8a0d69c16cad Implement OutlinePoints for land generators, some ground work for template based landgen
unc0rr
parents: 13950
diff changeset
    85
    #[inline]
8a0d69c16cad Implement OutlinePoints for land generators, some ground work for template based landgen
unc0rr
parents: 13950
diff changeset
    86
    pub fn new(x: i32, y: i32, width: u32, height: u32) -> Self {
8a0d69c16cad Implement OutlinePoints for land generators, some ground work for template based landgen
unc0rr
parents: 13950
diff changeset
    87
        Self { x, y, width, height }
8a0d69c16cad Implement OutlinePoints for land generators, some ground work for template based landgen
unc0rr
parents: 13950
diff changeset
    88
    }
8a0d69c16cad Implement OutlinePoints for land generators, some ground work for template based landgen
unc0rr
parents: 13950
diff changeset
    89
}
8a0d69c16cad Implement OutlinePoints for land generators, some ground work for template based landgen
unc0rr
parents: 13950
diff changeset
    90
8a0d69c16cad Implement OutlinePoints for land generators, some ground work for template based landgen
unc0rr
parents: 13950
diff changeset
    91
13935
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
    92
pub struct LinePoints {
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    93
    accumulator: Point,
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    94
    direction: Point,
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    95
    sign: Point,
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    96
    current: Point,
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    97
    total_steps: i32,
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
    98
    step: i32,
13935
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
    99
}
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   100
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   101
impl LinePoints {
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   102
    pub fn new(from: Point, to: Point) -> Self {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   103
        let dir = to - from;
13935
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   104
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   105
        Self {
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   106
            accumulator: Point::zero(),
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   107
            direction: dir.abs(),
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   108
            sign: dir.signum(),
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   109
            current: from,
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   110
            total_steps: dir.max_norm(),
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   111
            step: 0,
13935
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   112
        }
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   113
    }
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   114
}
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   115
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   116
impl Iterator for LinePoints {
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   117
    type Item = Point;
13935
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   118
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   119
    fn next(&mut self) -> Option<Self::Item> {
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   120
        if self.step <= self.total_steps {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   121
            self.accumulator += self.direction;
13935
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   122
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   123
            if self.accumulator.x > self.total_steps {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   124
                self.accumulator.x -= self.total_steps;
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   125
                self.current.x += self.sign.x;
13935
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   126
            }
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   127
            if self.accumulator.y > self.total_steps {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   128
                self.accumulator.y -= self.total_steps;
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   129
                self.current.y += self.sign.y;
13935
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   130
            }
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   131
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   132
            self.step += 1;
13935
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   133
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   134
            Some(self.current)
13935
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   135
        } else {
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   136
            None
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   137
        }
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   138
    }
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   139
}
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   140
13941
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   141
pub struct ArcPoints {
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   142
    point: Point,
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   143
    step: i32,
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   144
}
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   145
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   146
impl ArcPoints {
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   147
    pub fn new(radius: i32) -> Self {
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   148
        Self {
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   149
            point: Point::new(0, radius),
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   150
            step: 3 - 2 * radius,
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   151
        }
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   152
    }
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   153
}
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   154
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   155
impl Iterator for ArcPoints {
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   156
    type Item = Point;
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   157
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   158
    fn next(&mut self) -> Option<Self::Item> {
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   159
        if self.point.x < self.point.y {
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   160
            let result = self.point;
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   161
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   162
            if self.step < 0 {
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   163
                self.step += self.point.x * 4 + 6;
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   164
            } else {
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   165
                self.step += (self.point.x - self.point.y) * 4 + 10;
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   166
                self.point.y -= 1;
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   167
            }
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   168
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   169
            self.point.x += 1;
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   170
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   171
            Some(result)
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   172
        } else if self.point.x == self.point.y {
13947
85645992bc8a Fix ArcPoints never finishing
unc0rr
parents: 13943
diff changeset
   173
            self.point.x += 1;
13950
48796bef9e69 Add --protocol option to engine
unc0rr
parents: 13947
diff changeset
   174
13941
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   175
            Some(self.point)
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   176
        } else {
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   177
            None
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   178
        }
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   179
    }
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   180
}
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   181
13942
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   182
pub struct EquidistantPoints {
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   183
    vector: Point,
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   184
    iteration: u8,
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   185
}
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   186
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   187
impl EquidistantPoints {
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   188
    pub fn new(vector: Point) -> Self {
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   189
        Self {
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   190
            vector,
13943
a325ed57ebfe Don't generate unnecessary duplication in case of equal coordinates
unc0rr
parents: 13942
diff changeset
   191
            iteration: if vector.x == vector.y { 4 } else { 8 },
13942
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   192
        }
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   193
    }
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   194
}
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   195
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   196
impl Iterator for EquidistantPoints {
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   197
    type Item = Point;
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   198
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   199
    fn next(&mut self) -> Option<Self::Item> {
13943
a325ed57ebfe Don't generate unnecessary duplication in case of equal coordinates
unc0rr
parents: 13942
diff changeset
   200
        if self.iteration > 0 {
13942
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   201
            self.vector.x = -self.vector.x;
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   202
            if self.iteration & 1 == 0 {
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   203
                self.vector.y = -self.vector.y;
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   204
            }
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   205
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   206
            if self.iteration == 4 {
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   207
                std::mem::swap(&mut self.vector.x, &mut self.vector.y);
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   208
            }
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   209
13943
a325ed57ebfe Don't generate unnecessary duplication in case of equal coordinates
unc0rr
parents: 13942
diff changeset
   210
            self.iteration -= 1;
13942
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   211
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   212
            Some(self.vector)
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   213
        } else {
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   214
            None
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   215
        }
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   216
    }
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   217
}
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   218
13935
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   219
#[cfg(test)]
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   220
mod tests {
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   221
    use super::*;
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   222
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   223
    fn get_points(coords: &[(i32, i32)]) -> Vec<Point> {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   224
        coords.iter().map(|(x, y)| Point::new(*x, *y)).collect()
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   225
    }
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   226
13935
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   227
    #[test]
13942
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   228
    fn line_basic() {
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   229
        let line = LinePoints::new(Point::new(0, 0), Point::new(3, 3));
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   230
        let v = get_points(&[(0, 0), (1, 1), (2, 2), (3, 3), (123, 456)]);
13935
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   231
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   232
        for (&a, b) in v.iter().zip(line) {
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   233
            assert_eq!(a, b);
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   234
        }
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   235
    }
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   236
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   237
    #[test]
13942
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   238
    fn line_skewed() {
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   239
        let line = LinePoints::new(Point::new(0, 0), Point::new(5, -7));
13941
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   240
        let v = get_points(&[
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   241
            (0, 0),
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   242
            (1, -1),
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   243
            (2, -2),
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   244
            (2, -3),
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   245
            (3, -4),
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   246
            (4, -5),
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   247
            (4, -6),
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   248
            (5, -7),
3f69a70063a5 Implement ArcPoints iterator for circles
unc0rr
parents: 13938
diff changeset
   249
        ]);
13938
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   250
1fa905aa4cdb move point struct into integral-geometry and use it to refactor a bit
alfadur
parents: 13937
diff changeset
   251
        for (&a, b) in v.iter().zip(line) {
13935
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   252
            assert_eq!(a, b);
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   253
        }
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   254
    }
13942
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   255
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   256
    #[test]
13943
a325ed57ebfe Don't generate unnecessary duplication in case of equal coordinates
unc0rr
parents: 13942
diff changeset
   257
    fn equidistant_full() {
13942
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   258
        let n = EquidistantPoints::new(Point::new(1, 3));
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   259
        let v = get_points(&[
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   260
            (-1, -3),
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   261
            (1, -3),
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   262
            (-1, 3),
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   263
            (1, 3),
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   264
            (-3, -1),
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   265
            (3, -1),
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   266
            (-3, 1),
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   267
            (3, 1),
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   268
            (123, 456),
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   269
        ]);
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   270
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   271
        for (&a, b) in v.iter().zip(n) {
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   272
            assert_eq!(a, b);
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   273
        }
7e7a03e85ac4 Add EquidistantPoints iterator to help iterating over all points of circles
unc0rr
parents: 13941
diff changeset
   274
    }
13943
a325ed57ebfe Don't generate unnecessary duplication in case of equal coordinates
unc0rr
parents: 13942
diff changeset
   275
a325ed57ebfe Don't generate unnecessary duplication in case of equal coordinates
unc0rr
parents: 13942
diff changeset
   276
    #[test]
a325ed57ebfe Don't generate unnecessary duplication in case of equal coordinates
unc0rr
parents: 13942
diff changeset
   277
    fn equidistant_half() {
a325ed57ebfe Don't generate unnecessary duplication in case of equal coordinates
unc0rr
parents: 13942
diff changeset
   278
        let n = EquidistantPoints::new(Point::new(2, 2));
a325ed57ebfe Don't generate unnecessary duplication in case of equal coordinates
unc0rr
parents: 13942
diff changeset
   279
        let v = get_points(&[(-2, -2), (2, -2), (-2, 2), (2, 2), (123, 456)]);
a325ed57ebfe Don't generate unnecessary duplication in case of equal coordinates
unc0rr
parents: 13942
diff changeset
   280
a325ed57ebfe Don't generate unnecessary duplication in case of equal coordinates
unc0rr
parents: 13942
diff changeset
   281
        for (&a, b) in v.iter().zip(n) {
a325ed57ebfe Don't generate unnecessary duplication in case of equal coordinates
unc0rr
parents: 13942
diff changeset
   282
            assert_eq!(a, b);
a325ed57ebfe Don't generate unnecessary duplication in case of equal coordinates
unc0rr
parents: 13942
diff changeset
   283
        }
a325ed57ebfe Don't generate unnecessary duplication in case of equal coordinates
unc0rr
parents: 13942
diff changeset
   284
    }
13935
75eaf7c71789 Introduce integral-geometry crate, implement LinePoints iterator
unc0rr
parents:
diff changeset
   285
}