1 extern crate fpnum; |
1 extern crate fpnum; |
2 |
2 |
3 use fpnum::distance; |
3 use fpnum::distance; |
4 use std::cmp::max; |
4 use std::cmp::max; |
5 use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, RangeInclusive, Sub, SubAssign}; |
5 use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Range, RangeInclusive, Sub, SubAssign}; |
6 |
6 |
7 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
7 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
8 pub struct Point { |
8 pub struct Point { |
9 pub x: i32, |
9 pub x: i32, |
10 pub y: i32, |
10 pub y: i32, |
63 pub fn cross(self, other: Point) -> i32 { |
68 pub fn cross(self, other: Point) -> i32 { |
64 self.dot(other.rotate90()) |
69 self.dot(other.rotate90()) |
65 } |
70 } |
66 |
71 |
67 #[inline] |
72 #[inline] |
68 pub fn fit(self, rect: &Rect) -> Point { |
73 pub fn clamp(self, rect: &Rect) -> Point { |
69 let x = if self.x > rect.right() { |
74 Point::new( |
70 rect.right() |
75 rect.x_range().clamp(self.x), |
71 } else if self.x < rect.left() { |
76 rect.y_range().clamp(self.y) |
72 rect.left() |
77 ) |
73 } else { |
78 } |
74 self.x |
79 |
75 }; |
80 #[inline] |
76 let y = if self.y > rect.bottom() { |
81 pub fn line_to(self, end: Point) -> Line { |
77 rect.bottom() |
82 Line::new(self, end) |
78 } else if self.y < rect.top() { |
83 } |
79 rect.top() |
84 |
80 } else { |
85 #[inline] |
81 self.y |
86 pub fn ray_to(self, end: Point) -> Ray { |
82 }; |
87 self.line_to(end).to_ray() |
83 |
88 } |
84 Point::new(x, y) |
89 |
|
90 #[inline] |
|
91 pub fn tangent(self) -> i32 { |
|
92 self.y / self.x |
|
93 } |
|
94 |
|
95 #[inline] |
|
96 pub fn cotangent(self) -> i32 { |
|
97 self.x / self.y |
85 } |
98 } |
86 } |
99 } |
87 |
100 |
88 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
101 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
89 pub struct Size { |
102 pub struct Size { |
344 #[inline] |
357 #[inline] |
345 pub fn y_range(&self) -> RangeInclusive<i32> { |
358 pub fn y_range(&self) -> RangeInclusive<i32> { |
346 self.y..=self.y + self.height as i32 |
359 self.y..=self.y + self.height as i32 |
347 } |
360 } |
348 |
361 |
349 /* requires #[feature(range_contains)] |
|
350 #[inline] |
362 #[inline] |
351 pub fn contains(&self, point: Point) -> bool { |
363 pub fn contains(&self, point: Point) -> bool { |
352 x_range().contains(point.x) && y_range.contains(point.y) |
364 self.x_range().contains(point.x) && self.y_range().contains(point.y) |
353 }*/ |
365 } |
354 |
366 |
355 #[inline] |
367 #[inline] |
356 pub fn contains_inside(&self, point: Point) -> bool { |
368 pub fn contains_inside(&self, point: Point) -> bool { |
357 point.x > self.left() |
369 point.x > self.left() |
358 && point.x < self.right() |
370 && point.x < self.right() |
376 Rect::from_box(point.x, self.right(), self.top(), point.y), |
388 Rect::from_box(point.x, self.right(), self.top(), point.y), |
377 Rect::from_box(point.x, self.right(), point.y, self.bottom()), |
389 Rect::from_box(point.x, self.right(), point.y, self.bottom()), |
378 Rect::from_box(self.left(), point.x, point.y, self.bottom()), |
390 Rect::from_box(self.left(), point.x, point.y, self.bottom()), |
379 ] |
391 ] |
380 } |
392 } |
|
393 |
|
394 #[inline] |
|
395 pub fn quotient(self, x: u32, y: u32) -> Point { |
|
396 self.top_left() + |
|
397 Point::new( |
|
398 (x % self.width) as i32, |
|
399 (y % self.height) as i32 |
|
400 ) |
|
401 } |
|
402 } |
|
403 |
|
404 trait RangeContains<T> { |
|
405 fn contains(&self, value: T) -> bool; |
|
406 } |
|
407 |
|
408 impl <T: Ord> RangeContains<T> for Range<T> { |
|
409 fn contains(&self, value: T) -> bool { |
|
410 value >= self.start && value < self.end |
|
411 } |
|
412 } |
|
413 |
|
414 impl <T: Ord> RangeContains<T> for RangeInclusive<T> { |
|
415 fn contains(&self, value: T) -> bool { |
|
416 value >= *self.start() && value <= *self.end() |
|
417 } |
|
418 } |
|
419 |
|
420 trait RangeClamp<T> { |
|
421 fn clamp(&self, value: T) -> T; |
|
422 } |
|
423 |
|
424 impl <T: Ord + Copy> RangeClamp<T> for RangeInclusive<T> { |
|
425 fn clamp(&self, value: T) -> T { |
|
426 if value < *self.start() { |
|
427 *self.start() |
|
428 } else if value > *self.end() { |
|
429 *self.end() |
|
430 } else { |
|
431 value |
|
432 } |
|
433 } |
381 } |
434 } |
382 |
435 |
383 pub struct Polygon { |
436 pub struct Polygon { |
384 vertices: Vec<Point>, |
437 vertices: Vec<Point>, |
385 } |
438 } |
433 Self { vertices: v } |
486 Self { vertices: v } |
434 } |
487 } |
435 } |
488 } |
436 |
489 |
437 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
490 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
|
491 pub struct Ray { |
|
492 pub start: Point, |
|
493 pub direction: Point |
|
494 } |
|
495 |
|
496 impl Ray { |
|
497 #[inline] |
|
498 pub fn new(start: Point, direction: Point) -> Ray { |
|
499 Self { start, direction } |
|
500 } |
|
501 |
|
502 #[inline] |
|
503 pub fn tangent(&self) -> i32 { |
|
504 self.direction.tangent() |
|
505 } |
|
506 |
|
507 #[inline] |
|
508 pub fn cotangent(&self) -> i32 { |
|
509 self.direction.cotangent() |
|
510 } |
|
511 |
|
512 #[inline] |
|
513 pub fn orientation(&self, point: Point) -> i32 { |
|
514 (point - self.start).cross(self.direction).signum() |
|
515 } |
|
516 } |
|
517 |
|
518 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
438 pub struct Line { |
519 pub struct Line { |
439 pub start: Point, |
520 pub start: Point, |
440 pub end: Point, |
521 pub end: Point, |
441 } |
522 } |
442 |
523 |
455 pub fn center(&self) -> Point { |
536 pub fn center(&self) -> Point { |
456 (self.start + self.end) / 2 |
537 (self.start + self.end) / 2 |
457 } |
538 } |
458 |
539 |
459 #[inline] |
540 #[inline] |
|
541 pub fn scaled_direction(&self) -> Point { |
|
542 self.end - self.start |
|
543 } |
|
544 |
|
545 #[inline] |
460 pub fn scaled_normal(&self) -> Point { |
546 pub fn scaled_normal(&self) -> Point { |
461 (self.end - self.start).rotate90() |
547 self.scaled_direction().rotate90() |
|
548 } |
|
549 |
|
550 #[inline] |
|
551 pub fn to_ray(&self) -> Ray { |
|
552 Ray::new(self.start, self.scaled_direction()) |
462 } |
553 } |
463 } |
554 } |
464 |
555 |
465 impl IntoIterator for Line { |
556 impl IntoIterator for Line { |
466 type Item = Point; |
557 type Item = Point; |