split kartesian into multiple modules
Dieser Commit ist enthalten in:
Ursprung
b24a6f52c0
Commit
6236636fc9
6 geänderte Dateien mit 645 neuen und 517 gelöschten Zeilen
|
@ -1,517 +0,0 @@
|
||||||
use log::debug;
|
|
||||||
use num::*;
|
|
||||||
use std::{
|
|
||||||
fmt::{Debug, Display},
|
|
||||||
ops::*,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub type KD = KartesianDirection;
|
|
||||||
|
|
||||||
pub trait MaximumFromMap<T: Integer> {
|
|
||||||
fn maximum<U>(map: &Vec<Vec<U>>) -> Kartesian<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
||||||
pub struct Kartesian<T>
|
|
||||||
where
|
|
||||||
T: Integer,
|
|
||||||
{
|
|
||||||
pub x: T,
|
|
||||||
pub y: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Integer> Add for Kartesian<T> {
|
|
||||||
fn add(self, rhs: Self) -> Self::Output {
|
|
||||||
Kartesian { x: self.x + rhs.x, y: self.y + rhs.y }
|
|
||||||
}
|
|
||||||
|
|
||||||
type Output = Kartesian<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Integer + AddAssign> AddAssign for Kartesian<T> {
|
|
||||||
fn add_assign(&mut self, rhs: Self) {
|
|
||||||
self.x += rhs.x;
|
|
||||||
self.y += rhs.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Integer> Sub for Kartesian<T> {
|
|
||||||
fn sub(self, rhs: Self) -> Self::Output {
|
|
||||||
Kartesian { x: self.x - rhs.x, y: self.y - rhs.y }
|
|
||||||
}
|
|
||||||
|
|
||||||
type Output = Kartesian<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MaximumFromMap<u32> for Kartesian<u32> {
|
|
||||||
fn maximum<U>(map: &Vec<Vec<U>>) -> Kartesian<u32> {
|
|
||||||
Kartesian {
|
|
||||||
x: map.len().to_u32().unwrap(),
|
|
||||||
y: map[0].len().to_u32().unwrap(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MaximumFromMap<u64> for Kartesian<u64> {
|
|
||||||
fn maximum<U>(map: &Vec<Vec<U>>) -> Kartesian<u64> {
|
|
||||||
Kartesian {
|
|
||||||
x: map.len().to_u64().unwrap(),
|
|
||||||
y: map[0].len().to_u64().unwrap(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MaximumFromMap<u128> for Kartesian<u128> {
|
|
||||||
fn maximum<U>(map: &Vec<Vec<U>>) -> Kartesian<u128> {
|
|
||||||
Kartesian {
|
|
||||||
x: map.len().to_u128().unwrap(),
|
|
||||||
y: map[0].len().to_u128().unwrap(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MaximumFromMap<usize> for Kartesian<usize> {
|
|
||||||
fn maximum<U>(map: &Vec<Vec<U>>) -> Kartesian<usize> {
|
|
||||||
Kartesian { x: map.len(), y: map[0].len() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Integer + SubAssign> SubAssign for Kartesian<T> {
|
|
||||||
fn sub_assign(&mut self, rhs: Self) {
|
|
||||||
self.x -= rhs.x;
|
|
||||||
self.y -= rhs.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Integer> Kartesian<T> {
|
|
||||||
pub const fn new(x: T, y: T) -> Self {
|
|
||||||
Self { x: x, y: y }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Kartesian<usize> {
|
|
||||||
pub fn get_value<T: Copy>(self, map: &Vec<Vec<T>>) -> Option<T> {
|
|
||||||
if map.len() > self.x {
|
|
||||||
if map[self.x].len() > self.y {
|
|
||||||
return Some(map[self.x][self.y]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Integer + Eq + Debug + CheckedAdd + CheckedSub + Default + Copy> Kartesian<T> {
|
|
||||||
pub fn checked_add_max(self, rhs: Kartesian<T>, max: Kartesian<T>) -> Option<Kartesian<T>> {
|
|
||||||
let mut new = Kartesian::default();
|
|
||||||
new.x = match self.x.checked_add(&rhs.x) {
|
|
||||||
None => return None,
|
|
||||||
Some(x) => {
|
|
||||||
if x < T::default() || x >= max.x {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
x
|
|
||||||
},
|
|
||||||
};
|
|
||||||
new.y = match self.y.checked_add(&rhs.y) {
|
|
||||||
None => return None,
|
|
||||||
Some(y) => {
|
|
||||||
if y < T::default() || y >= max.y {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
y
|
|
||||||
},
|
|
||||||
};
|
|
||||||
Some(new)
|
|
||||||
}
|
|
||||||
pub fn checked_sub(self, rhs: Kartesian<T>) -> Option<Kartesian<T>> {
|
|
||||||
let mut new = Kartesian::default();
|
|
||||||
new.x = match self.x.checked_sub(&rhs.x) {
|
|
||||||
None => return None,
|
|
||||||
Some(x) => x,
|
|
||||||
};
|
|
||||||
new.y = match self.y.checked_sub(&rhs.y) {
|
|
||||||
None => return None,
|
|
||||||
Some(y) => y,
|
|
||||||
};
|
|
||||||
Some(new)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn diff(self, rhs: Kartesian<T>) -> (Kartesian<T>, KartesianDirection) {
|
|
||||||
let mut relative = Kartesian::<T>::default();
|
|
||||||
let mut dir = KartesianDirection::None;
|
|
||||||
debug!("{:?} <> {:?}", self.x, rhs.x);
|
|
||||||
if self.x < rhs.x {
|
|
||||||
dir = dir.down();
|
|
||||||
relative.x = rhs.x - self.x;
|
|
||||||
} else if self.x > rhs.x {
|
|
||||||
dir = dir.up();
|
|
||||||
relative.x = self.x - rhs.x;
|
|
||||||
}
|
|
||||||
debug!("{:?} <> {:?}", self.x, rhs.x);
|
|
||||||
if self.y < rhs.y {
|
|
||||||
dir = dir.right();
|
|
||||||
relative.y = rhs.y - self.y;
|
|
||||||
} else if self.y > rhs.y {
|
|
||||||
dir = dir.left();
|
|
||||||
relative.y = self.y - rhs.y;
|
|
||||||
}
|
|
||||||
(relative, dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn move_dir(self, vector: Kartesian<T>, dir: KartesianDirection) -> Option<Kartesian<T>> {
|
|
||||||
let mut new = self;
|
|
||||||
match dir {
|
|
||||||
KartesianDirection::TopLeft | KartesianDirection::Top | KartesianDirection::TopRight => {
|
|
||||||
new.x = match new.x.checked_sub(&vector.x) {
|
|
||||||
None => return None,
|
|
||||||
Some(d) => d,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
KartesianDirection::BottomLeft | KartesianDirection::Bottom | KartesianDirection::BottomRight => {
|
|
||||||
new.x = match new.x.checked_add(&vector.x) {
|
|
||||||
None => return None,
|
|
||||||
Some(d) => d,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {},
|
|
||||||
}
|
|
||||||
match dir {
|
|
||||||
KartesianDirection::TopLeft | KartesianDirection::Left | KartesianDirection::BottomLeft => {
|
|
||||||
new.y = match new.y.checked_sub(&vector.y) {
|
|
||||||
None => return None,
|
|
||||||
Some(d) => d,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
KartesianDirection::TopRight | KartesianDirection::Right | KartesianDirection::BottomRight => {
|
|
||||||
new.y = match new.y.checked_add(&vector.y) {
|
|
||||||
None => return None,
|
|
||||||
Some(d) => d,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {},
|
|
||||||
}
|
|
||||||
Some(new)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn move_dir_max(self, vector: Kartesian<T>, dir: KartesianDirection, max: Kartesian<T>) -> Option<Kartesian<T>> {
|
|
||||||
match self.move_dir(vector, dir) {
|
|
||||||
None => None,
|
|
||||||
Some(new) => {
|
|
||||||
if new.x < max.x && new.y < max.y {
|
|
||||||
Some(new)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Integer + Display + Copy> Display for Kartesian<T> {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.write_fmt(format_args!("{}:{}", self.x, self.y))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Integer + Copy> Div<T> for Kartesian<T> {
|
|
||||||
type Output = Kartesian<T>;
|
|
||||||
fn div(self, rhs: T) -> Self::Output {
|
|
||||||
Kartesian {
|
|
||||||
x: self.x.div_ceil(&rhs),
|
|
||||||
y: self.y.div_ceil(&rhs),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub enum KartesianDirection {
|
|
||||||
TopLeft,
|
|
||||||
Top,
|
|
||||||
TopRight,
|
|
||||||
Left,
|
|
||||||
None,
|
|
||||||
Right,
|
|
||||||
BottomLeft,
|
|
||||||
Bottom,
|
|
||||||
BottomRight,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl KartesianDirection {
|
|
||||||
pub fn vector<T: Integer>(self) -> Kartesian<T> {
|
|
||||||
Kartesian {
|
|
||||||
x: match self {
|
|
||||||
Self::Left | Self::None | Self::Right => T::zero(),
|
|
||||||
_ => T::one(),
|
|
||||||
},
|
|
||||||
y: match self {
|
|
||||||
Self::Top | Self::None | Self::Bottom => T::zero(),
|
|
||||||
_ => T::one(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn vector_abs<T: Integer + From<u8>>(self) -> Kartesian<T> {
|
|
||||||
self.vector()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clockwise(self, diagonal: bool) -> Self {
|
|
||||||
match (self, diagonal) {
|
|
||||||
(Self::TopLeft, _) => Self::Top,
|
|
||||||
(Self::Top, true) => Self::TopRight,
|
|
||||||
(Self::Top, false) => Self::Right,
|
|
||||||
(Self::TopRight, _) => Self::Right,
|
|
||||||
(Self::Right, true) => Self::BottomRight,
|
|
||||||
(Self::Right, false) => Self::Bottom,
|
|
||||||
(Self::BottomRight, _) => Self::Bottom,
|
|
||||||
(Self::Bottom, true) => Self::BottomLeft,
|
|
||||||
(Self::Bottom, false) => Self::Left,
|
|
||||||
(Self::BottomLeft, _) => Self::Left,
|
|
||||||
(Self::Left, true) => Self::TopLeft,
|
|
||||||
(Self::Left, false) => Self::Top,
|
|
||||||
(Self::None, _) => Self::None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn anticlockwise(self, diagonal: bool) -> Self {
|
|
||||||
match (self, diagonal) {
|
|
||||||
(Self::TopLeft, _) => Self::Left,
|
|
||||||
(Self::Left, true) => Self::BottomLeft,
|
|
||||||
(Self::Left, false) => Self::Bottom,
|
|
||||||
(Self::BottomLeft, _) => Self::Bottom,
|
|
||||||
(Self::Bottom, true) => Self::BottomRight,
|
|
||||||
(Self::Bottom, false) => Self::Right,
|
|
||||||
(Self::BottomRight, _) => Self::Right,
|
|
||||||
(Self::Right, true) => Self::TopRight,
|
|
||||||
(Self::Right, false) => Self::Top,
|
|
||||||
(Self::TopRight, _) => Self::Top,
|
|
||||||
(Self::Top, true) => Self::TopLeft,
|
|
||||||
(Self::Top, false) => Self::Left,
|
|
||||||
(Self::None, _) => Self::None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn up(self) -> Self {
|
|
||||||
match self {
|
|
||||||
Self::Top | Self::TopLeft | Self::TopRight => self,
|
|
||||||
Self::Left => Self::TopLeft,
|
|
||||||
Self::None => Self::Top,
|
|
||||||
Self::Right => Self::TopRight,
|
|
||||||
Self::BottomLeft => Self::Left,
|
|
||||||
Self::Bottom => Self::None,
|
|
||||||
Self::BottomRight => Self::Right,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn down(self) -> Self {
|
|
||||||
match self {
|
|
||||||
Self::Bottom | Self::BottomLeft | Self::BottomRight => self,
|
|
||||||
Self::TopLeft => Self::Left,
|
|
||||||
Self::Top => Self::None,
|
|
||||||
Self::TopRight => Self::Right,
|
|
||||||
Self::Left => Self::BottomLeft,
|
|
||||||
Self::None => Self::Bottom,
|
|
||||||
Self::Right => Self::BottomRight,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn left(self) -> Self {
|
|
||||||
match self {
|
|
||||||
Self::TopLeft | Self::Left | Self::BottomLeft => self,
|
|
||||||
Self::Top => Self::TopLeft,
|
|
||||||
Self::None => Self::Left,
|
|
||||||
Self::Bottom => Self::BottomLeft,
|
|
||||||
Self::TopRight => Self::Top,
|
|
||||||
Self::Right => Self::None,
|
|
||||||
Self::BottomRight => Self::Bottom,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn right(self) -> Self {
|
|
||||||
match self {
|
|
||||||
Self::TopRight | Self::Right | Self::BottomRight => self,
|
|
||||||
Self::Top => Self::TopRight,
|
|
||||||
Self::None => Self::Right,
|
|
||||||
Self::Bottom => Self::BottomRight,
|
|
||||||
Self::TopLeft => Self::Top,
|
|
||||||
Self::Left => Self::None,
|
|
||||||
Self::BottomLeft => Self::Bottom,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn neg(self) -> Self {
|
|
||||||
match self {
|
|
||||||
Self::TopLeft => Self::BottomRight,
|
|
||||||
Self::Top => Self::Bottom,
|
|
||||||
Self::TopRight => Self::BottomLeft,
|
|
||||||
Self::Left => Self::Right,
|
|
||||||
Self::None => Self::None,
|
|
||||||
Self::Right => Self::Left,
|
|
||||||
Self::BottomLeft => Self::TopRight,
|
|
||||||
Self::Bottom => Self::Top,
|
|
||||||
Self::BottomRight => Self::TopLeft,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter(none: bool, diagonal: bool, straight: bool) -> KartesianIterator {
|
|
||||||
KartesianIterator {
|
|
||||||
i: 0,
|
|
||||||
none,
|
|
||||||
diagonal,
|
|
||||||
straight,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for KartesianDirection {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
let _ = match *self {
|
|
||||||
Self::Top | Self::TopLeft | Self::TopRight => f.write_str("top"),
|
|
||||||
Self::Bottom | Self::BottomLeft | Self::BottomRight => f.write_str("bottom"),
|
|
||||||
Self::None => return f.write_str("none"),
|
|
||||||
_ => std::fmt::Result::Ok(()),
|
|
||||||
};
|
|
||||||
let _ = match *self {
|
|
||||||
Self::TopLeft | Self::Left | Self::BottomLeft => f.write_str("left"),
|
|
||||||
Self::TopRight | Self::Right | Self::BottomRight => f.write_str("right"),
|
|
||||||
_ => std::fmt::Result::Ok(()),
|
|
||||||
};
|
|
||||||
std::fmt::Result::Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct KartesianIterator {
|
|
||||||
i: u8,
|
|
||||||
diagonal: bool,
|
|
||||||
none: bool,
|
|
||||||
straight: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Iterator for KartesianIterator {
|
|
||||||
type Item = KartesianDirection;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
let mut i = self.i;
|
|
||||||
if self.straight {
|
|
||||||
if i < 4 {
|
|
||||||
self.i += 1;
|
|
||||||
}
|
|
||||||
match i {
|
|
||||||
0 => return Some(KartesianDirection::Right),
|
|
||||||
1 => return Some(KartesianDirection::Bottom),
|
|
||||||
2 => return Some(KartesianDirection::Left),
|
|
||||||
3 => return Some(KartesianDirection::Top),
|
|
||||||
_ => i -= 4,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if self.none {
|
|
||||||
if i == 0 {
|
|
||||||
self.i += 1;
|
|
||||||
return Some(KartesianDirection::None);
|
|
||||||
}
|
|
||||||
i -= 1;
|
|
||||||
}
|
|
||||||
if self.diagonal {
|
|
||||||
if i < 4 {
|
|
||||||
self.i += 1;
|
|
||||||
}
|
|
||||||
match i {
|
|
||||||
0 => return Some(KartesianDirection::TopLeft),
|
|
||||||
1 => return Some(KartesianDirection::TopRight),
|
|
||||||
2 => return Some(KartesianDirection::BottomLeft),
|
|
||||||
3 => return Some(KartesianDirection::BottomRight),
|
|
||||||
_ => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_clockwise() {
|
|
||||||
let mut current = KartesianDirection::Top;
|
|
||||||
let clock = [
|
|
||||||
KartesianDirection::Top,
|
|
||||||
KartesianDirection::TopRight,
|
|
||||||
KartesianDirection::Right,
|
|
||||||
KartesianDirection::BottomRight,
|
|
||||||
KartesianDirection::Bottom,
|
|
||||||
KartesianDirection::BottomLeft,
|
|
||||||
KartesianDirection::Left,
|
|
||||||
KartesianDirection::TopLeft,
|
|
||||||
];
|
|
||||||
for hand in clock {
|
|
||||||
assert_eq!(current, hand);
|
|
||||||
current = current.clockwise(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn test_anticlockwise() {
|
|
||||||
let mut current = KartesianDirection::Top;
|
|
||||||
let clock = [
|
|
||||||
KartesianDirection::Top,
|
|
||||||
KartesianDirection::TopLeft,
|
|
||||||
KartesianDirection::Left,
|
|
||||||
KartesianDirection::BottomLeft,
|
|
||||||
KartesianDirection::Bottom,
|
|
||||||
KartesianDirection::BottomRight,
|
|
||||||
KartesianDirection::Right,
|
|
||||||
KartesianDirection::TopRight,
|
|
||||||
];
|
|
||||||
for hand in clock {
|
|
||||||
assert_eq!(current, hand);
|
|
||||||
current = current.anticlockwise(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_kartesian_iter() {
|
|
||||||
let test: Vec<_> = [
|
|
||||||
KartesianDirection::Right,
|
|
||||||
KartesianDirection::Top,
|
|
||||||
KartesianDirection::Left,
|
|
||||||
KartesianDirection::Bottom,
|
|
||||||
KartesianDirection::None,
|
|
||||||
KartesianDirection::TopLeft,
|
|
||||||
KartesianDirection::TopRight,
|
|
||||||
KartesianDirection::BottomLeft,
|
|
||||||
KartesianDirection::BottomRight,
|
|
||||||
]
|
|
||||||
.into();
|
|
||||||
let i: Vec<_> = KartesianDirection::iter(true, true, true).collect();
|
|
||||||
assert_eq!(i, test);
|
|
||||||
let test: Vec<_> = [
|
|
||||||
KartesianDirection::Right,
|
|
||||||
KartesianDirection::Top,
|
|
||||||
KartesianDirection::Left,
|
|
||||||
KartesianDirection::Bottom,
|
|
||||||
KartesianDirection::TopLeft,
|
|
||||||
KartesianDirection::TopRight,
|
|
||||||
KartesianDirection::BottomLeft,
|
|
||||||
KartesianDirection::BottomRight,
|
|
||||||
]
|
|
||||||
.into();
|
|
||||||
let i: Vec<_> = KartesianDirection::iter(false, true, true).collect();
|
|
||||||
assert_eq!(i, test);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_diff_dir() {
|
|
||||||
const START: Kartesian<u8> = Kartesian::new(1, 1);
|
|
||||||
// Top Group
|
|
||||||
assert_eq!(KartesianDirection::TopLeft, START.diff(Kartesian::new(0, 0)).1);
|
|
||||||
assert_eq!(KartesianDirection::Top, START.diff(Kartesian::new(0, 1)).1);
|
|
||||||
assert_eq!(KartesianDirection::TopRight, START.diff(Kartesian::new(0, 2)).1);
|
|
||||||
// Same Line
|
|
||||||
assert_eq!(KartesianDirection::Left, START.diff(Kartesian::new(1, 0)).1);
|
|
||||||
assert_eq!(KartesianDirection::None, START.diff(Kartesian::new(1, 1)).1);
|
|
||||||
assert_eq!(KartesianDirection::Right, START.diff(Kartesian::new(1, 2)).1);
|
|
||||||
// Below/Bottom Line
|
|
||||||
assert_eq!(KartesianDirection::BottomLeft, START.diff(Kartesian::new(2, 0)).1);
|
|
||||||
assert_eq!(KartesianDirection::Bottom, START.diff(Kartesian::new(2, 1)).1);
|
|
||||||
assert_eq!(KartesianDirection::BottomRight, START.diff(Kartesian::new(2, 2)).1);
|
|
||||||
}
|
|
||||||
}
|
|
152
src/coordinate_systems/kartesian/direction.rs
Normale Datei
152
src/coordinate_systems/kartesian/direction.rs
Normale Datei
|
@ -0,0 +1,152 @@
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
use super::{Kartesian, KartesianIterator};
|
||||||
|
use num::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub enum KartesianDirection {
|
||||||
|
TopLeft,
|
||||||
|
Top,
|
||||||
|
TopRight,
|
||||||
|
Left,
|
||||||
|
None,
|
||||||
|
Right,
|
||||||
|
BottomLeft,
|
||||||
|
Bottom,
|
||||||
|
BottomRight,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KartesianDirection {
|
||||||
|
pub fn vector<T: Integer>(self) -> Kartesian<T> {
|
||||||
|
Kartesian {
|
||||||
|
x: match self {
|
||||||
|
Self::Left | Self::None | Self::Right => T::zero(),
|
||||||
|
_ => T::one(),
|
||||||
|
},
|
||||||
|
y: match self {
|
||||||
|
Self::Top | Self::None | Self::Bottom => T::zero(),
|
||||||
|
_ => T::one(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn vector_abs<T: Integer + From<u8>>(self) -> Kartesian<T> {
|
||||||
|
self.vector()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clockwise(self, diagonal: bool) -> Self {
|
||||||
|
match (self, diagonal) {
|
||||||
|
(Self::TopLeft, _) => Self::Top,
|
||||||
|
(Self::Top, true) => Self::TopRight,
|
||||||
|
(Self::Top, false) => Self::Right,
|
||||||
|
(Self::TopRight, _) => Self::Right,
|
||||||
|
(Self::Right, true) => Self::BottomRight,
|
||||||
|
(Self::Right, false) => Self::Bottom,
|
||||||
|
(Self::BottomRight, _) => Self::Bottom,
|
||||||
|
(Self::Bottom, true) => Self::BottomLeft,
|
||||||
|
(Self::Bottom, false) => Self::Left,
|
||||||
|
(Self::BottomLeft, _) => Self::Left,
|
||||||
|
(Self::Left, true) => Self::TopLeft,
|
||||||
|
(Self::Left, false) => Self::Top,
|
||||||
|
(Self::None, _) => Self::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn anticlockwise(self, diagonal: bool) -> Self {
|
||||||
|
match (self, diagonal) {
|
||||||
|
(Self::TopLeft, _) => Self::Left,
|
||||||
|
(Self::Left, true) => Self::BottomLeft,
|
||||||
|
(Self::Left, false) => Self::Bottom,
|
||||||
|
(Self::BottomLeft, _) => Self::Bottom,
|
||||||
|
(Self::Bottom, true) => Self::BottomRight,
|
||||||
|
(Self::Bottom, false) => Self::Right,
|
||||||
|
(Self::BottomRight, _) => Self::Right,
|
||||||
|
(Self::Right, true) => Self::TopRight,
|
||||||
|
(Self::Right, false) => Self::Top,
|
||||||
|
(Self::TopRight, _) => Self::Top,
|
||||||
|
(Self::Top, true) => Self::TopLeft,
|
||||||
|
(Self::Top, false) => Self::Left,
|
||||||
|
(Self::None, _) => Self::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn up(self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::Top | Self::TopLeft | Self::TopRight => self,
|
||||||
|
Self::Left => Self::TopLeft,
|
||||||
|
Self::None => Self::Top,
|
||||||
|
Self::Right => Self::TopRight,
|
||||||
|
Self::BottomLeft => Self::Left,
|
||||||
|
Self::Bottom => Self::None,
|
||||||
|
Self::BottomRight => Self::Right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn down(self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::Bottom | Self::BottomLeft | Self::BottomRight => self,
|
||||||
|
Self::TopLeft => Self::Left,
|
||||||
|
Self::Top => Self::None,
|
||||||
|
Self::TopRight => Self::Right,
|
||||||
|
Self::Left => Self::BottomLeft,
|
||||||
|
Self::None => Self::Bottom,
|
||||||
|
Self::Right => Self::BottomRight,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn left(self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::TopLeft | Self::Left | Self::BottomLeft => self,
|
||||||
|
Self::Top => Self::TopLeft,
|
||||||
|
Self::None => Self::Left,
|
||||||
|
Self::Bottom => Self::BottomLeft,
|
||||||
|
Self::TopRight => Self::Top,
|
||||||
|
Self::Right => Self::None,
|
||||||
|
Self::BottomRight => Self::Bottom,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn right(self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::TopRight | Self::Right | Self::BottomRight => self,
|
||||||
|
Self::Top => Self::TopRight,
|
||||||
|
Self::None => Self::Right,
|
||||||
|
Self::Bottom => Self::BottomRight,
|
||||||
|
Self::TopLeft => Self::Top,
|
||||||
|
Self::Left => Self::None,
|
||||||
|
Self::BottomLeft => Self::Bottom,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn neg(self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::TopLeft => Self::BottomRight,
|
||||||
|
Self::Top => Self::Bottom,
|
||||||
|
Self::TopRight => Self::BottomLeft,
|
||||||
|
Self::Left => Self::Right,
|
||||||
|
Self::None => Self::None,
|
||||||
|
Self::Right => Self::Left,
|
||||||
|
Self::BottomLeft => Self::TopRight,
|
||||||
|
Self::Bottom => Self::Top,
|
||||||
|
Self::BottomRight => Self::TopLeft,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(none: bool, diagonal: bool, straight: bool) -> KartesianIterator {
|
||||||
|
KartesianIterator { i: 0, none, diagonal, straight }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for KartesianDirection {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let _ = match *self {
|
||||||
|
Self::Top | Self::TopLeft | Self::TopRight => f.write_str("top"),
|
||||||
|
Self::Bottom | Self::BottomLeft | Self::BottomRight => f.write_str("bottom"),
|
||||||
|
Self::None => return f.write_str("none"),
|
||||||
|
_ => std::fmt::Result::Ok(()),
|
||||||
|
};
|
||||||
|
let _ = match *self {
|
||||||
|
Self::TopLeft | Self::Left | Self::BottomLeft => f.write_str("left"),
|
||||||
|
Self::TopRight | Self::Right | Self::BottomRight => f.write_str("right"),
|
||||||
|
_ => std::fmt::Result::Ok(()),
|
||||||
|
};
|
||||||
|
std::fmt::Result::Ok(())
|
||||||
|
}
|
||||||
|
}
|
109
src/coordinate_systems/kartesian/map.rs
Normale Datei
109
src/coordinate_systems/kartesian/map.rs
Normale Datei
|
@ -0,0 +1,109 @@
|
||||||
|
use super::Kartesian;
|
||||||
|
|
||||||
|
/// Rust implementation of an Map. The Zeropoint is Topleft
|
||||||
|
/// The Rows in the data are not nessesaryly in the specifed length, should values be missing, then there are functions that returns
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Map<T: Clone+Copy> {
|
||||||
|
maximum: Kartesian<usize>,
|
||||||
|
data: Vec<Vec<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone+Copy> Map<T> {
|
||||||
|
/// creates an empty Map
|
||||||
|
pub fn empty(length: usize, height: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
data: Vec::new(),
|
||||||
|
maximum: Kartesian::new(height, length),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// returns true if coordinates are outside of bounds
|
||||||
|
#[inline]
|
||||||
|
fn outside(&self, coord: Kartesian<usize>) -> bool {
|
||||||
|
coord.x >= self.maximum.x || coord.y >= self.maximum.y
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unsafe Version of the get or get_wrapping functions.
|
||||||
|
/// It does not check against an missing value and panics if its out of bounds.
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn get_unsafe(&self, coord: Kartesian<usize>) ->T{
|
||||||
|
if self.outside(coord) {
|
||||||
|
panic!("Coordinates out of bounds: {} >= {}", coord, self.maximum)
|
||||||
|
}
|
||||||
|
self.data[coord.x][coord.y]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Copy +Copy+ Default> Map<T> {
|
||||||
|
/// Returns an Option Containing the value.
|
||||||
|
/// Returns None if out of bounds or not yet set.
|
||||||
|
pub fn get(&self, coord: Kartesian<usize>) -> Option<T> {
|
||||||
|
if self.outside(coord) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if coord.x >= self.data.len() {
|
||||||
|
Some(T::default())
|
||||||
|
} else if coord.y >= self.data[coord.x].len() {
|
||||||
|
Some(T::default())
|
||||||
|
} else {
|
||||||
|
Some(self.data[coord.x][coord.y])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the value of in the map.
|
||||||
|
#[inline]
|
||||||
|
pub fn wrapping_get(&self, coord: Kartesian<usize>) -> T {
|
||||||
|
let modded = coord % self.maximum;
|
||||||
|
if modded.x >= self.data.len() {
|
||||||
|
T::default()
|
||||||
|
} else if modded.y >= self.data[modded.x].len() {
|
||||||
|
T::default()
|
||||||
|
} else {
|
||||||
|
self.data[modded.x][modded.y]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set(&mut self, coord: Kartesian<usize>, value: T) -> T {
|
||||||
|
if coord.x >= self.maximum.x || coord.y >= self.maximum.y {
|
||||||
|
panic!("Coordinates outside of bounds: {} >= {}", coord, self.maximum)
|
||||||
|
}
|
||||||
|
if self.data.len() < coord.x + 1 {
|
||||||
|
self.data.resize(coord.x + 1, Vec::new());
|
||||||
|
}
|
||||||
|
if self.data[coord.x].len() < coord.y + 1 {
|
||||||
|
self.data[coord.x].resize(coord.y + 1, T::default());
|
||||||
|
}
|
||||||
|
let oldvalue = self.data[coord.x][coord.y];
|
||||||
|
self.data[coord.x][coord.y] = value;
|
||||||
|
oldvalue
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extend_left(&mut self, amount: usize) {
|
||||||
|
for line in self.data.iter_mut() {
|
||||||
|
for _ in 0..amount {
|
||||||
|
line.insert(0, T::default());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.maximum.y += amount;
|
||||||
|
}
|
||||||
|
pub fn extend_right(&mut self, amount: usize) {
|
||||||
|
self.maximum.y += amount;
|
||||||
|
}
|
||||||
|
pub fn extend_up(&mut self, amount: usize) {
|
||||||
|
for _ in 0..amount {
|
||||||
|
self.data.insert(0, Vec::new());
|
||||||
|
}
|
||||||
|
self.maximum.x += amount
|
||||||
|
}
|
||||||
|
pub fn extend_down(&mut self, amount: usize) {
|
||||||
|
self.maximum.x += amount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone+Copy> From<Vec<Vec<T>>> for Map<T> {
|
||||||
|
fn from(value: Vec<Vec<T>>) -> Self {
|
||||||
|
Map {
|
||||||
|
data: value.clone(),
|
||||||
|
maximum: Kartesian::new(value.len(), value.iter().map(|line| line.len()).max().unwrap_or(0)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
src/coordinate_systems/kartesian/maximum.rs
Normale Datei
39
src/coordinate_systems/kartesian/maximum.rs
Normale Datei
|
@ -0,0 +1,39 @@
|
||||||
|
use super::Kartesian;
|
||||||
|
use num::*;
|
||||||
|
|
||||||
|
pub trait MaximumFromMap<T: Integer> {
|
||||||
|
fn maximum<U>(map: &Vec<Vec<U>>) -> Kartesian<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MaximumFromMap<u32> for Kartesian<u32> {
|
||||||
|
fn maximum<U>(map: &Vec<Vec<U>>) -> Kartesian<u32> {
|
||||||
|
Kartesian {
|
||||||
|
x: map.len().to_u32().unwrap(),
|
||||||
|
y: map[0].len().to_u32().unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MaximumFromMap<u64> for Kartesian<u64> {
|
||||||
|
fn maximum<U>(map: &Vec<Vec<U>>) -> Kartesian<u64> {
|
||||||
|
Kartesian {
|
||||||
|
x: map.len().to_u64().unwrap(),
|
||||||
|
y: map[0].len().to_u64().unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MaximumFromMap<u128> for Kartesian<u128> {
|
||||||
|
fn maximum<U>(map: &Vec<Vec<U>>) -> Kartesian<u128> {
|
||||||
|
Kartesian {
|
||||||
|
x: map.len().to_u128().unwrap(),
|
||||||
|
y: map[0].len().to_u128().unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MaximumFromMap<usize> for Kartesian<usize> {
|
||||||
|
fn maximum<U>(map: &Vec<Vec<U>>) -> Kartesian<usize> {
|
||||||
|
Kartesian { x: map.len(), y: map[0].len() }
|
||||||
|
}
|
||||||
|
}
|
258
src/coordinate_systems/kartesian/mod.rs
Normale Datei
258
src/coordinate_systems/kartesian/mod.rs
Normale Datei
|
@ -0,0 +1,258 @@
|
||||||
|
use log::debug;
|
||||||
|
use num::*;
|
||||||
|
use std::{
|
||||||
|
fmt::{Debug, Display},
|
||||||
|
ops::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub mod direction;
|
||||||
|
pub mod map;
|
||||||
|
pub mod maximum;
|
||||||
|
mod test;
|
||||||
|
pub use direction::*;
|
||||||
|
pub use map::*;
|
||||||
|
pub use maximum::*;
|
||||||
|
|
||||||
|
pub type KD = KartesianDirection;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct Kartesian<T>
|
||||||
|
where
|
||||||
|
T: Integer,
|
||||||
|
{
|
||||||
|
pub x: T,
|
||||||
|
pub y: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Integer> Add for Kartesian<T> {
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
Kartesian { x: self.x + rhs.x, y: self.y + rhs.y }
|
||||||
|
}
|
||||||
|
|
||||||
|
type Output = Kartesian<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Integer + AddAssign> AddAssign for Kartesian<T> {
|
||||||
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
|
self.x += rhs.x;
|
||||||
|
self.y += rhs.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Integer> Sub for Kartesian<T> {
|
||||||
|
fn sub(self, rhs: Self) -> Self::Output {
|
||||||
|
Kartesian { x: self.x - rhs.x, y: self.y - rhs.y }
|
||||||
|
}
|
||||||
|
|
||||||
|
type Output = Kartesian<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Integer + SubAssign> SubAssign for Kartesian<T> {
|
||||||
|
fn sub_assign(&mut self, rhs: Self) {
|
||||||
|
self.x -= rhs.x;
|
||||||
|
self.y -= rhs.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Integer> Kartesian<T> {
|
||||||
|
pub const fn new(x: T, y: T) -> Self {
|
||||||
|
Self { x: x, y: y }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Kartesian<usize> {
|
||||||
|
pub fn get_value<T: Copy>(self, map: &Vec<Vec<T>>) -> Option<T> {
|
||||||
|
if map.len() > self.x {
|
||||||
|
if map[self.x].len() > self.y {
|
||||||
|
return Some(map[self.x][self.y]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Integer + Eq + Debug + CheckedAdd + CheckedSub + Default + Copy> Kartesian<T> {
|
||||||
|
pub fn checked_add_max(self, rhs: Kartesian<T>, max: Kartesian<T>) -> Option<Kartesian<T>> {
|
||||||
|
let mut new = Kartesian::default();
|
||||||
|
new.x = match self.x.checked_add(&rhs.x) {
|
||||||
|
None => return None,
|
||||||
|
Some(x) => {
|
||||||
|
if x < T::default() || x >= max.x {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
x
|
||||||
|
},
|
||||||
|
};
|
||||||
|
new.y = match self.y.checked_add(&rhs.y) {
|
||||||
|
None => return None,
|
||||||
|
Some(y) => {
|
||||||
|
if y < T::default() || y >= max.y {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
y
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Some(new)
|
||||||
|
}
|
||||||
|
pub fn checked_sub(self, rhs: Kartesian<T>) -> Option<Kartesian<T>> {
|
||||||
|
let mut new = Kartesian::default();
|
||||||
|
new.x = match self.x.checked_sub(&rhs.x) {
|
||||||
|
None => return None,
|
||||||
|
Some(x) => x,
|
||||||
|
};
|
||||||
|
new.y = match self.y.checked_sub(&rhs.y) {
|
||||||
|
None => return None,
|
||||||
|
Some(y) => y,
|
||||||
|
};
|
||||||
|
Some(new)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn diff(self, rhs: Kartesian<T>) -> (Kartesian<T>, KartesianDirection) {
|
||||||
|
let mut relative = Kartesian::<T>::default();
|
||||||
|
let mut dir = KartesianDirection::None;
|
||||||
|
debug!("{:?} <> {:?}", self.x, rhs.x);
|
||||||
|
if self.x < rhs.x {
|
||||||
|
dir = dir.down();
|
||||||
|
relative.x = rhs.x - self.x;
|
||||||
|
} else if self.x > rhs.x {
|
||||||
|
dir = dir.up();
|
||||||
|
relative.x = self.x - rhs.x;
|
||||||
|
}
|
||||||
|
debug!("{:?} <> {:?}", self.x, rhs.x);
|
||||||
|
if self.y < rhs.y {
|
||||||
|
dir = dir.right();
|
||||||
|
relative.y = rhs.y - self.y;
|
||||||
|
} else if self.y > rhs.y {
|
||||||
|
dir = dir.left();
|
||||||
|
relative.y = self.y - rhs.y;
|
||||||
|
}
|
||||||
|
(relative, dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn move_dir(self, vector: Kartesian<T>, dir: KartesianDirection) -> Option<Kartesian<T>> {
|
||||||
|
let mut new = self;
|
||||||
|
match dir {
|
||||||
|
KartesianDirection::TopLeft | KartesianDirection::Top | KartesianDirection::TopRight => {
|
||||||
|
new.x = match new.x.checked_sub(&vector.x) {
|
||||||
|
None => return None,
|
||||||
|
Some(d) => d,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
KartesianDirection::BottomLeft | KartesianDirection::Bottom | KartesianDirection::BottomRight => {
|
||||||
|
new.x = match new.x.checked_add(&vector.x) {
|
||||||
|
None => return None,
|
||||||
|
Some(d) => d,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
match dir {
|
||||||
|
KartesianDirection::TopLeft | KartesianDirection::Left | KartesianDirection::BottomLeft => {
|
||||||
|
new.y = match new.y.checked_sub(&vector.y) {
|
||||||
|
None => return None,
|
||||||
|
Some(d) => d,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
KartesianDirection::TopRight | KartesianDirection::Right | KartesianDirection::BottomRight => {
|
||||||
|
new.y = match new.y.checked_add(&vector.y) {
|
||||||
|
None => return None,
|
||||||
|
Some(d) => d,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
Some(new)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn move_dir_max(self, vector: Kartesian<T>, dir: KartesianDirection, max: Kartesian<T>) -> Option<Kartesian<T>> {
|
||||||
|
match self.move_dir(vector, dir) {
|
||||||
|
None => None,
|
||||||
|
Some(new) => {
|
||||||
|
if new.x < max.x && new.y < max.y {
|
||||||
|
Some(new)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Integer + Display + Copy> Display for Kartesian<T> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.write_fmt(format_args!("{}:{}", self.x, self.y))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Integer + Copy> Div<T> for Kartesian<T> {
|
||||||
|
type Output = Kartesian<T>;
|
||||||
|
fn div(self, rhs: T) -> Self::Output {
|
||||||
|
Kartesian {
|
||||||
|
x: self.x.div_ceil(&rhs),
|
||||||
|
y: self.y.div_ceil(&rhs),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Integer + Rem> Rem for Kartesian<T> {
|
||||||
|
type Output = Self;
|
||||||
|
fn rem(self, rhs: Self) -> Self {
|
||||||
|
Kartesian { x: self.x % rhs.x, y: self.y % rhs.y }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<T: Integer + RemAssign> RemAssign for Kartesian<T> {
|
||||||
|
fn rem_assign(&mut self, rhs: Self) {
|
||||||
|
self.x %= rhs.x;
|
||||||
|
self.y %= rhs.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct KartesianIterator {
|
||||||
|
i: u8,
|
||||||
|
diagonal: bool,
|
||||||
|
none: bool,
|
||||||
|
straight: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for KartesianIterator {
|
||||||
|
type Item = KartesianDirection;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let mut i = self.i;
|
||||||
|
if self.straight {
|
||||||
|
if i < 4 {
|
||||||
|
self.i += 1;
|
||||||
|
}
|
||||||
|
match i {
|
||||||
|
0 => return Some(KartesianDirection::Right),
|
||||||
|
1 => return Some(KartesianDirection::Bottom),
|
||||||
|
2 => return Some(KartesianDirection::Left),
|
||||||
|
3 => return Some(KartesianDirection::Top),
|
||||||
|
_ => i -= 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.none {
|
||||||
|
if i == 0 {
|
||||||
|
self.i += 1;
|
||||||
|
return Some(KartesianDirection::None);
|
||||||
|
}
|
||||||
|
i -= 1;
|
||||||
|
}
|
||||||
|
if self.diagonal {
|
||||||
|
if i < 4 {
|
||||||
|
self.i += 1;
|
||||||
|
}
|
||||||
|
match i {
|
||||||
|
0 => return Some(KartesianDirection::TopLeft),
|
||||||
|
1 => return Some(KartesianDirection::TopRight),
|
||||||
|
2 => return Some(KartesianDirection::BottomLeft),
|
||||||
|
3 => return Some(KartesianDirection::BottomRight),
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
87
src/coordinate_systems/kartesian/test.rs
Normale Datei
87
src/coordinate_systems/kartesian/test.rs
Normale Datei
|
@ -0,0 +1,87 @@
|
||||||
|
#[cfg(test)]
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_clockwise() {
|
||||||
|
let mut current = KartesianDirection::Top;
|
||||||
|
let clock = [
|
||||||
|
KartesianDirection::Top,
|
||||||
|
KartesianDirection::TopRight,
|
||||||
|
KartesianDirection::Right,
|
||||||
|
KartesianDirection::BottomRight,
|
||||||
|
KartesianDirection::Bottom,
|
||||||
|
KartesianDirection::BottomLeft,
|
||||||
|
KartesianDirection::Left,
|
||||||
|
KartesianDirection::TopLeft,
|
||||||
|
];
|
||||||
|
for hand in clock {
|
||||||
|
assert_eq!(current, hand);
|
||||||
|
current = current.clockwise(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_anticlockwise() {
|
||||||
|
let mut current = KartesianDirection::Top;
|
||||||
|
let clock = [
|
||||||
|
KartesianDirection::Top,
|
||||||
|
KartesianDirection::TopLeft,
|
||||||
|
KartesianDirection::Left,
|
||||||
|
KartesianDirection::BottomLeft,
|
||||||
|
KartesianDirection::Bottom,
|
||||||
|
KartesianDirection::BottomRight,
|
||||||
|
KartesianDirection::Right,
|
||||||
|
KartesianDirection::TopRight,
|
||||||
|
];
|
||||||
|
for hand in clock {
|
||||||
|
assert_eq!(current, hand);
|
||||||
|
current = current.anticlockwise(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_kartesian_iter() {
|
||||||
|
let test: Vec<_> = [
|
||||||
|
KartesianDirection::Right,
|
||||||
|
KartesianDirection::Top,
|
||||||
|
KartesianDirection::Left,
|
||||||
|
KartesianDirection::Bottom,
|
||||||
|
KartesianDirection::None,
|
||||||
|
KartesianDirection::TopLeft,
|
||||||
|
KartesianDirection::TopRight,
|
||||||
|
KartesianDirection::BottomLeft,
|
||||||
|
KartesianDirection::BottomRight,
|
||||||
|
]
|
||||||
|
.into();
|
||||||
|
let i: Vec<_> = KartesianDirection::iter(true, true, true).collect();
|
||||||
|
assert_eq!(i, test);
|
||||||
|
let test: Vec<_> = [
|
||||||
|
KartesianDirection::Right,
|
||||||
|
KartesianDirection::Top,
|
||||||
|
KartesianDirection::Left,
|
||||||
|
KartesianDirection::Bottom,
|
||||||
|
KartesianDirection::TopLeft,
|
||||||
|
KartesianDirection::TopRight,
|
||||||
|
KartesianDirection::BottomLeft,
|
||||||
|
KartesianDirection::BottomRight,
|
||||||
|
]
|
||||||
|
.into();
|
||||||
|
let i: Vec<_> = KartesianDirection::iter(false, true, true).collect();
|
||||||
|
assert_eq!(i, test);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_diff_dir() {
|
||||||
|
const START: Kartesian<u8> = Kartesian::new(1, 1);
|
||||||
|
// Top Group
|
||||||
|
assert_eq!(KartesianDirection::TopLeft, START.diff(Kartesian::new(0, 0)).1);
|
||||||
|
assert_eq!(KartesianDirection::Top, START.diff(Kartesian::new(0, 1)).1);
|
||||||
|
assert_eq!(KartesianDirection::TopRight, START.diff(Kartesian::new(0, 2)).1);
|
||||||
|
// Same Line
|
||||||
|
assert_eq!(KartesianDirection::Left, START.diff(Kartesian::new(1, 0)).1);
|
||||||
|
assert_eq!(KartesianDirection::None, START.diff(Kartesian::new(1, 1)).1);
|
||||||
|
assert_eq!(KartesianDirection::Right, START.diff(Kartesian::new(1, 2)).1);
|
||||||
|
// Below/Bottom Line
|
||||||
|
assert_eq!(KartesianDirection::BottomLeft, START.diff(Kartesian::new(2, 0)).1);
|
||||||
|
assert_eq!(KartesianDirection::Bottom, START.diff(Kartesian::new(2, 1)).1);
|
||||||
|
assert_eq!(KartesianDirection::BottomRight, START.diff(Kartesian::new(2, 2)).1);
|
||||||
|
}
|
Laden …
Tabelle hinzufügen
In neuem Issue referenzieren