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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//!
//! User interface geometry
//!
//! The 2D coordinate system in X-Plane has its origin in the lower left corner of the window.
//! Its units are pixels. [More information about X-Plane's coordinate systems is available here]
//! (http://www.xsquawkbox.net/xpsdk/mediawiki/ScreenCoordinates)
//!

/// A 2-dimensional rectangle
#[derive(Debug, Copy, Clone)]
pub struct Rect<N> {
    /// The top coordinate
    top: N,
    /// The bottom coordinate
    bottom: N,
    /// The left coordinate
    left: N,
    /// The right coordinate
    right: N,
}

impl<N> Rect<N> {
    /// Creates a rectangle from left, top, right, and bottom coordinates
    pub fn from_left_top_right_bottom(left: N, top: N, right: N, bottom: N) -> Self {
        Rect {
            top,
            bottom,
            left,
            right,
        }
    }
    /// Creates a rectangle from a top left corner and a bottom right corner
    pub fn from_corners(top_left: Point<N>, bottom_right: Point<N>) -> Self {
        let (left, top) = top_left.into_xy();
        let (bottom, right) = bottom_right.into_xy();
        Rect {
            top,
            bottom,
            left,
            right,
        }
    }
    /// Consumes this rectangle and returns its left, top, bottom, and right coordinates
    pub fn into_left_top_bottom_right(self) -> (N, N, N, N) {
        (self.left, self.top, self.bottom, self.right)
    }

    pub fn set_top(&mut self, top: N) {
        self.top = top;
    }
    pub fn set_left(&mut self, left: N) {
        self.left = left;
    }
    pub fn set_bottom(&mut self, bottom: N) {
        self.bottom = bottom;
    }
    pub fn set_right(&mut self, right: N) {
        self.right = right;
    }

    /// Determines whether this rectangle contains a point
    ///
    /// For this calculation, the bottom and left edges are inside the rectangle, while the
    /// top and right edges are outside.
    pub fn contains(&self, point: Point<N>) -> bool
    where
        N: PartialOrd,
    {
        let (x, y) = point.into_xy();
        x >= self.left && x < self.right && y >= self.bottom && y < self.top
    }
}

impl<N: Clone> Rect<N> {
    pub fn top(&self) -> N {
        self.top.clone()
    }
    pub fn bottom(&self) -> N {
        self.bottom.clone()
    }
    pub fn left(&self) -> N {
        self.left.clone()
    }
    pub fn right(&self) -> N {
        self.right.clone()
    }
}

/// A 2D point
#[derive(Debug, Copy, Clone)]
pub struct Point<N> {
    /// The X coordinate
    x: N,
    /// The Y coordinate
    y: N,
}

impl<N> Point<N> {
    /// Creates a point from X and Y coordinates
    pub fn from_xy(x: N, y: N) -> Self {
        Point { x, y }
    }
    pub fn set_x(&mut self, x: N) {
        self.x = x;
    }
    pub fn set_y(&mut self, y: N) {
        self.y = y;
    }
    pub fn into_xy(self) -> (N, N) {
        (self.x, self.y)
    }
}

impl<N: Clone> Point<N> {
    pub fn x(&self) -> N {
        self.x.clone()
    }
    pub fn y(&self) -> N {
        self.y.clone()
    }
}

impl<N> From<(N, N)> for Point<N> {
    /// Converts an (x, y) pair into a point
    fn from((x, y): (N, N)) -> Self {
        Point::from_xy(x, y)
    }
}