1use std::fmt::{Display, Formatter};
24use std::iter::FromIterator;
25use std::ops::{Add, Div, Index, Neg, Sub};
26use std::slice::Iter;
27use std::vec::IntoIter;
28
29#[derive(Debug, Copy, Clone, PartialEq)]
31pub struct Point {
32 x: f64,
33 y: f64
34}
35
36impl Point {
37 #[inline]
38 pub fn new(x: f64, y: f64) -> Self {
39 Point { x, y }
40 }
41
42 #[inline]
43 pub fn zero() -> Self {
44 Point { x: 0.0, y: 0.0 }
45 }
46
47 #[inline]
48 pub fn x(&self) -> f64 {
49 self.x
50 }
51
52 #[inline]
53 pub fn y(&self) -> f64 {
54 self.y
55 }
56}
57
58
59#[derive(Debug, Copy, Clone, PartialEq)]
62pub struct Vector {
63 x: f64,
64 y: f64
65}
66
67impl Vector {
68 #[inline]
69 pub fn new(x: f64, y: f64) -> Self {
70 Vector { x, y }
71 }
72
73 #[inline]
74 pub fn up() -> Self {
75 Vector::new(0.0, 1.0)
76 }
77
78 #[inline]
79 pub fn down() -> Self {
80 Vector::new(0.0, -1.0)
81 }
82
83 #[inline]
84 pub fn zero() -> Self {
85 Vector::new(0.0, 0.0)
86 }
87
88 pub fn norm(&self) -> f64 {
89 (self.x.powi(2) + self.y.powi(2)).sqrt()
90 }
91
92 #[inline]
93 pub fn x(&self) -> f64 {
94 self.x
95 }
96
97 #[inline]
98 pub fn y(&self) -> f64 {
99 self.y
100 }
101
102 pub fn rotate(&self, degrees: f64) -> Self {
117 let cos = degrees.to_radians().cos();
118 let sin = degrees.to_radians().sin();
119
120 Vector::new(
121 cos * self.x() - sin * self.y(),
122 sin * self.x() + cos * self.y()
123 )
124 }
125}
126
127impl Default for Vector {
128 #[inline]
129 fn default() -> Self {
130 Vector::zero()
131 }
132}
133
134impl Default for Point {
135 #[inline]
136 fn default() -> Self {
137 Point::zero()
138 }
139}
140
141impl From<Point> for Vector {
142 #[inline]
143 fn from(value: Point) -> Self {
144 Vector::new(value.x, value.y)
145 }
146}
147
148impl From<Vector> for Point {
149 #[inline]
150 fn from(value: Vector) -> Self {
151 Point::new(value.x, value.y)
152 }
153}
154
155
156impl Add for Vector {
157 type Output = Vector;
158
159 fn add(self, rhs: Self) -> Self::Output {
160 Vector::new(self.x() + rhs.x(), self.y() + rhs.y())
161 }
162}
163
164impl Sub for Vector {
165 type Output = Vector;
166
167 fn sub(self, rhs: Self) -> Self::Output {
168 Vector::new(self.x() - rhs.x(), self.y() - rhs.y())
169 }
170}
171
172impl Neg for Vector {
173 type Output = Vector;
174
175 fn neg(self) -> Self::Output {
176 Vector::new(-self.x(), -self.y())
177 }
178}
179
180impl Add<Vector> for Point {
181 type Output = Point;
182
183 fn add(self, rhs: Vector) -> Self::Output {
184 Point::new(self.x + rhs.x, self.y + rhs.y)
185 }
186}
187
188impl Add for Point {
189 type Output = Point;
190
191 fn add(self, rhs: Self) -> Self::Output {
192 Point::new(self.x + rhs.x, self.y + rhs.y)
193 }
194}
195
196impl Sub<Vector> for Point {
197 type Output = Point;
198
199 fn sub(self, rhs: Vector) -> Self::Output {
200 Point::new(self.x - rhs.x, self.y - rhs.y)
201 }
202}
203
204impl Sub for Point {
205 type Output = Point;
206
207 fn sub(self, rhs: Self) -> Self::Output {
208 Point::new(self.x - rhs.x, self.y - rhs.y)
209 }
210}
211
212impl Div<f64> for Point {
213 type Output = Point;
214
215 fn div(self, rhs: f64) -> Self::Output {
216 Point::new(self.x() / rhs, self.y() / rhs)
217 }
218}
219
220impl Neg for Point {
221 type Output = Point;
222
223 fn neg(self) -> Self::Output {
224 Point::new(-self.x, -self.y)
225 }
226}
227
228impl Display for Point {
229 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
230 write!(f, "({},{})", self.x, self.y)
231 }
232}
233
234impl Display for Vector {
235 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
236 write!(f, "({},{})", self.x, self.y)
237 }
238}
239
240#[derive(Debug, Clone)]
243pub struct Path {
244 points: Vec<Point>
245}
246
247impl Path {
248 #[inline]
249 pub fn new() -> Self {
250 Path { points: Vec::new() }
251 }
252
253 #[inline]
254 pub fn len(&self) -> usize {
255 self.points.len()
256 }
257
258 #[inline]
259 pub fn is_empty(&self) -> bool {
260 self.points.is_empty()
261 }
262
263 #[inline]
264 pub fn push<T: Into<Point>>(&mut self, point: T) {
265 self.points.push(point.into())
266 }
267
268 #[inline]
269 pub fn get(&self, index: usize) -> Option<&Point> {
270 self.points.get(index)
271 }
272
273 #[inline]
274 pub fn iter(&self) -> Iter<'_, Point> {
275 self.points.iter()
276 }
277
278 #[inline]
280 pub fn get_start(&self) -> Option<&Point> {
281 self.points.first()
282 }
283}
284
285impl Index<usize> for Path {
286 type Output = Point;
287
288 fn index(&self, index: usize) -> &Self::Output {
289 &self.points[index]
290 }
291}
292
293impl Default for Path {
294 fn default() -> Self {
295 Path::new()
296 }
297}
298
299impl IntoIterator for Path {
300 type Item = Point;
301 type IntoIter = IntoIter<Point>;
302
303 fn into_iter(self) -> Self::IntoIter {
304 self.points.into_iter()
305 }
306}
307
308impl FromIterator<Point> for Path {
310 fn from_iter<T: IntoIterator<Item=Point>>(iter: T) -> Self {
311 Path { points: iter.into_iter().collect() }
312 }
313}
314
315impl Add<Vector> for Path {
317 type Output = Path;
318
319 fn add(self, rhs: Vector) -> Self::Output {
320 self.into_iter().map(|p| p + rhs).collect()
321 }
322}
323
324#[derive(Debug, Clone, Default)]
326pub struct BoundingBox {
327 pub min_x: f64,
328 pub max_x: f64,
329 pub min_y: f64,
330 pub max_y: f64,
331 pub com: Point
333}
334
335impl BoundingBox {
336 #[inline]
337 pub fn width(&self) -> f64 {
338 (self.max_x - self.min_x).abs()
339 }
340
341 #[inline]
342 pub fn height(&self) -> f64 {
343 (self.max_y - self.min_y).abs()
344 }
345
346 #[inline]
348 pub fn center(&self) -> Point {
349 Point::new((self.max_x + self.min_x) / 2.0, (self.max_y + self.min_y) / 2.0)
350 }
351
352 fn initial_infinite() -> Self {
354 BoundingBox {
355 min_x: f64::INFINITY,
356 max_x: f64::NEG_INFINITY,
357 min_y: f64::INFINITY,
358 max_y: f64::NEG_INFINITY,
359 ..Default::default()
360 }
361 }
362
363 pub fn zero() -> Self {
367 Self::default()
368 }
369}
370
371pub trait Bounds {
376 fn bounds(&self) -> Option<BoundingBox>;
377}
378
379impl Bounds for Path {
380 fn bounds(&self) -> Option<BoundingBox> {
383 let mut bounds = BoundingBox::initial_infinite();
384
385 let mut center = Point::zero();
386
387 for point in &self.points {
388 center = center + *point;
389
390 if point.x < bounds.min_x {
391 bounds.min_x = point.x;
392 }
393 if point.x > bounds.max_x {
394 bounds.max_x = point.x;
395 }
396 if point.y < bounds.min_y {
397 bounds.min_y = point.y;
398 }
399 if point.y > bounds.max_y {
400 bounds.max_y = point.y;
401 }
402 }
403
404 bounds.com = center / self.len() as f64;
405
406 Some(bounds)
407 }
408}
409
410impl Bounds for Vec<Path> {
411 fn bounds(&self) -> Option<BoundingBox> {
412 let mut min_x = f64::INFINITY;
413 let mut max_x = f64::NEG_INFINITY;
414 let mut min_y = f64::INFINITY;
415 let mut max_y = f64::NEG_INFINITY;
416
417 let mut center = Point::zero();
418 let mut len = 0_f64;
419
420 for path in self {
421 len += path.len() as f64;
422
423 for point in &path.points {
424 center = center + *point;
425
426 if point.x < min_x {
427 min_x = point.x;
428 }
429 if point.x > max_x {
430 max_x = point.x;
431 }
432 if point.y < min_y {
433 min_y = point.y;
434 }
435 if point.y > max_y {
436 max_y = point.y;
437 }
438 }
439 }
440
441 if min_x.is_infinite() {
442 return None
443 }
444
445 Some(BoundingBox {
446 min_x,
447 max_x,
448 min_y,
449 max_y,
450 com: center / len
451 })
452 }
453}
454
455
456#[cfg(test)]
457mod tests {
458 use super::*;
459
460 #[test]
461 fn testing_rotations() {
462 let up = Vector::up();
463 let one = up.rotate(90.0);
464
465 assert_eq!(up, Vector::new(0.0, 1.0));
466
467 assert!((one.x - -1.0).abs() < 0.001);
468 assert!((one.y - 0.0).abs() < 0.001);
469 }
470
471 #[test]
472 fn bounding_box() {
473 assert_eq!(BoundingBox::zero().width(), 0.0);
474 assert_eq!(BoundingBox::zero().height(), 0.0);
475 assert_eq!(BoundingBox { min_y: -12.0, max_y: 100.0, ..Default::default()}.height(), 112.0);
476 assert_eq!(BoundingBox { min_x: -10.0, max_x: 100.0, ..Default::default()}.width(), 110.0);
477
478 let b = BoundingBox { min_x: -22.0, max_x:-2.0, min_y: 100.0, max_y: 101.0, ..BoundingBox::default()};
479 assert_eq!(b.width(), 20.0);
480 assert_eq!(b.height(), 1.0);
481 assert_eq!(b.center().x, -12.0);
482 assert_eq!(b.center().y, 100.5);
483 }
484}