use std::ops::{
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
};
pub type Vec3 = Vector3D;
#[derive(Debug, PartialEq, Clone, Copy, Default)]
pub struct Vector3D {
pub x: f32,
pub y: f32,
pub z: f32,
}
impl Vector3D {
pub fn new(x: f32, y: f32, z: f32) -> Self {
Self { x, y, z }
}
#[inline]
pub fn magnitude(&self) -> f32 {
(self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
}
#[inline]
pub fn normalize(&self) -> Self {
(*self / self.magnitude())
}
}
impl Index<u8> for Vector3D {
type Output = f32;
fn index(&self, index: u8) -> &f32 {
match index {
0 => &self.x,
1 => &self.x,
2 => &self.x,
_ => panic!(
"index out of bounds: the len is 3 but the index is {}",
index
),
}
}
}
#[test]
fn index() {
let v = Vec3::new(10., 10., 10.);
assert_eq!(10., v[0]);
assert_eq!(10., v[1]);
assert_eq!(10., v[2]);
}
impl IndexMut<u8> for Vector3D {
fn index_mut(&mut self, index: u8) -> &mut f32 {
match index {
0 => &mut self.x,
1 => &mut self.x,
2 => &mut self.x,
_ => panic!(
"index out of bounds: the len is 3 but the index is {}",
index
),
}
}
}
#[test]
fn index_mut() {
let mut v = Vec3::new(10., 10., 10.);
assert_eq!(10., v[0]);
assert_eq!(10., v[1]);
assert_eq!(10., v[2]);
v[2] = 3.0;
assert_eq!(3., v[2]);
}
impl MulAssign<f32> for Vector3D {
fn mul_assign(&mut self, s: f32) {
self.x *= s;
self.y *= s;
self.z *= s;
}
}
#[test]
fn mul_assign() {
let mut v = Vec3::new(5., 5., 5.);
v *= 4.0;
assert_eq!(Vec3::new(20., 20., 20.), v);
}
impl DivAssign<f32> for Vector3D {
fn div_assign(&mut self, mut s: f32) {
s = 1.0f32 / s;
self.x *= s;
self.y *= s;
self.z *= s;
}
}
#[test]
fn div_assign() {
let mut v = Vec3::new(20., 20., 20.);
v /= 4.0;
assert_eq!(Vec3::new(5., 5., 5.), v);
}
impl Mul<f32> for Vector3D {
type Output = Self;
fn mul(self, s: f32) -> Self {
Self::new(self.x * s, self.y * s, self.z * s)
}
}
#[test]
fn mul() {
let v = Vec3::new(20., 20., 20.);
let v = v * 4.0;
assert_eq!(Vec3::new(80., 80., 80.), v);
}
impl Div<f32> for Vector3D {
type Output = Self;
fn div(self, mut s: f32) -> Self {
s = 1.0f32 / s;
Self::new(self.x * s, self.y * s, self.z * s)
}
}
#[test]
fn div() {
let mut v = Vec3::new(20., 20., 20.);
v = v / 4.0;
assert_eq!(Vec3::new(5., 5., 5.), v);
}
impl Neg for Vector3D {
type Output = Self;
fn neg(self) -> Self {
Self::new(-self.x, -self.y, -self.z)
}
}
#[test]
fn neg() {
let v = Vec3::new(20., 20., 20.);
assert_eq!(Vec3::new(-20., -20., -20.), -v);
}
impl AddAssign for Vector3D {
fn add_assign(&mut self, v: Self) {
*self = Self {
x: self.x + v.x,
y: self.y + v.y,
z: self.z + v.z,
}
}
}
#[test]
fn add_assign() {
let mut a = Vec3::new(20., 20., 20.);
let b = Vec3::new(20., 20., 20.);
a += b;
assert_eq!(Vec3::new(40., 40., 40.), a);
}
impl SubAssign for Vector3D {
fn sub_assign(&mut self, v: Self) {
*self = Self {
x: self.x - v.x,
y: self.y - v.y,
z: self.z - v.z,
}
}
}
#[test]
fn sub_assign() {
let mut a = Vec3::new(40., 40., 40.);
let b = Vec3::new(20., 20., 20.);
a -= b;
assert_eq!(Vec3::new(20., 20., 20.), a);
}
impl Add for Vector3D {
type Output = Self;
fn add(self, v: Self) -> Self {
Self {
x: self.x + v.x,
y: self.y + v.y,
z: self.z + v.z,
}
}
}
#[test]
fn add() {
let a = Vec3::new(20., 20., 20.);
let b = Vec3::new(20., 20., 20.);
let v = a + b;
assert_eq!(Vec3::new(40., 40., 40.), v);
}
impl Sub for Vector3D {
type Output = Self;
fn sub(self, v: Self) -> Self {
Self {
x: self.x - v.x,
y: self.y - v.y,
z: self.z - v.z,
}
}
}
#[test]
fn sub() {
let a = Vec3::new(40., 40., 40.);
let b = Vec3::new(20., 20., 20.);
let v = a - b;
assert_eq!(Vec3::new(20., 20., 20.), v);
}
impl From<[f32; 3]> for Vector3D {
fn from(n: [f32; 3]) -> Self {
Self {
x: n[0],
y: n[1],
z: n[2],
}
}
}
#[test]
fn from() {
let n = [2., 3., 4.];
let v = Vec3::from(n);
assert_eq!(Vec3::new(2., 3., 4.), v);
}