bear_lib_terminal/geometry.rs
1//! Helper `struct`s for abstracting on-screen geometry.
2
3
4use std::fmt;
5
6
7/// Represents a single on-screen point/coordinate pair.
8#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
9pub struct Point {
10 pub x: i32,
11 pub y: i32,
12}
13
14impl Point {
15 /// Creates a new point on the specified non-negative coordinates
16 pub fn new(x: i32, y: i32) -> Point {
17 assert!(x >= 0);
18 assert!(y >= 0);
19
20 Point{
21 x: x,
22 y: y
23 }
24 }
25}
26
27
28/// A 2D size representation.
29#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
30pub struct Size {
31 pub width: i32,
32 pub height: i32,
33}
34
35impl Size {
36 /// Creates a new non-negative size.
37 pub fn new(width: i32, height: i32) -> Size {
38 assert!(width >= 0);
39 assert!(height >= 0);
40
41 Size{
42 width: width,
43 height: height,
44 }
45 }
46}
47
48impl fmt::Display for Size {
49 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
50 write!(formatter, "{}x{}", self.width, self.height)
51 }
52}
53
54
55/// A rectangle, described by its four corners and a size.
56#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
57pub struct Rect {
58 /// The top-left corner.
59 pub top_left: Point,
60 /// The top-right corner.
61 pub top_right: Point,
62 /// The bottom-right corner.
63 pub bottom_right: Point,
64 /// The bottom-left corner.
65 pub bottom_left: Point,
66 /// The `Rect`angle's size.
67 pub size: Size,
68}
69
70impl Rect {
71 /// Construct a `Rect` from its top-left corner and its size.
72 ///
73 /// # Examples
74 ///
75 /// ```
76 /// # use bear_lib_terminal::geometry::{Rect, Point, Size};
77 /// let rect = Rect::from_size(Point::new(10, 20), Size::new(30, 40));
78 /// assert_eq!(rect.top_left, Point::new(10, 20));
79 /// assert_eq!(rect.top_right, Point::new(40, 20));
80 /// assert_eq!(rect.bottom_left, Point::new(10, 60));
81 /// assert_eq!(rect.bottom_right, Point::new(40, 60));
82 /// assert_eq!(rect.size, Size::new(30, 40));
83 /// ```
84 pub fn from_size(origin: Point, size: Size) -> Rect {
85 let top_right = Point::new(origin.x + size.width, origin.y);
86 let bottom_left = Point::new(origin.x, origin.y + size.height);
87 let bottom_right = Point::new(top_right.x, bottom_left.y);
88
89 Rect{
90 top_left: origin,
91 top_right: top_right,
92 bottom_left: bottom_left,
93 bottom_right: bottom_right,
94 size: size
95 }
96 }
97
98 /// Construct a `Rect` from its top-left and bottom-right corners.
99 ///
100 /// # Examples
101 ///
102 /// ```
103 /// # use bear_lib_terminal::geometry::{Rect, Point, Size};
104 /// let rect = Rect::from_points(Point::new(10, 20), Point::new(30, 40));
105 /// assert_eq!(rect.top_left, Point::new(10, 20));
106 /// assert_eq!(rect.top_right, Point::new(30, 20));
107 /// assert_eq!(rect.bottom_left, Point::new(10, 40));
108 /// assert_eq!(rect.bottom_right, Point::new(30, 40));
109 /// assert_eq!(rect.size, Size::new(20, 20));
110 /// ```
111 pub fn from_points(top_left: Point, bottom_right: Point) -> Rect {
112 assert!(bottom_right.x >= top_left.x);
113 assert!(bottom_right.y >= top_left.y);
114
115 let size = Size::new(bottom_right.x - top_left.x, bottom_right.y - top_left.y);
116 Rect::from_size(top_left, size)
117 }
118
119 /// Construct a `Rect` from its top-left corner and its size, values unwrapped.
120 ///
121 /// # Examples
122 ///
123 /// ```
124 /// # use bear_lib_terminal::geometry::{Rect, Point, Size};
125 /// assert_eq!(Rect::from_values(10, 20, 30, 40), Rect::from_size(Point::new(10, 20), Size::new(30, 40)));
126 /// ```
127 pub fn from_values(x: i32, y: i32, width: i32, height: i32) -> Rect {
128 let origin = Point::new(x, y);
129 let size = Size::new(width, height);
130 Rect::from_size(origin, size)
131 }
132
133
134 /// Construct a `Rect` from its top-left and bottom-right corners, values unwrapped.
135 ///
136 /// # Examples
137 ///
138 /// ```
139 /// # use bear_lib_terminal::geometry::{Rect, Point, Size};
140 /// assert_eq!(Rect::from_point_values(10, 20, 30, 40), Rect::from_points(Point::new(10, 20), Point::new(30, 40)));
141 /// ```
142 pub fn from_point_values(top_left_x: i32, top_left_y: i32, bottom_right_x: i32, bottom_right_y: i32) -> Rect {
143 let top_left = Point::new(top_left_x, top_left_y);
144 let bottom_right = Point::new(bottom_right_x, bottom_right_y);
145 Rect::from_points(top_left, bottom_right)
146 }
147}