opencv/manual/core/
rect.rs

1use std::ops::{Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, Mul, Sub, SubAssign};
2
3use num_traits::{NumCast, NumOps, ToPrimitive, Zero};
4
5use crate::core::{Point_, Size_};
6use crate::opencv_type_simple_generic;
7
8#[inline(always)]
9fn partial_min<T: PartialOrd>(a: T, b: T) -> T {
10	if a <= b {
11		a
12	} else {
13		b
14	}
15}
16
17#[inline(always)]
18fn partial_max<T: PartialOrd>(a: T, b: T) -> T {
19	if b >= a {
20		b
21	} else {
22		a
23	}
24}
25
26/// [docs.opencv.org](https://docs.opencv.org/master/d2/d44/classcv_1_1Rect__.html)
27#[repr(C)]
28#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd)]
29pub struct Rect_<T> {
30	pub x: T,
31	pub y: T,
32	pub width: T,
33	pub height: T,
34}
35
36impl<T> Rect_<T> {
37	#[inline]
38	pub const fn new(x: T, y: T, width: T, height: T) -> Self {
39		Self { x, y, width, height }
40	}
41
42	#[inline]
43	pub fn from_point_size(pt: Point_<T>, sz: Size_<T>) -> Self {
44		Self::new(pt.x, pt.y, sz.width, sz.height)
45	}
46
47	#[inline]
48	pub fn from_points(pt1: Point_<T>, pt2: Point_<T>) -> Self
49	where
50		T: PartialOrd + Sub<Output = T> + Copy,
51	{
52		let x = partial_min(pt1.x, pt2.x);
53		let y = partial_min(pt1.y, pt2.y);
54		Self::new(x, y, partial_max(pt1.x, pt2.x) - x, partial_max(pt1.y, pt2.y) - y)
55	}
56
57	#[inline]
58	pub const fn tl(&self) -> Point_<T>
59	where
60		T: Copy,
61	{
62		Point_::new(self.x, self.y)
63	}
64
65	#[inline]
66	pub fn br(&self) -> Point_<T>
67	where
68		T: Add<Output = T> + Copy,
69	{
70		Point_::new(self.x + self.width, self.y + self.height)
71	}
72
73	#[inline]
74	pub const fn size(&self) -> Size_<T>
75	where
76		T: Copy,
77	{
78		Size_::new(self.width, self.height)
79	}
80
81	#[inline]
82	pub fn area(&self) -> T
83	where
84		T: Mul<Output = T> + Copy,
85	{
86		self.width * self.height
87	}
88
89	#[inline]
90	pub fn empty(&self) -> bool
91	where
92		T: PartialOrd + Zero,
93	{
94		self.width <= T::zero() || self.height <= T::zero()
95	}
96
97	#[inline]
98	pub fn contains(&self, pt: Point_<T>) -> bool
99	where
100		T: PartialOrd + Add<Output = T> + Copy,
101	{
102		self.x <= pt.x && pt.x < self.x + self.width && self.y <= pt.y && pt.y < self.y + self.height
103	}
104
105	/// Cast `Rect` to the other coord and size type
106	#[inline]
107	pub fn to<D: NumCast>(&self) -> Option<Rect_<D>>
108	where
109		T: ToPrimitive + Copy,
110	{
111		Some(Rect_ {
112			x: D::from(self.x)?,
113			y: D::from(self.y)?,
114			width: D::from(self.width)?,
115			height: D::from(self.height)?,
116		})
117	}
118}
119
120impl<T> From<(T, T, T, T)> for Rect_<T> {
121	#[inline]
122	fn from(s: (T, T, T, T)) -> Self {
123		Self::new(s.0, s.1, s.2, s.3)
124	}
125}
126
127impl<T> From<(Point_<T>, Size_<T>)> for Rect_<T> {
128	#[inline]
129	fn from(s: (Point_<T>, Size_<T>)) -> Self {
130		Self::from_point_size(s.0, s.1)
131	}
132}
133
134impl<T: PartialOrd + Sub<Output = T> + Copy> From<(Point_<T>, Point_<T>)> for Rect_<T> {
135	#[inline]
136	fn from(s: (Point_<T>, Point_<T>)) -> Self {
137		Self::from_points(s.0, s.1)
138	}
139}
140
141impl<P, R> Add<Point_<P>> for Rect_<R>
142where
143	Self: AddAssign<Point_<P>>,
144{
145	type Output = Self;
146
147	fn add(mut self, rhs: Point_<P>) -> Self::Output {
148		self += rhs;
149		self
150	}
151}
152
153impl<P, R> Sub<Point_<P>> for Rect_<R>
154where
155	Self: SubAssign<Point_<P>>,
156{
157	type Output = Self;
158
159	fn sub(mut self, rhs: Point_<P>) -> Self::Output {
160		self -= rhs;
161		self
162	}
163}
164
165impl<S, R> Add<Size_<S>> for Rect_<R>
166where
167	Self: AddAssign<Size_<S>>,
168{
169	type Output = Self;
170
171	fn add(mut self, rhs: Size_<S>) -> Self::Output {
172		self += rhs;
173		self
174	}
175}
176
177impl<S, R> Sub<Size_<S>> for Rect_<R>
178where
179	Self: SubAssign<Size_<S>>,
180{
181	type Output = Self;
182
183	fn sub(mut self, rhs: Size_<S>) -> Self::Output {
184		self -= rhs;
185		self
186	}
187}
188
189impl<T> BitOr for Rect_<T>
190where
191	Rect_<T>: BitOrAssign,
192{
193	type Output = Rect_<T>;
194
195	fn bitor(mut self, rhs: Self) -> Self::Output {
196		self |= rhs;
197		self
198	}
199}
200
201impl<T> BitAnd for Rect_<T>
202where
203	Rect_<T>: BitAndAssign,
204{
205	type Output = Rect_<T>;
206
207	fn bitand(mut self, rhs: Self) -> Self::Output {
208		self &= rhs;
209		self
210	}
211}
212
213impl<P, R: AddAssign<P>> AddAssign<Point_<P>> for Rect_<R> {
214	fn add_assign(&mut self, rhs: Point_<P>) {
215		self.x += rhs.x;
216		self.y += rhs.y;
217	}
218}
219
220impl<P, R: SubAssign<P>> SubAssign<Point_<P>> for Rect_<R> {
221	fn sub_assign(&mut self, rhs: Point_<P>) {
222		self.x -= rhs.x;
223		self.y -= rhs.y;
224	}
225}
226
227impl<S, R: AddAssign<S>> AddAssign<Size_<S>> for Rect_<R> {
228	fn add_assign(&mut self, rhs: Size_<S>) {
229		self.width += rhs.width;
230		self.height += rhs.height;
231	}
232}
233
234impl<S, R: SubAssign<S>> SubAssign<Size_<S>> for Rect_<R> {
235	fn sub_assign(&mut self, rhs: Size_<S>) {
236		self.width -= rhs.width;
237		self.height -= rhs.height;
238	}
239}
240
241impl<T: PartialOrd + NumOps + Zero + Copy> BitOrAssign for Rect_<T> {
242	fn bitor_assign(&mut self, rhs: Self) {
243		if self.empty() {
244			*self = rhs;
245		} else if !rhs.empty() {
246			let x1 = partial_min(self.x, rhs.x);
247			let y1 = partial_min(self.y, rhs.y);
248			self.width = partial_max(self.x + self.width, rhs.x + rhs.width) - x1;
249			self.height = partial_max(self.y + self.height, rhs.y + rhs.height) - y1;
250			self.x = x1;
251			self.y = y1;
252		}
253	}
254}
255
256impl<T: PartialOrd + NumOps + Zero + Copy> BitAndAssign for Rect_<T>
257where
258	Self: Default,
259{
260	fn bitand_assign(&mut self, rhs: Self) {
261		let x1 = partial_max(self.x, rhs.x);
262		let y1 = partial_max(self.y, rhs.y);
263		self.width = partial_min(self.x + self.width, rhs.x + rhs.width) - x1;
264		self.height = partial_min(self.y + self.height, rhs.y + rhs.height) - y1;
265		self.x = x1;
266		self.y = y1;
267		if self.empty() {
268			*self = Self::default();
269		}
270	}
271}
272
273#[test]
274fn test_partial() {
275	assert_eq!(1., partial_min(1., 2.));
276	assert_eq!(1., partial_min(2., 1.));
277	assert_eq!(1., partial_min(1., 1.));
278	assert_eq!(1, partial_min(1, 2));
279	assert_eq!(1, partial_min(2, 1));
280	assert_eq!(1, partial_min(1, 1));
281
282	assert_eq!(2., partial_max(1., 2.));
283	assert_eq!(2., partial_max(2., 1.));
284	assert_eq!(2., partial_max(2., 2.));
285	assert_eq!(2, partial_max(1, 2));
286	assert_eq!(2, partial_max(2, 1));
287	assert_eq!(2, partial_max(2, 2));
288}
289
290opencv_type_simple_generic! { Rect_<Copy> }