#![deny(missing_docs)]
extern crate float;
use float::Float;
pub trait Rect: Sized {
type Scalar: Float;
fn from_x_y_w_h(Self::Scalar, Self::Scalar, Self::Scalar, Self::Scalar)
-> Self;
#[inline(always)]
fn from_u32(rect: [u32; 4]) -> Self {
use float::FromPrimitive;
Rect::from_x_y_w_h(
FromPrimitive::from_u32(rect[0]),
FromPrimitive::from_u32(rect[1]),
FromPrimitive::from_u32(rect[2]),
FromPrimitive::from_u32(rect[3])
)
}
#[inline(always)]
fn from_i32(rect: [i32; 4]) -> Self {
use float::FromPrimitive;
Rect::from_x_y_w_h(
FromPrimitive::from_i32(rect[0]),
FromPrimitive::from_i32(rect[1]),
FromPrimitive::from_i32(rect[2]),
FromPrimitive::from_i32(rect[3])
)
}
fn x(&self) -> Self::Scalar;
fn y(&self) -> Self::Scalar;
fn w(&self) -> Self::Scalar;
fn h(&self) -> Self::Scalar;
fn set_x(&mut self, val: Self::Scalar);
fn set_y(&mut self, val: Self::Scalar);
fn set_w(&mut self, val: Self::Scalar);
fn set_h(&mut self, val: Self::Scalar);
#[inline(always)]
fn xy(&self) -> (Self::Scalar, Self::Scalar) { (self.x(), self.y()) }
#[inline(always)]
fn wh(&self) -> (Self::Scalar, Self::Scalar) { (self.w(), self.h()) }
#[inline(always)]
fn xw(&self) -> (Self::Scalar, Self::Scalar) { (self.x(), self.w()) }
#[inline(always)]
fn yh(&self) -> (Self::Scalar, Self::Scalar) { (self.y(), self.h()) }
#[inline(always)]
fn x1x2(&self) -> (Self::Scalar, Self::Scalar) { (self.x(), self.x() + self.w()) }
#[inline(always)]
fn y1y2(&self) -> (Self::Scalar, Self::Scalar) { (self.y(), self.y() + self.h()) }
#[inline(always)]
fn p1p2(&self) -> ([Self::Scalar; 2], [Self::Scalar; 2]) {
([self.x(), self.y()], [self.x() + self.w(), self.y() + self.h()])
}
#[inline(always)]
fn xywh(&self) -> (Self::Scalar, Self::Scalar, Self::Scalar, Self::Scalar) {
(self.x(), self.y(), self.w(), self.h())
}
#[inline(always)]
fn center(&self) -> [Self::Scalar; 2] {
use float::FromPrimitive;
let _05: Self::Scalar = FromPrimitive::from_f64(0.5);
[self.x() + _05 * self.h(), self.y() + _05 * self.h()]
}
#[inline(always)]
fn is_empty(&self) -> bool {
use float::Zero;
self.w() * self.h() == Zero::zero()
}
fn margin(&self, val: Self::Scalar) -> Self {
use float::{ FromPrimitive, Zero };
let x: Self::Scalar;
let y: Self::Scalar;
let w: Self::Scalar;
let h: Self::Scalar;
let _2: Self::Scalar = FromPrimitive::from_f64(2.0);
let _05: Self::Scalar = FromPrimitive::from_f64(0.5);
let _0: Self::Scalar = Zero::zero();
if self.w() < _2 * val {
x = self.x() + _05 * self.w();
w = _0;
} else {
x = self.x() + val;
w = self.w() - _2 * val;
}
if self.h() < _2 * val {
y = self.y() + _05 * self.h();
h = _0;
} else {
y = self.y() + val;
h = self.h() - _2 * val;
}
<Self as Rect>::from_x_y_w_h(x, y, w, h)
}
fn split_left(&self, val: Self::Scalar, factor: Self::Scalar)
-> (Self, Self) {
use float::One;
let (x, y, w, h) = self.xywh();
if val > w * factor {
let _1: Self::Scalar = One::one();
(Rect::from_x_y_w_h(x, y, w * factor, h),
Rect::from_x_y_w_h(x + w * factor, y, w * (_1 - factor), h))
} else {
(Rect::from_x_y_w_h(x, y, val, h),
Rect::from_x_y_w_h(x + val, y, w - val, h))
}
}
#[inline(always)]
fn split_right(&self, val: Self::Scalar, factor: Self::Scalar)
-> (Self, Self) {
use float::One;
let (x, y, w, h) = self.xywh();
if val > w * factor {
let _1: Self::Scalar = One::one();
(Rect::from_x_y_w_h(x, y, w * (_1 - factor), h),
Rect::from_x_y_w_h(x + w * (_1 - factor), y, w * factor, h))
} else {
(Rect::from_x_y_w_h(x, y, w - val, h),
Rect::from_x_y_w_h(x + w - val, y, val, h))
}
}
fn split_top(&self, val: Self::Scalar, factor: Self::Scalar)
-> (Self, Self) {
use float::One;
let (x, y, w, h) = self.xywh();
if val > h * factor {
let _1: Self::Scalar = One::one();
(Rect::from_x_y_w_h(x, y, w, h * factor),
Rect::from_x_y_w_h(x, y + h * factor, w, h * (_1 - factor)))
} else {
(Rect::from_x_y_w_h(x, y, w, val),
Rect::from_x_y_w_h(x, y + val, w, h - val))
}
}
#[inline(always)]
fn split_bottom(&self, val: Self::Scalar, factor: Self::Scalar)
-> (Self, Self) {
use float::One;
let (x, y, w, h) = self.xywh();
if val > h * factor {
let _1: Self::Scalar = One::one();
(Rect::from_x_y_w_h(x, y, w, h * (_1 - factor)),
Rect::from_x_y_w_h(x, y + h * (_1 - factor), w, h * factor))
} else {
(Rect::from_x_y_w_h(x, y, w, h - val),
Rect::from_x_y_w_h(x, y + h - val, w, val))
}
}
}
impl Rect for [f64; 4] {
type Scalar = f64;
fn from_x_y_w_h(x: f64, y: f64, w: f64, h: f64) -> [f64; 4] {
[x, y, w, h]
}
fn x(&self) -> f64 { self[0] }
fn y(&self) -> f64 { self[1] }
fn w(&self) -> f64 { self[2] }
fn h(&self) -> f64 { self[3] }
fn set_x(&mut self, val: f64) { self[0] = val }
fn set_y(&mut self, val: f64) { self[1] = val }
fn set_w(&mut self, val: f64) { self[2] = val }
fn set_h(&mut self, val: f64) { self[3] = val }
}
impl Rect for [f32; 4] {
type Scalar = f32;
fn from_x_y_w_h(x: f32, y: f32, w: f32, h: f32) -> [f32; 4] {
[x, y, w, h]
}
fn x(&self) -> f32 { self[0] }
fn y(&self) -> f32 { self[1] }
fn w(&self) -> f32 { self[2] }
fn h(&self) -> f32 { self[3] }
fn set_x(&mut self, val: f32) { self[0] = val }
fn set_y(&mut self, val: f32) { self[1] = val }
fn set_w(&mut self, val: f32) { self[2] = val }
fn set_h(&mut self, val: f32) { self[3] = val }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_empty() {
assert!([0.0, 0.0, 0.0, 0.0].is_empty());
assert!([0.0, 0.0, 1.0, 0.0].is_empty());
assert!([0.0, 0.0, 0.0, 1.0].is_empty());
assert!(![0.0, 0.0, 1.0, 1.0].is_empty());
}
#[test]
fn margin() {
assert_eq!([0.0, 0.0, 0.0, 0.0].margin(2.0), [0.0, 0.0, 0.0, 0.0]);
assert_eq!([0.0, 0.0, 1.0, 1.0].margin(2.0), [0.5, 0.5, 0.0, 0.0]);
assert_eq!([0.0, 0.0, 100.0, 100.0].margin(2.0), [2.0, 2.0, 96.0, 96.0]);
assert_eq!([0.0, 0.0, 100.0, 200.0].margin(2.0), [2.0, 2.0, 96.0, 196.0]);
}
#[test]
fn xywh() {
let rect = [0.0, 1.0, 2.0, 3.0];
assert_eq!(rect.x(), 0.0);
assert_eq!(rect.y(), 1.0);
assert_eq!(rect.w(), 2.0);
assert_eq!(rect.h(), 3.0);
}
#[test]
fn split_left() {
assert_eq!([0.0, 0.0, 0.0, 10.0].split_left(30.0, 0.5),
([0.0, 0.0, 0.0, 10.0], [0.0, 0.0, 0.0, 10.0]));
assert_eq!([0.0, 0.0, 10.0, 10.0].split_left(15.0, 0.5),
([0.0, 0.0, 5.0, 10.0], [5.0, 0.0, 5.0, 10.0]));
assert_eq!([0.0, 0.0, 100.0, 10.0].split_left(30.0, 0.5),
([0.0, 0.0, 30.0, 10.0], [30.0, 0.0, 70.0, 10.0]));
}
#[test]
fn split_top() {
assert_eq!([0.0, 0.0, 10.0, 0.0].split_top(30.0, 0.5),
([0.0, 0.0, 10.0, 0.0], [0.0, 0.0, 10.0, 0.0]));
assert_eq!([0.0, 0.0, 10.0, 10.0].split_top(15.0, 0.5),
([0.0, 0.0, 10.0, 5.0], [0.0, 5.0, 10.0, 5.0]));
assert_eq!([0.0, 0.0, 10.0, 100.0].split_top(30.0, 0.5),
([0.0, 0.0, 10.0, 30.0], [0.0, 30.0, 10.0, 70.0]));
}
}