mod r2d;
use core::fmt::{ self, Debug, Display, Formatter };
use crate::vectorized::Vectorized;
use crate::scalar::{ Scalar, FloatScalar, SignedScalar };
use crate::vector::{ FloatVector, SignedVector, Vector, VectorAbstract };
pub use r2d::{ Side2, Rect2 };
pub trait RectAbstract<T: Scalar + Vectorized<T, V>, V: VectorAbstract<T, V>, R: RectAbstract<T, V, R>>
where Self:
Clone + PartialEq + PartialOrd + Default + Display + Debug
{}
pub trait Rect<T: Scalar + Vectorized<T, V>, V: Vector<T, V, A>, R: Rect<T, V, R, A, S>, A, S>: RectAbstract<T, V, R> {
fn new(position: V, size: V) -> R;
fn zero() -> R {
Self::new(T::zero().dvec(), T::zero().dvec())
}
fn unit() -> R {
Self::unit_at(T::zero().dvec())
}
fn unit_at(position: V) -> R {
Self::new(position, T::one().dvec())
}
fn of_size(size: V) -> R {
Self::new(T::zero().dvec(), size)
}
fn encompass_points(points: &[V]) -> R;
fn encompass_rects(rects: &[R]) -> R {
if rects.is_empty() { return Self::zero();
}
let mut merge: R = rects[0].clone();
for i in 1..rects.len() {
merge = merge.merge(&rects[i]);
}
merge
}
fn identity(&self) -> &R;
fn position(&self) -> V;
fn position_mut(&mut self) -> &mut V;
fn size(&self) -> V;
fn size_mut(&mut self) -> &mut V;
fn set_position(&mut self, position: V);
fn set_size(&mut self, size: V);
fn center(&self) -> V {
self.position() + (self.size() / T::from(2.0).unwrap())
}
fn end(&self) -> V {
self.position() + self.size()
}
fn vertex(&self, idx: usize) -> V;
fn longest_axis(&self) -> A;
fn longest_axis_length(&self) -> T {
self.axis_length(self.longest_axis())
}
fn shortest_axis(&self) -> A;
fn shortest_axis_length(&self) -> T {
self.axis_length(self.shortest_axis())
}
fn axis_length(&self, axis: A) -> T;
fn encompasses(&self, other: &R) -> bool {
self.position() < other.position() && other.end() <= self.end()
}
fn encompasses_point(&self, point: V) -> bool {
self.position() <= point && point < self.end()
}
fn expand_to_include(&self, point: V) -> R;
fn measure(&self) -> T {
self.size().product()
}
fn has_valid_measure(&self) -> bool {
self.size() > T::zero().dvec()
}
fn grow(&self, amount: T) -> R {
Self::new(self.position() - amount, self.size() + (amount * T::from(2).unwrap()))
}
fn grow_by(&self, amount: &R) -> R {
Self::new(self.position() - amount.position(), self.size() + amount.size() + amount.position())
}
fn grow_side(&self, side: S, amount: T) -> R;
fn merge(&self, other: &R) -> R {
let mut encompassing_rect: R = R::zero();
encompassing_rect.set_position(other.position().min(self.position()));
encompassing_rect.set_size(other.end().max(self.end()));
encompassing_rect.set_size(encompassing_rect.size() - encompassing_rect.position());
encompassing_rect
}
fn intersection(&self, other: &R) -> Option<R> {
if !self.intersects(other, false) {
return None;
}
let self_end: V = self.end();
let other_end: V = other.end();
let new_position: V = other.position().max(self.position());
let cross_section: R = R::new(
new_position,
other_end.min(self_end) - new_position
);
Some(cross_section)
}
fn intersects(&self, other: &R, including_borders: bool) -> bool;
}
pub trait SignedRect<T: SignedScalar + Vectorized<T, V>, V: SignedVector<T, V, A, C>, R: SignedRect<T, V, R, A, S, C>, A, S, C: Vectorized<T, V>>: Rect<T, V, R, A, S> {
fn abs(&self) -> R {
let end: V = self.end();
let top_left: V = self.position().min(end);
Self::new(top_left, self.size().abs())
}
}
pub trait FloatRect<T: FloatScalar + Vectorized<T, V>, V: FloatVector<T, V, A, C>, R: FloatRect<T, V, R, A, S, C>, A, S, C: Vectorized<T, V>>: SignedRect<T, V, R, A, S, C> {
fn approx_eq(&self, other: &R) -> bool {
self.position().approx_eq(other.position()) && self.size().approx_eq(other.size())
}
fn is_finite(&self) -> bool {
self.position().is_finite() && self.size().is_finite()
}
fn is_nan(&self) -> bool {
self.position().is_nan() || self.size().is_nan()
}
}