Files
Zxq5-OS/src/user/lib/coords.rs
T
FantasyPvP d4b7ee243f e
E
2023-10-31 18:40:30 +00:00

281 lines
8.0 KiB
Rust

use alloc::borrow::ToOwned;
use alloc::vec::Vec;
use libm::sqrt;
use crate::println;
#[derive(Clone, Debug, PartialEq)]
pub enum Line {
Vertical(i64),
Horizontal(i64),
}
#[derive(Clone, Debug, PartialEq)]
pub struct Position {
pub x: i64,
pub y: i64,
}
/// a point represented with x and y coordinates.
impl Position {
/// checks if the point is on a given line
pub fn touches_line(&self, line: &Line) -> bool {
match line {
Line::Vertical(y) => self.y as i64 == *y,
Line::Horizontal(x) => self.x as i64 == *x,
}
}
/// checks if two points are equal and returns the x and y equality result for each
pub fn aligns(&self, other: &Position) -> (bool, bool) {
(self.x == other.x, self.y == other.y)
}
/// calculates x + y distance between two points
pub fn get_offset(&self, other: &Position) -> Position {
Position {
x: other.x - self.x,
y: other.y - self.y
}
}
pub fn diagonal_distance(&self, other: &Position) -> i64 {
sqrt((self.x - other.x).pow(2) as f64 + (self.y - other.y).pow(2) as f64) as i64
}
pub fn as_usize(&self) -> (usize, usize) {
(self.x as usize, self.y as usize)
}
pub fn magnitude(&self) -> i64 {
self.x.abs() + self.y.abs()
}
pub fn nearest(&self, points: &Vec<Position>) -> Position {
let mut points = points.clone();
points.sort_by_key(|p| {
let p = self.get_offset(p);
p.x.abs() + p.y.abs()
});
points.first().unwrap().to_owned()
}
pub fn rotated_aroundte(&self, angle: Direction, p: Position) -> Position { // rotates by an angle around a point
// gets coords relative to point to rotate around
let mut p_offset = self.get_offset(&p);
p_offset = match angle { // default angle is posy = 0 degrees and negy = 180
Direction::Degrees0 => Position {
x: p_offset.x,
y: p_offset.y,
},
Direction::Degrees90 => Position {
x: -p_offset.y,
y: p_offset.x,
},
Direction::Degrees180 => Position {
x: -p_offset.x,
y: -p_offset.y,
},
Direction::Degrees270 => Position {
x: p_offset.y,
y: -p_offset.x,
},
Direction::None => panic!("direction should never be none in this application"),
};
return p_offset + p;
}
pub fn rotate(&self, angle: Direction) -> Position { // rotates by an angle around origin
match angle { // default angle is posy = 0 degrees and negy = 180
Direction::Degrees0 => Position {
x: self.x,
y: self.y,
},
Direction::Degrees90 => Position {
x: -self.y,
y: self.x,
},
Direction::Degrees180 => Position {
x: -self.x,
y: -self.y,
},
Direction::Degrees270 => Position {
x: self.y,
y: -self.x,
},
Direction::None => panic!("direction should never be none in this application"),
}
}
pub fn real(self) -> PositionReal {
PositionReal {
x: self.x as f64,
y: self.y as f64,
}
}
}
impl core::ops::Add for Position {
type Output = Position;
fn add(self, other: Position) -> Position {
Position {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
/// can be expressed as degrees relative to north (where north faces towards the top of the screen)
/// none variant used for when the value is missing / no value is decided.
#[derive(Clone, Debug, PartialEq)]
pub enum Direction {
Degrees0,
Degrees180,
Degrees90,
Degrees270,
None,
}
impl Direction {
pub fn rev(&self) -> Direction {
match self {
Direction::Degrees0 => Direction::Degrees180,
Direction::Degrees180 => Direction::Degrees0,
Direction::Degrees90 => Direction::Degrees270,
Direction::Degrees270 => Direction::Degrees90,
Direction::None => Direction::None,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct PositionReal {
pub x: f64,
pub y: f64,
}
/// a point represented with x and y coordinates.
impl PositionReal {
/// checks if the point is on a given line
pub fn touches_line(&self, line: &Line) -> bool {
match line {
Line::Vertical(y) => self.y as i64 == *y,
Line::Horizontal(x) => self.x as i64 == *x,
}
}
/// checks if two points are equal and returns the x and y equality result for each
pub fn aligns(&self, other: &PositionReal) -> (bool, bool) {
(self.x == other.x, self.y == other.y)
}
/// calculates x + y distance between two points
pub fn get_offset(&self, other: &PositionReal) -> PositionReal {
PositionReal {
x: other.x - self.x,
y: other.y - self.y
}
}
pub fn diagonal_distance(&self, other: &PositionReal) -> f64 {
sqrt((self.x - other.x)*(self.x - other.x) + (self.y - other.y)* (self.y - other.y) as f64)
}
pub fn as_usize(&self) -> (usize, usize) {
(self.x as usize, self.y as usize)
}
pub fn magnitude(&self) -> i64 {
let absx = if self.x >= 0.0 { self.x } else { -self.x };
let absy = if self.y >= 0.0 { self.y } else { -self.y };
(absx + absy) as i64
}
pub fn nearest(&self, points: &Vec<PositionReal>) -> PositionReal {
let mut points = points.clone();
points.sort_by_key(|p| {
let p = self.get_offset(p);
let absx = if p.x >= 0.0 { p.x } else { -p.x };
let absy = if p.y >= 0.0 { p.y } else { -p.y };
(absx + absy) as i64
});
points.first().unwrap().to_owned()
}
pub fn rotated_around(&self, angle: Direction, p: PositionReal) -> PositionReal { // rotates by an angle around a point
// gets coords relative to point to rotate around
let mut p_offset = self.get_offset(&p);
p_offset = match angle { // default angle is posy = 0 degrees and negy = 180
Direction::Degrees0 => PositionReal {
x: p_offset.x,
y: p_offset.y,
},
Direction::Degrees90 => PositionReal {
x: -p_offset.y,
y: p_offset.x,
},
Direction::Degrees180 => PositionReal {
x: -p_offset.x,
y: -p_offset.y,
},
Direction::Degrees270 => PositionReal {
x: p_offset.y,
y: -p_offset.x,
},
Direction::None => panic!("direction should never be none in this application"),
};
return p_offset + p;
}
pub fn rotate(&self, angle: Direction) -> PositionReal { // rotates by an angle around origin
match angle { // default angle is posy = 0 degrees and negy = 180
Direction::Degrees0 => PositionReal {
x: self.x,
y: self.y,
},
Direction::Degrees90 => PositionReal {
x: -self.y,
y: self.x,
},
Direction::Degrees180 => PositionReal {
x: -self.x,
y: -self.y,
},
Direction::Degrees270 => PositionReal {
x: self.y,
y: -self.x,
},
Direction::None => panic!("direction should never be none in this application"),
}
}
pub fn integer(self) -> Position {
Position {
x: self.x as i64,
y: self.y as i64,
}
}
}
impl core::ops::Add for PositionReal {
type Output = PositionReal;
fn add(self, other: PositionReal) -> PositionReal {
PositionReal {
x: self.x + other.x,
y: self.y + other.y,
}
}
}