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}