use std::iter::Sum;
use std::ops::{AddAssign, Div, Sub};
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Point {
pub x: f32,
pub y: f32,
}
impl Point {
pub fn new(x: f32, y: f32) -> Self {
Self { x, y }
}
pub fn to_array(&self) -> [f32; 2] {
[self.x, self.y]
}
pub fn add(&mut self, other: &Point) {
self.x += other.x;
self.y += other.y;
}
pub fn to_perpendicular_left(&self) -> Self {
Self::new(self.y, -self.x)
}
pub fn to_perpendicular_right(&self) -> Self {
Self::new(-self.y, self.x)
}
pub fn multiply_scalar(&mut self, scalar: f32) {
self.x *= scalar;
self.y *= scalar;
}
pub fn normalize(&mut self) {
let length = self.length();
if length != 0.0 {
self.x /= length;
self.y /= length;
}
}
pub fn length(&self) -> f32 {
(self.x.powi(2) + self.y.powi(2)).sqrt()
}
pub fn distance_to(&self, other: &Self) -> f32 {
let distance = *other - *self;
distance.length()
}
pub fn rotation(&self) -> f32 {
self.y.atan2(self.x)
}
pub fn clamp(&mut self, max: f32, min: f32) {
if self.x < min {
self.x = min;
} else if self.x > max {
self.x = max;
}
if self.y < min {
self.y = min;
} else if self.y > max {
self.y = max;
}
}
}
impl Default for Point {
fn default() -> Self {
Self { x: 0.0, y: 0.0 }
}
}
impl AddAssign for Point {
fn add_assign(&mut self, rhs: Self) {
self.x += rhs.x;
self.y += rhs.y;
}
}
impl Sub for Point {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
Self {
x: self.x - rhs.x,
y: self.y - rhs.y,
}
}
}
impl Div<usize> for Point {
type Output = Self;
fn div(self, rhs: usize) -> Self::Output {
Self {
x: self.x / rhs as f32,
y: self.y / rhs as f32,
}
}
}
impl Sum<Point> for Point {
fn sum<I: Iterator<Item = Point>>(points: I) -> Self {
points.fold(Self::new(0.0, 0.0), |mut summed_point, point| {
summed_point.add(&point);
summed_point
})
}
}