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 {}