diff options
Diffstat (limited to 'src/geometry.rs')
| -rw-r--r-- | src/geometry.rs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/src/geometry.rs b/src/geometry.rs new file mode 100644 index 0000000..3d25b5d --- /dev/null +++ b/src/geometry.rs @@ -0,0 +1,100 @@ +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<u8> + Ord + Sub<Output=Self> { } +impl<T: Copy + From<u8> + Ord + Sub<Output=T>> Coordinate for T { } + + +#[derive(Debug)] +pub struct Point<T: Coordinate> { + pub x: T, + pub y: T, +} + +#[derive(Debug)] +pub struct Rectangle<T: Coordinate> { + pub left: T, + pub top: T, + pub width: T, + pub height: T, +} + +impl<T: Coordinate> Rectangle<T> { + pub fn corner_point(&self, corner: Corner) -> Point<T> { + 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<T> + { + 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<T> { + 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, + } + } +} + |