use std::fmt;
use std::fmt::Display;
use std::ops;
#[derive(Debug, Clone, Copy)]
pub struct Vector2 {
pub x: f64,
pub y: f64
}
impl Default for Vector2 {
fn default() -> Self {
Vector2 { x: 0.0, y: 0.0 }
}
}
impl Display for Vector2 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[x: {}, y: {}]", self.x, self.y)
}
}
impl Vector2 {
pub fn new(x: f64, y: f64) -> Self {
Vector2 { x: x, y: y }
}
pub fn set(&mut self, x: f64, y: f64) {
self.x = x;
self.y = y;
}
pub fn length(&self) -> f64 {
(self.x * self.x + self.y * self.y).sqrt()
}
pub fn length_squared(&self) -> f64 {
self.x * self.x + self.y * self.y
}
pub fn set_length(&mut self, length: f64) {
let old = self.length_squared();
if old != 0.0 || old != length * length {
self.multiply_scalar((length * length / old).sqrt());
}
}
pub fn distance(&self, other: &Vector2) -> f64 {
(((self.x - other.x) * (self.x - other.x)) + ((self.y - other.y) * (self.y - other.y))).sqrt()
}
pub fn distance_squared(&self, other: &Vector2) -> f64 {
((self.x - other.x) * (self.x - other.x)) + ((self.y - other.y) * (self.y - other.y))
}
pub fn normalize(&mut self) {
let length = self.length();
if length != 0.0 {
self.x /= length;
self.y /= length;
}
}
pub fn dot(&self, other: &Vector2) -> f64 {
self.x * other.x + self.y * other.y
}
pub fn cross(&self, other: &Vector2) -> f64 {
self.x * other.y - self.y * other.x
}
pub fn angle(&self) -> f64 {
let mut angle = self.y.atan2(self.x) * crate::math::RAD_TO_DEG;
if angle < 0.0 {
angle += 360.0;
}
angle
}
pub fn angle_rad(&self) -> f64 {
self.y.atan2(self.x)
}
pub fn angle_relative_to(&self, other: &Vector2) -> f64 {
self.cross(other).atan2(self.dot(other)) * crate::math::RAD_TO_DEG
}
pub fn angle_relative_to_rad(&self, other: &Vector2) -> f64 {
self.cross(other).atan2(self.dot(other))
}
pub fn set_angle(&mut self, degrees: f64) {
self.set_angle_rad(degrees * crate::math::DEG_TO_RAD);
}
pub fn set_angle_rad(&mut self, radians: f64) {
self.set(self.length(), 0.0);
self.rotate_rad(radians);
}
pub fn rotate(&mut self, degrees: f64) {
self.rotate_rad(degrees * crate::math::DEG_TO_RAD);
}
pub fn rotate_rad(&mut self, radians: f64) {
let cos = radians.cos();
let sin = radians.sin();
let new_x = self.x * cos - self.y * sin;
let new_y = self.x * sin + self.y * cos;
self.x = new_x;
self.y = new_y;
}
pub fn rotate_around(&mut self, other: &Vector2, degrees: f64) {
self.subtract(other);
self.rotate(degrees);
self.add(other);
}
pub fn rotate_around_rad(&mut self, other: &Vector2, radians: f64) {
self.subtract(other);
self.rotate_rad(radians);
self.add(other);
}
pub fn nor(&mut self) {
let length = self.length();
if length != 0.0 {
self.x /= length;
self.y /= length;
}
}
pub fn lerp(&mut self, target: &Vector2, alpha: f64) {
let inv_progress = 1.0 - alpha;
self.x = (self.x * inv_progress) + (target.x * alpha);
self.y = (self.y * inv_progress) + (target.y * alpha);
}
pub fn set_to_random_direction(&mut self) {
let theta = crate::random::random_double_range(0.0, std::f64::consts::PI * 2.0);
self.set(theta.cos(), theta.sin());
}
pub fn copy(&self) -> Self {
Vector2 { x: self.x, y: self.y }
}
pub fn add(&mut self, other: &Vector2) {
self.x += other.x;
self.y += other.y;
}
pub fn subtract(&mut self, other: &Vector2) {
self.x -= other.x;
self.y -= other.y;
}
pub fn multiply(&mut self, other: &Vector2) {
self.x *= other.x;
self.y *= other.y;
}
pub fn divide(&mut self, other: &Vector2) {
self.x /= other.x;
self.y /= other.y;
}
pub fn add_scalar(&mut self, scalar: f64) {
self.x += scalar;
self.y += scalar;
}
pub fn subtract_scalar(&mut self, scalar: f64) {
self.x -= scalar;
self.y -= scalar;
}
pub fn multiply_scalar(&mut self, scalar: f64) {
self.x *= scalar;
self.y *= scalar;
}
pub fn divide_scalar(&mut self, scalar: f64) {
self.x /= scalar;
self.y /= scalar;
}
}
impl ops::Add for Vector2 {
type Output = Vector2;
fn add(self, other: Vector2) -> Vector2 {
Vector2 { x: self.x + other.x, y: self.y + other.y }
}
}
impl ops::Sub for Vector2 {
type Output = Vector2;
fn sub(self, other: Vector2) -> Vector2 {
Vector2 { x: self.x - other.x, y: self.y - other.y }
}
}
impl ops::Mul for Vector2 {
type Output = Vector2;
fn mul(self, other: Vector2) -> Vector2 {
Vector2 { x: self.x * other.x, y: self.y * other.y }
}
}
impl ops::Div for Vector2 {
type Output = Vector2;
fn div(self, other: Vector2) -> Vector2 {
Vector2 { x: self.x / other.x, y: self.x / other.y }
}
}
impl ops::Add<f64> for Vector2 {
type Output = Vector2;
fn add(self, scalar: f64) -> Vector2 {
Vector2 { x: self.x + scalar, y: self.y + scalar }
}
}
impl ops::Sub<f64> for Vector2 {
type Output = Vector2;
fn sub(self, scalar: f64) -> Vector2 {
Vector2 { x: self.x - scalar, y: self.y - scalar }
}
}
impl ops::Mul<f64> for Vector2 {
type Output = Vector2;
fn mul(self, scalar: f64) -> Vector2 {
Vector2 { x: self.x * scalar, y: self.y * scalar }
}
}
impl ops::Div<f64> for Vector2 {
type Output = Vector2;
fn div(self, scalar: f64) -> Vector2 {
Vector2 { x: self.x / scalar, y: self.y / scalar }
}
}
impl ops::AddAssign for Vector2 {
fn add_assign(&mut self, other: Vector2) {
self.add(&other);
}
}
impl ops::SubAssign for Vector2 {
fn sub_assign(&mut self, other: Vector2) {
self.subtract(&other);
}
}
impl ops::MulAssign for Vector2 {
fn mul_assign(&mut self, other: Vector2) {
self.multiply(&other);
}
}
impl ops::DivAssign for Vector2 {
fn div_assign(&mut self, other: Vector2) {
self.divide(&other);
}
}
impl ops::AddAssign<f64> for Vector2 {
fn add_assign(&mut self, scalar: f64) {
self.add_scalar(scalar);
}
}
impl ops::SubAssign<f64> for Vector2 {
fn sub_assign(&mut self, scalar: f64) {
self.subtract_scalar(scalar);
}
}
impl ops::MulAssign<f64> for Vector2 {
fn mul_assign(&mut self, scalar: f64) {
self.multiply_scalar(scalar);
}
}
impl ops::DivAssign<f64> for Vector2 {
fn div_assign(&mut self, scalar: f64) {
self.divide_scalar(scalar);
}
}
impl ops::Neg for Vector2 {
type Output = Vector2;
fn neg(self) -> Vector2 {
Vector2 { x: -self.x, y: -self.y }
}
}