Skip to main content

vec_rac/
vector.rs

1use std::fmt;
2use std::iter;
3use std::mem;
4use std::ops;
5
6#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash, Debug)]
7pub struct Vector {
8    pub x: i32,
9    pub y: i32,
10}
11
12impl Vector {
13    pub const ORIGIN: Vector = Vector { x: 0, y: 0 };
14
15    pub fn new(x: i32, y: i32) -> Vector {
16        Vector { x, y }
17    }
18
19    pub fn segment_pts(self, other: Vector) -> SegmentPts {
20        let disp_x = (other.x - self.x) as f64;
21        let disp_y = (other.y - self.y) as f64;
22        let hypot = f64::hypot(disp_x, disp_y);
23        SegmentPts {
24            from: self,
25            to: other,
26            x: self.x as f64,
27            y: self.y as f64,
28            dx: disp_x / hypot,
29            dy: disp_y / hypot,
30            done: false,
31        }
32    }
33}
34
35impl ops::Add for Vector {
36    type Output = Vector;
37
38    fn add(self, other: Vector) -> Vector {
39        Vector::new(self.x + other.x, self.y + other.y)
40    }
41}
42
43impl ops::Sub for Vector {
44    type Output = Vector;
45
46    fn sub(self, other: Vector) -> Vector {
47        Vector::new(self.x - other.x, self.y - other.y)
48    }
49}
50
51impl ops::Neg for Vector {
52    type Output = Vector;
53
54    fn neg(self) -> Vector {
55        Vector::new(-self.x, -self.y)
56    }
57}
58
59impl fmt::Display for Vector {
60    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61        write!(f, "({}, {})", self.x, self.y)
62    }
63}
64
65#[derive(Clone, PartialEq)]
66pub struct SegmentPts {
67    from: Vector,
68    to: Vector,
69    x: f64,
70    y: f64,
71    dx: f64,
72    dy: f64,
73    done: bool,
74}
75
76impl Iterator for SegmentPts {
77    type Item = Vector;
78
79    fn next(&mut self) -> Option<Vector> {
80        if self.done {
81            None
82        } else if self.from == self.to {
83            self.done = true;
84            Some(self.from)
85        } else {
86            self.x += self.dx;
87            self.y += self.dy;
88            Some(mem::replace(
89                &mut self.from,
90                Vector {
91                    x: f64::round(self.x) as i32,
92                    y: f64::round(self.y) as i32,
93                },
94            ))
95        }
96    }
97
98    fn size_hint(&self) -> (usize, Option<usize>) {
99        if self.done {
100            (0, Some(0))
101        } else {
102            (1, None)
103        }
104    }
105}
106
107impl iter::FusedIterator for SegmentPts {}
108
109#[derive(Clone, PartialEq)]
110pub struct CirclePts {
111    pos: Vector,
112    radius: i32,
113    end_y: i32,
114}
115
116pub fn circle_pts(radius: i32) -> CirclePts {
117    let abs_rad = i32::abs(radius);
118    CirclePts {
119        radius: abs_rad,
120        pos: Vector::new(-abs_rad, -1),
121        end_y: 0,
122    }
123}
124
125impl Iterator for CirclePts {
126    type Item = Vector;
127
128    fn next(&mut self) -> Option<Vector> {
129        if self.pos.x > self.radius {
130            None
131        } else if self.pos.y < self.end_y {
132            self.pos.y += 1;
133            Some(self.pos)
134        } else {
135            self.pos.x += 1;
136            if self.pos.x <= self.radius {
137                let r = self.radius as f64;
138                let x = self.pos.x as f64;
139                let y = f64::sqrt(r * r - x * x);
140                self.end_y = y as i32;
141                self.pos.y = -self.end_y;
142                Some(self.pos)
143            } else {
144                None
145            }
146        }
147    }
148}
149
150impl iter::FusedIterator for CirclePts {}