summary refs log tree commit diff
path: root/src/geometry.rs
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@irenes.space>2026-11-12 00:18:39 -0700
committerIrene Knapp <ireneista@irenes.space>2026-11-12 00:18:39 -0700
commit6480f84e8ee9839fb486916d708712daf34a0aff (patch)
treeb53dd2b3eeecad2d52d926f8b2977051551e5bcb /src/geometry.rs
parentcea4c230b40d5ea2851ed3f97f73b2554849dc34 (diff)
rounded corners
fun

that was some nontrivial type magick

Force-Push: yes
Change-Id: I9b2848cc76f3dfab5b87d7e6b2f28bf2a136fca5
Diffstat (limited to 'src/geometry.rs')
-rw-r--r--src/geometry.rs100
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,
+    }
+  }
+}
+