shape_core/elements/rectangles/rectangle_2d/mod.rs
1use super::*;
2
3mod constructors;
4mod arith;
5
6/// A non-rotated rectangle, used to represent AABB collision boxes.
7///
8/// # Notice
9///
10/// The constructor will not check the legality of the parameters, it is possible that two points coincide, or the side length is negative
11///
12/// # Examples
13///
14/// ```
15/// # use shape_core::Rectangle;
16/// let rect = Rectangle::new(0.0, 0.0, 1.0, 1.0);
17/// ```
18#[cfg_attr(feature = "serde", repr(C), derive(Serialize, Deserialize))]
19#[derive(Copy, Clone, PartialEq, Eq, Hash)]
20pub struct Rectangle<T> {
21 /// origin x points of the rectangle
22 pub min: Point<T>,
23 /// origin y points of the rectangle
24 pub max: Point<T>,
25}
26
27impl<T> Shape2D for Rectangle<T>
28where
29 T: Signed + Clone + PartialOrd,
30{
31 type Value = T;
32 type VertexIterator<'a>
33
34 = IntoIter<Point<T>>where
35 T: 'a;
36 type LineIterator<'a>
37
38 = IntoIter<Line<T>>where
39 T: 'a;
40
41 /// A valid rectangle means it has a positive area.
42 ///
43 /// # Examples
44 ///
45 /// ```
46 /// # use shape_core::{Rectangle, Shape2D};
47 /// let rect = Rectangle::new(0.0, 0.0, 1.0, 1.0);
48 /// assert!(rect.is_valid());
49 /// ```
50 fn is_valid(&self) -> bool {
51 // can not be zero area
52 self.max.x > self.min.x && self.max.y > self.min.y
53 }
54
55 fn normalize(&mut self) -> bool {
56 *self = self.boundary();
57 // maybe zero area after flip
58 self.is_valid()
59 }
60 /// # SAFETY
61 ///
62 /// It may return a zero area rectangle if shape is not valid.
63 ///
64 /// It never returns a rectangle with negative area.
65 ///
66 /// # Examples
67 ///
68 /// ```ignore
69 /// # use shape_core::{Rectangle, Shape2D};
70 /// let rect = Rectangle::new(0.0, 0.0, -1.0, -1.0);
71 /// assert_eq!(rect.boundary(), Rectangle::new(0.0,0.0, 1.0,1.0));
72 /// ```
73 fn boundary(&self) -> Rectangle<Self::Value> {
74 let min_x = min2(&self.min.x, &self.max.x).clone();
75 let min_y = min2(&self.min.y, &self.max.y).clone();
76 let max_x = max2(&self.max.x, &self.min.x).clone();
77 let max_y = max2(&self.max.y, &self.min.y).clone();
78 Rectangle { min: Point { x: min_x, y: min_y }, max: Point { x: max_x, y: max_y } }
79 }
80
81 /// Returns four vertices counterclockwise in the **↑Y coordinate system**
82 fn vertices<'a>(&'a self, _: usize) -> Self::VertexIterator<'a> {
83 // yield self.min.clone();
84 // yield Point { x: self.max.x.clone(), y: self.min.y.clone() };
85 // yield self.max.clone();
86 // yield Point { x: self.min.x.clone(), y: self.max.y.clone() };
87 vec![
88 self.min.clone(),
89 Point { x: self.max.x.clone(), y: self.min.y.clone() },
90 self.max.clone(),
91 Point { x: self.min.x.clone(), y: self.max.y.clone() },
92 ]
93 .into_iter()
94 }
95
96 /// Returns four edges counterclockwise in the **↑Y coordinate system**
97 fn edges<'a>(&'a self, _: usize) -> Self::LineIterator<'a> {
98 let mut start = self.min.clone();
99 let mut end = Point { x: self.max.x.clone(), y: self.min.y.clone() };
100 let mut out = Vec::with_capacity(4);
101 {
102 out.push(Line::new(start.clone(), end.clone()));
103 start = end.clone();
104 end = self.max.clone();
105 out.push(Line::new(start.clone(), end.clone()));
106 start = end.clone();
107 end = Point { x: self.min.x.clone(), y: self.max.y.clone() };
108 out.push(Line::new(start.clone(), end.clone()));
109 start = end.clone();
110 end = self.min.clone();
111 out.push(Line::new(start.clone(), end.clone()));
112 };
113 out.into_iter()
114 }
115}
116
117impl<T> Rectangle<T> {
118 /// Get the width of the rectangle
119 ///
120 /// # Examples
121 ///
122 /// ```
123 /// # use shape_core::Rectangle;
124 /// let rect = Rectangle::new(0.0, 0.0, 1.0, 1.0);
125 /// assert_eq!(rect.width(), 1.0);
126 /// ```
127 pub fn width(&self) -> T
128 where
129 T: Clone + Sub<Output = T>,
130 {
131 self.max.x.clone() - self.min.x.clone()
132 }
133
134 /// Get the height of the rectangle
135 ///
136 /// # Examples
137 ///
138 /// ```
139 /// # use shape_core::Rectangle;
140 /// let rect = Rectangle::new(0.0, 0.0, 1.0, 1.0);
141 /// assert_eq!(rect.height(), 1.0);
142 /// ```
143 pub fn height(&self) -> T
144 where
145 T: Clone + Sub<Output = T>,
146 {
147 self.max.y.clone() - self.min.y.clone()
148 }
149 /// Get the origin of the rectangle
150 ///
151 /// # Examples
152 ///
153 /// ```
154 /// # use shape_core::{Point, Rectangle};
155 /// let rect = Rectangle::from_center((0.0, 0.0), 1.0,1.0);
156 /// assert_eq!(rect.origin(), -Point::new(0.5, 0.5));
157 /// ```
158 pub fn origin(&self) -> Point<T>
159 where
160 T: Clone,
161 {
162 self.min.clone()
163 }
164 /// Get the center point of the rectangle
165 ///
166 /// # Examples
167 ///
168 /// ```
169 /// # use shape_core::{Point, Rectangle};
170 /// let rect = Rectangle::new(0.0, 0.0, 1.0, 1.0);
171 /// assert_eq!(rect.center(), Point::new(0.5, 0.5));
172 /// ```
173 pub fn center(&self) -> Point<T>
174 where
175 T: Clone + One + Add<Output = T> + Sub<Output = T> + Div<Output = T>,
176 {
177 Point { x: (self.min.x.clone() + self.max.x.clone()) / two(), y: (self.min.y.clone() + self.max.y.clone()) / two() }
178 }
179 /// Move reference to the inner value
180 pub fn ref_inner(&self) -> Rectangle<&T> {
181 Rectangle { min: self.min.ref_inner(), max: self.max.ref_inner() }
182 }
183 pub fn contains(&self, point: &Point<T>) -> bool
184 where
185 T: Clone + PartialOrd,
186 {
187 point.x >= self.min.x.clone()
188 && point.x <= self.max.x.clone()
189 && point.y >= self.min.y.clone()
190 && point.y <= self.max.y.clone()
191 }
192 /// Check if two rectangle had overlapped
193 pub fn overlaps(&self, other: &Rectangle<T>) -> bool
194 where
195 T: Clone + PartialOrd,
196 {
197 self.min.x.clone() <= other.max.x.clone()
198 && self.max.x.clone() >= other.min.x.clone()
199 && self.min.y.clone() <= other.max.y.clone()
200 && self.max.y.clone() >= other.min.y.clone()
201 }
202 /// Get the area of the rectangle
203 ///
204 /// # Examples
205 ///
206 /// ```
207 /// # use shape_core::{Point, Rectangle};
208 /// let rect = Rectangle::new(0.0, 0.0, 2.0, 2.0);
209 /// assert_eq!(rect.area(), 4.0);
210 /// ```
211 pub fn area(&self) -> T
212 where
213 T: Clone + Mul<Output = T> + Sub<Output = T>,
214 {
215 (self.max.x.clone() - self.min.x.clone()) * (self.max.y.clone() - self.min.y.clone())
216 }
217}