common/rust: add Line type

This commit is contained in:
Xiretza 2022-12-14 19:14:13 +01:00
parent 26700274c3
commit 7db15c9cf7

View file

@ -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> {
LinePoints::try_from(self).ok()
}
}
/// An iterator over a line's points. See [`Line::points()`] for details.
pub struct LinePoints {
line: Option<Line>,
}
impl TryFrom<Line> for LinePoints {
type Error = ();
fn try_from(line: Line) -> Result<Self, Self::Error> {
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<Self::Item> {
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)
}
}