use crate::{Point, Size};
#[derive(Copy, Clone, Default, Debug, PartialEq)]
pub struct Rectangle {
position: Point,
size: Size,
}
impl Rectangle {
pub fn new(position: impl Into<Point>, size: impl Into<Size>) -> Self {
Rectangle {
position: position.into(),
size: size.into(),
}
}
pub fn x(&self) -> f64 {
self.position.x()
}
pub fn set_x(&mut self, x: impl Into<f64>) {
self.position.set_x(x);
}
pub fn y(&self) -> f64 {
self.position.y()
}
pub fn set_y(&mut self, y: impl Into<f64>) {
self.position.set_y(y);
}
pub fn position(&self) -> Point {
self.position
}
pub fn set_position(&mut self, position: impl Into<Point>) {
self.position = position.into();
}
pub fn width(&self) -> f64 {
self.size.width()
}
pub fn set_width(&mut self, width: impl Into<f64>) {
self.size.set_width(width.into());
}
pub fn height(&self) -> f64 {
self.size.height()
}
pub fn set_height(&mut self, height: impl Into<f64>) {
self.size.set_height(height.into());
}
pub fn size(&self) -> Size {
self.size
}
pub fn set_size(&mut self, width: impl Into<f64>, height: impl Into<f64>) {
self.size.set_width(width.into());
self.size.set_height(height.into());
}
pub fn contains(&self, point: impl Into<Point>) -> bool {
let point: Point = point.into();
point.x() >= self.x()
&& point.x() <= self.x() + self.width()
&& point.y() >= self.y()
&& point.y() <= self.y() + self.height()
}
pub fn contains_rect(&self, rect: &Rectangle) -> bool {
let p1 = rect.position();
let p2 = (p1.x() + rect.width(), p1.y() + rect.height());
self.contains(p1) && self.contains(p2)
}
pub fn intersects(&self, rect: &Rectangle) -> bool {
!(rect.x() > (self.x() + self.width())
|| self.x() > (rect.x() + rect.width())
|| rect.y() > (self.y() + self.height())
|| self.y() > (rect.y() + rect.height()))
}
}
impl From<(Point, Size)> for Rectangle {
fn from(t: (Point, Size)) -> Self {
Rectangle::new(t.0, t.1)
}
}
impl From<(i32, i32, i32, i32)> for Rectangle {
fn from(t: (i32, i32, i32, i32)) -> Self {
Rectangle::new((t.0 as f64, t.1 as f64), (t.2 as f64, t.3 as f64))
}
}
impl From<(f64, f64, f64, f64)> for Rectangle {
fn from(t: (f64, f64, f64, f64)) -> Self {
Rectangle::new((t.0, t.1), (t.2, t.3))
}
}
#[cfg(test)]
mod tests {
use crate::prelude::*;
#[test]
fn test_new() {
let rect = Rectangle::new((5.0, 10.0), (20.0, 30.0));
assert_eq!(rect.x(), 5.0);
assert_eq!(rect.y(), 10.0);
assert_eq!(rect.width(), 20.0);
assert_eq!(rect.height(), 30.0);
}
#[test]
fn test_contains() {
let rect = Rectangle::new((5.0, 10.0), (20.0, 30.0));
let p = Point::new(5.0, 10.0);
assert!(rect.contains(p), "{:?}", p);
let p = Point::new(25.0, 40.0);
assert!(rect.contains(p), "{:?}", p);
let p = Point::new(15.0, 15.0);
assert!(rect.contains(p), "{:?}", p);
let p = Point::new(30.0, 15.0);
assert!(!rect.contains(p), "{:?}", p);
let p = Point::new(15.0, 50.0);
assert!(!rect.contains(p), "{:?}", p);
let p = Point::new(30.0, 40.0);
assert!(!rect.contains(p), "{:?}", p);
}
#[test]
fn test_contains_rect() {
let rect = Rectangle::new((5.0, 10.0), (20.0, 30.0));
let r = Rectangle::new((5.0, 10.0), (20.0, 30.0));
assert!(rect.contains_rect(&r), "{:?}", r);
let r = Rectangle::new((5.0, 20.0), (10.0, 20.0));
assert!(rect.contains_rect(&r), "{:?}", r);
let r = Rectangle::new((5.0, 10.0), (10.0, 20.0));
assert!(rect.contains_rect(&r), "{:?}", r);
let r = Rectangle::new((10.0, 20.0), (5.0, 10.0));
assert!(rect.contains_rect(&r), "{:?}", r);
let r = Rectangle::new((20.0, 25.0), (20.0, 30.0));
assert!(!rect.contains_rect(&r), "{:?}", r);
let r = Rectangle::new((50.0, 100.0), (20.0, 30.0));
assert!(!rect.contains_rect(&r), "{:?}", r);
}
#[test]
fn test_intersects() {
let rect = Rectangle::new((5.0, 10.0), (20.0, 30.0));
let r = Rectangle::new((5.0, 10.0), (20.0, 30.0));
assert!(rect.intersects(&r), "{:?}", r);
let r = Rectangle::new((25.0, 10.0), (20.0, 30.0));
assert!(rect.intersects(&r), "{:?}", r);
let r = Rectangle::new((-15.0, 10.0), (20.0, 30.0));
assert!(rect.intersects(&r), "{:?}", r);
let r = Rectangle::new((5.0, 40.0), (20.0, 30.0));
assert!(rect.intersects(&r), "{:?}", r);
let r = Rectangle::new((5.0, -20.0), (20.0, 30.0));
assert!(rect.intersects(&r), "{:?}", r);
let r = Rectangle::new((30.0, 10.0), (20.0, 30.0));
assert!(!rect.intersects(&r), "{:?}", r);
let r = Rectangle::new((-20.0, 10.0), (20.0, 30.0));
assert!(!rect.intersects(&r), "{:?}", r);
let r = Rectangle::new((5.0, 50.0), (20.0, 30.0));
assert!(!rect.intersects(&r), "{:?}", r);
let r = Rectangle::new((5.0, -30.0), (20.0, 30.0));
assert!(!rect.intersects(&r), "{:?}", r);
}
}