1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
use std::ops::Sub;
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Side { Top, Bottom, Left, Right }
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Corner { TopLeft, TopRight, BottomRight, BottomLeft }
impl Side {
pub fn opposite(&self) -> Side {
match self {
Side::Top => Side::Bottom,
Side::Right => Side::Left,
Side::Bottom => Side::Top,
Side::Left => Side::Right,
}
}
pub fn corners_on_side(&self) -> &[Corner] {
match self {
Side::Top => &[ Corner::TopLeft, Corner::TopRight ],
Side::Right => &[ Corner::TopRight, Corner::BottomRight ],
Side::Bottom => &[ Corner::BottomRight, Corner::BottomLeft ],
Side::Left => &[ Corner::BottomLeft, Corner::TopLeft ],
}
}
}
impl Corner {
pub fn first_clockwise_side(&self) -> Side {
match self {
Corner::TopLeft => Side::Left,
Corner::TopRight => Side::Top,
Corner::BottomRight => Side::Right,
Corner::BottomLeft => Side::Bottom,
}
}
}
pub trait Coordinate: Copy + From<u8> + Ord + Sub<Output=Self> { }
impl<T: Copy + From<u8> + Ord + Sub<Output=T>> Coordinate for T { }
#[derive(Debug)]
pub struct Point<T: Coordinate> {
pub x: T,
pub y: T,
}
#[derive(Debug)]
pub struct Rectangle<T: Coordinate> {
pub left: T,
pub top: T,
pub width: T,
pub height: T,
}
impl<T: Coordinate> Rectangle<T> {
pub fn corner_point(&self, corner: Corner) -> Point<T> {
match corner {
Corner::TopLeft => Point { x: T::from(0), y: T::from(0) },
Corner::TopRight => Point { x: self.width, y: T::from(0) },
Corner::BottomRight => Point { x: self.width, y: self.height },
Corner::BottomLeft => Point { x: T::from(0), y: self.height },
}
}
pub fn inset_from_corner_point(&self, corner: Corner, distance: T)
-> Point<T>
{
match corner {
Corner::TopLeft => Point { x: distance, y: distance },
Corner::TopRight => Point { x: self.width - distance, y: distance },
Corner::BottomRight => Point {
x: self.width - distance,
y: self.height - distance
},
Corner::BottomLeft => Point { x: distance, y: self.height - distance },
}
}
pub fn corner_square(&self, corner: Corner, size: T) -> Rectangle<T> {
let corner_point = self.corner_point(corner);
let inset_point = self.inset_from_corner_point(corner, size);
let left = corner_point.x.min(inset_point.x);
let top = corner_point.y.min(inset_point.y);
let right = corner_point.x.max(inset_point.x);
let bottom = corner_point.y.max(inset_point.y);
Rectangle {
left, top,
width: right - left,
height: bottom - top,
}
}
}
|