1#[cfg(feature="serde")]
2use serde::{Deserialize, Serialize};
3
4use super::{Coordinate, Dimensions};
5
6#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
19#[derive(Clone, Eq, Debug, Default, PartialEq)]
20pub struct Rectangle {
21 pub coordinate : Coordinate,
22 pub dimensions : Dimensions
23}
24
25impl Rectangle {
26 #[inline]
27 pub const fn width (&self) -> usize {
28 self.dimensions.columns
29 }
30 #[inline]
31 pub const fn height (&self) -> usize {
32 self.dimensions.rows
33 }
34 #[inline]
35 pub const fn min (&self) -> Coordinate {
36 self.coordinate
37 }
38 #[inline]
40 pub const fn max (&self) -> Coordinate {
41 Coordinate {
42 row: self.coordinate.row + self.height() - 1,
43 column: self.coordinate.column + self.width() - 1,
44 }
45 }
46 #[inline]
47 pub const fn upper_left (&self) -> Coordinate {
48 self.min()
49 }
50 #[inline]
51 pub const fn upper_right (&self) -> Coordinate {
52 Coordinate {
53 row: self.min().row,
54 column: self.max().column
55 }
56 }
57 #[inline]
58 pub const fn lower_right (&self) -> Coordinate {
59 self.max()
60 }
61 #[inline]
62 pub const fn lower_left (&self) -> Coordinate {
63 Coordinate {
64 row: self.max().row,
65 column: self.min().column
66 }
67 }
68 #[inline]
69 pub fn row (&self, row : usize) -> Option <Self> {
70 if row < self.height() {
71 let coordinate = self.min() + (row, 0).into();
72 let dimensions = (1, self.width()).into();
73 Some (Rectangle { coordinate, dimensions })
74 } else {
75 None
76 }
77 }
78 #[inline]
79 pub fn column (&self, column : usize) -> Option <Self> {
80 if column < self.width() {
81 let coordinate = self.min() + (0, column).into();
82 let dimensions = (self.height(), 1).into();
83 Some (Rectangle { coordinate, dimensions })
84 } else {
85 None
86 }
87 }
88 #[inline]
90 pub const fn area (&self) -> usize {
91 self.height() * self.width()
92 }
93 #[inline]
95 pub fn contains (&self, Coordinate { row, column } : Coordinate) -> bool {
96 self.contains_rc (row, column)
97 }
98 #[inline]
99 pub fn contains_rc (&self, row : usize, column : usize) -> bool {
100 self.min().row <= row && row <= self.max().row &&
101 self.min().column <= column && column <= self.max().column
102 }
103 #[inline]
104 pub fn iter (&self) -> impl Iterator <Item = Coordinate> {
105 let row = self.min().row;
106 let col = self.min().column;
107 let height = self.height();
108 let width = self.width();
109 (row..row + height).map (move |row| std::iter::repeat (row)
110 .zip (col..col + width)).flatten().map (Into::into)
111 }
112} impl From <(Coordinate, Dimensions)> for Rectangle {
114 fn from ((coordinate, dimensions) : (Coordinate, Dimensions)) -> Self {
115 Rectangle { coordinate, dimensions }
116 }
117}
118impl From <Dimensions> for Rectangle {
119 fn from (dimensions : Dimensions) -> Self {
120 Rectangle { coordinate: (0, 0).into(), dimensions }
121 }
122}