use std::ops::Sub; #[derive(Clone, Copy, PartialEq, Eq)] pub enum Side { Top, Bottom, Left, Right } #[derive(Clone, Copy, PartialEq, Eq)] pub enum Corner { TopLeft, TopRight, BottomRight, BottomLeft } impl Side { pub fn opposite(&self) -> Side { match self { Side::Top => Side::Bottom, Side::Right => Side::Left, Side::Bottom => Side::Top, Side::Left => Side::Right, } } pub fn corners_on_side(&self) -> &[Corner] { match self { Side::Top => &[ Corner::TopLeft, Corner::TopRight ], Side::Right => &[ Corner::TopRight, Corner::BottomRight ], Side::Bottom => &[ Corner::BottomRight, Corner::BottomLeft ], Side::Left => &[ Corner::BottomLeft, Corner::TopLeft ], } } } impl Corner { pub fn first_clockwise_side(&self) -> Side { match self { Corner::TopLeft => Side::Left, Corner::TopRight => Side::Top, Corner::BottomRight => Side::Right, Corner::BottomLeft => Side::Bottom, } } } pub trait Coordinate: Copy + From + Ord + Sub { } impl + Ord + Sub> Coordinate for T { } #[derive(Debug)] pub struct Point { pub x: T, pub y: T, } #[derive(Debug)] pub struct Rectangle { pub left: T, pub top: T, pub width: T, pub height: T, } impl Rectangle { pub fn corner_point(&self, corner: Corner) -> Point { match corner { Corner::TopLeft => Point { x: T::from(0), y: T::from(0) }, Corner::TopRight => Point { x: self.width, y: T::from(0) }, Corner::BottomRight => Point { x: self.width, y: self.height }, Corner::BottomLeft => Point { x: T::from(0), y: self.height }, } } pub fn inset_from_corner_point(&self, corner: Corner, distance: T) -> Point { match corner { Corner::TopLeft => Point { x: distance, y: distance }, Corner::TopRight => Point { x: self.width - distance, y: distance }, Corner::BottomRight => Point { x: self.width - distance, y: self.height - distance }, Corner::BottomLeft => Point { x: distance, y: self.height - distance }, } } pub fn corner_square(&self, corner: Corner, size: T) -> Rectangle { let corner_point = self.corner_point(corner); let inset_point = self.inset_from_corner_point(corner, size); let left = corner_point.x.min(inset_point.x); let top = corner_point.y.min(inset_point.y); let right = corner_point.x.max(inset_point.x); let bottom = corner_point.y.max(inset_point.y); Rectangle { left, top, width: right - left, height: bottom - top, } } }