From 6480f84e8ee9839fb486916d708712daf34a0aff Mon Sep 17 00:00:00 2001 From: Irene Knapp Date: Thu, 12 Nov 2026 00:18:39 -0700 Subject: rounded corners fun that was some nontrivial type magick Force-Push: yes Change-Id: I9b2848cc76f3dfab5b87d7e6b2f28bf2a136fca5 --- src/geometry.rs | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 src/geometry.rs (limited to 'src/geometry.rs') 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 + 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, + } + } +} + -- cgit 1.4.1