From 7db15c9cf7081449fc90f183d90f8703548696da Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 14 Dec 2022 19:14:13 +0100 Subject: [PATCH] common/rust: add Line type --- common/rust/src/vec2.rs | 58 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/common/rust/src/vec2.rs b/common/rust/src/vec2.rs index 57fa4db..8b17950 100644 --- a/common/rust/src/vec2.rs +++ b/common/rust/src/vec2.rs @@ -6,8 +6,8 @@ use std::{ #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Vec2 { - x: i32, // increases toward right - y: i32, // increases toward top + pub x: i32, // increases toward right + pub y: i32, // increases toward top } impl Vec2 { @@ -140,3 +140,57 @@ impl FromStr for Direction { } } } + +/// A line from one point to another. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Line { + pub start: Vec2, + pub end: Vec2, +} + +impl Line { + /// Returns an iterator over the line's points represented as [`Vec2`], including the start and + /// end points. + /// + /// Only works for orthogonal lines. + #[must_use] + pub fn points(self) -> Option { + LinePoints::try_from(self).ok() + } +} + +/// An iterator over a line's points. See [`Line::points()`] for details. +pub struct LinePoints { + line: Option, +} + +impl TryFrom for LinePoints { + type Error = (); + + fn try_from(line: Line) -> Result { + if line.start.x == line.end.x || line.start.y == line.end.y { + Ok(Self { line: Some(line) }) + } else { + Err(()) + } + } +} + +impl Iterator for LinePoints { + type Item = Vec2; + + fn next(&mut self) -> Option { + let Some(line) = self.line.as_mut() else { return None }; + + let delta = (line.end - line.start).map(i32::signum); + + let p = line.start; + line.start += delta; + + if delta == Vec2::new(0, 0) { + self.line = None; + } + + Some(p) + } +}