use core::{fmt, ops};
use vexide::core::float::Float;
#[derive(Clone, PartialEq, Debug, Copy, Default)]
pub struct Vec2 {
pub x: f64,
pub y: f64,
}
impl Vec2 {
pub const fn new(x: f64, y: f64) -> Self {
Self { x, y }
}
pub fn x(&self) -> f64 {
self.x
}
pub fn y(&self) -> f64 {
self.y
}
pub fn from_polar(r: f64, theta: f64) -> Self {
let (sin, cos) = theta.sin_cos();
Vec2 {
x: r * cos,
y: r * sin,
}
}
pub fn angle(&self) -> f64 {
self.y.atan2(self.x)
}
pub fn length(&self) -> f64 {
self.x.hypot(self.y)
}
pub fn distance(&self, other: Vec2) -> f64 {
(*self - other).length()
}
pub fn lerp(self, other: Vec2, t: f64) -> Vec2 {
self + ((other - self) * t)
}
pub fn dot(&self, other: Vec2) -> f64 {
self.x * other.x + self.y * other.y
}
pub fn cross(&self, other: Vec2) -> f64 {
self.x * other.y - self.y * other.x
}
pub fn unit(&self) -> Self {
*self / self.length()
}
pub fn project(&self, onto: Vec2) -> Self {
onto * (self.dot(onto) / onto.length().powi(2))
}
pub fn rotate(&self, angle: f64) -> Self {
let (sin, cos) = angle.sin_cos();
Self {
x: self.x * cos - self.y * sin,
y: self.x * sin + self.y * cos,
}
}
}
impl From<(f64, f64)> for Vec2 {
fn from(tuple: (f64, f64)) -> Self {
Self {
x: tuple.0,
y: tuple.1,
}
}
}
impl fmt::Display for Vec2 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
impl ops::Add for Vec2 {
type Output = Self;
fn add(self, other: Vec2) -> Self {
Self {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
impl ops::Add<f64> for Vec2 {
type Output = Self;
fn add(self, scalar: f64) -> Self {
Self {
x: self.x + scalar,
y: self.y + scalar,
}
}
}
impl ops::Sub for Vec2 {
type Output = Self;
fn sub(self, other: Vec2) -> Self {
Self {
x: self.x - other.x,
y: self.y - other.y,
}
}
}
impl ops::Sub<f64> for Vec2 {
type Output = Self;
fn sub(self, scalar: f64) -> Self {
Self {
x: self.x - scalar,
y: self.y - scalar,
}
}
}
impl ops::Mul<f64> for Vec2 {
type Output = Self;
fn mul(self, scalar: f64) -> Self {
Self {
x: self.x * scalar,
y: self.y * scalar,
}
}
}
impl ops::Div<f64> for Vec2 {
type Output = Self;
fn div(self, scalar: f64) -> Self {
Self {
x: self.x / scalar,
y: self.y / scalar,
}
}
}
impl ops::Neg for Vec2 {
type Output = Self;
fn neg(self) -> Self {
Self {
x: -self.x,
y: -self.y,
}
}
}
impl ops::AddAssign for Vec2 {
fn add_assign(&mut self, other: Vec2) {
self.x += other.x;
self.y += other.y;
}
}
impl ops::AddAssign<f64> for Vec2 {
fn add_assign(&mut self, scalar: f64) {
self.x += scalar;
self.y += scalar;
}
}
impl ops::SubAssign for Vec2 {
fn sub_assign(&mut self, other: Vec2) {
self.x -= other.x;
self.y -= other.y;
}
}
impl ops::SubAssign<f64> for Vec2 {
fn sub_assign(&mut self, scalar: f64) {
self.x -= scalar;
self.y -= scalar;
}
}
impl ops::MulAssign<f64> for Vec2 {
fn mul_assign(&mut self, scalar: f64) {
self.x *= scalar;
self.y *= scalar;
}
}
impl ops::DivAssign<f64> for Vec2 {
fn div_assign(&mut self, scalar: f64) {
self.x /= scalar;
self.y /= scalar;
}
}