add new Rect_ constructors, add to() method, optimize implementation
MODIFY
src/manual/core/rect.rs
src/manual/core/rect.rs
@@ -3,14 +3,25 @@ use std::{
ops::{Add, AddAssign, Mul, Sub, SubAssign},
};
-use num::Zero;
+use num::{NumCast, ToPrimitive, Zero};
use crate::core::{Point_, RotatedRect, Size_, ValidPointType, ValidSizeType};
valid_types!(ValidRectType, i32, f32, f64);
+#[inline(always)]
+fn partial_min<T: PartialOrd>(a: T, b: T) -> T {
+ if a <= b { a } else { b }
+}
+
+#[inline(always)]
+fn partial_max<T: PartialOrd>(a: T, b: T) -> T {
+ if b >= a { b } else { a }
+}
+
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
+/// [docs.opencv.org](https://docs.opencv.org/master/d2/d44/classcv_1_1Rect__.html)
pub struct Rect_<T: ValidRectType> {
pub x: T,
pub y: T,
@@ -19,51 +30,57 @@ pub struct Rect_<T: ValidRectType> {
}
impl<T: ValidRectType> Rect_<T> {
+ #[inline]
pub fn new(x: T, y: T, width: T, height: T) -> Self {
Self { x, y, width, height }
}
+
+ #[inline]
+ pub fn from_point_size(pt: Point_<T>, sz: Size_<T>) -> Self where T: ValidPointType + ValidSizeType {
+ Self::new(pt.x, pt.y, sz.width, sz.height)
}
-impl<T: ValidRectType + ValidPointType> Rect_<T> {
#[inline]
- pub fn tl(&self) -> Point_<T> {
- Point_::new(self.x, self.y)
+ pub fn from_points(pt1: Point_<T>, pt2: Point_<T>) -> Self where T: ValidPointType + PartialOrd + Sub<Output=T> {
+ let x = partial_min(pt1.x, pt2.x);
+ let y = partial_min(pt1.y, pt2.y);
+ Self::new(x, y, partial_max(pt1.x, pt2.x) - x, partial_max(pt1.y, pt2.y) - y)
}
+
+ #[inline]
+ pub fn tl(&self) -> Point_<T> where T: ValidPointType {
+ Point_::new(self.x, self.y)
}
-impl<T: ValidRectType + ValidPointType + Add<Output=T>> Rect_<T> {
#[inline]
- pub fn br(&self) -> Point_<T> {
+ pub fn br(&self) -> Point_<T> where T: ValidPointType + Add<Output=T> {
Point_::new(self.x + self.width, self.y + self.height)
}
-}
-impl<T: ValidRectType + ValidSizeType> Rect_<T> {
#[inline]
- pub fn size(&self) -> Size_<T> {
+ pub fn size(&self) -> Size_<T> where T: ValidSizeType {
Size_::new(self.width, self.height)
}
-}
-impl<T: ValidRectType + Mul<Output=T>> Rect_<T> {
#[inline]
- pub fn area(&self) -> T {
+ pub fn area(&self) -> T where T: Mul<Output=T> {
self.width * self.height
}
-}
-impl<T: ValidRectType + Zero + PartialOrd> Rect_<T> {
#[inline]
- pub fn empty(&self) -> bool {
+ pub fn empty(&self) -> bool where T: Zero + PartialOrd {
self.width <= T::zero() || self.height <= T::zero()
}
-}
-impl<T: ValidRectType + ValidPointType + Add<Output=T> + PartialOrd> Rect_<T> {
#[inline]
- pub fn contains(&self, pt: Point_<T>) -> bool {
+ pub fn contains(&self, pt: Point_<T>) -> bool where T: ValidPointType + Add<Output=T> + PartialOrd {
self.x <= pt.x && pt.x < self.x + self.width && self.y <= pt.y && pt.y < self.y + self.height
}
+
+ #[inline]
+ pub fn to<D: ValidRectType + NumCast>(&self) -> Option<Rect_<D>> where T: ToPrimitive {
+ Some(Rect_ { x: D::from(self.x)?, y: D::from(self.y)?, width: D::from(self.width)?, height: D::from(self.height)? })
+ }
}
impl<T: ValidRectType + Default> Default for Rect_<T> {
@@ -177,3 +194,21 @@ impl fmt::Debug for RotatedRect {
.finish()
}
}
+
+
+#[test]
+fn test_partial() {
+ assert_eq!(1., partial_min(1., 2.));
+ assert_eq!(1., partial_min(2., 1.));
+ assert_eq!(1., partial_min(1., 1.));
+ assert_eq!(1, partial_min(1, 2));
+ assert_eq!(1, partial_min(2, 1));
+ assert_eq!(1, partial_min(1, 1));
+
+ assert_eq!(2., partial_max(1., 2.));
+ assert_eq!(2., partial_max(2., 1.));
+ assert_eq!(2., partial_max(2., 2.));
+ assert_eq!(2, partial_max(1, 2));
+ assert_eq!(2, partial_max(2, 1));
+ assert_eq!(2, partial_max(2, 2));
+}

MODIFY
tests/rect.rs
tests/rect.rs
-use opencv::core::{self, Point2d, Rect2d, Size2d};
+use opencv::core::{self, Point2d, Point2i, Rect2d, Rect2f, Rect2i, Size2d, Size2i};
#[test]
fn rect_add() {
@@ -66,6 +66,21 @@ fn rect_sub() {
}
}
+#[test]
+fn rect_constructor() {
+ let r = Rect2i::from_point_size(Point2i::new(1, 2), Size2i::new(3,4));
+ assert_eq!(1, r.x);
+ assert_eq!(2, r.y);
+ assert_eq!(3, r.width);
+ assert_eq!(4, r.height);
+
+ let r = Rect2d::from_points(Point2d::new(10., 20.), Point2d::new(20., 10.));
+ assert_eq!(10., r.x);
+ assert_eq!(10., r.y);
+ assert_eq!(10., r.width);
+ assert_eq!(10., r.height);
+}
+
#[test]
fn rect_methods() {
let mut rect = Rect2d::new(10., 20., 100., 200.);
@@ -79,3 +94,12 @@ fn rect_methods() {
rect.width = 0.;
assert!(rect.empty());
}
+
+#[test]
+fn rect_conv() {
+ let rectf = Rect2d::new(1.2, 2.3, 3.4, 4.5);
+ assert_eq!(Rect2i::new(1, 2, 3, 4), rectf.to::<i32>().unwrap());
+ assert_eq!(Rect2f::new(1.2, 2.3, 3.4, 4.5), rectf.to::<f32>().unwrap());
+ let recti = Rect2i::new(1, 2, 3, 4);
+ assert_eq!(Rect2f::new(1., 2., 3., 4.), recti.to::<f32>().unwrap());
+}

add new Rect_ constructors, add to() method, optimize implementation