cubi_vectors 0.2.1

A Simple Vector library
Documentation
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use mint::IntoMint;

use crate::vector2::Vector2;
use crate::vector_base;

vector_base!(Vector3<f32> {x,y,z});

impl Vector3 {
    pub const ZERO: Vector3 = Vector3 {
        x: 0.,
        y: 0.,
        z: 0.,
    };
    pub const IDENTITY: Vector3 = Vector3 {
        x: 1.,
        y: 1.,
        z: 1.,
    };
    pub const RIGHT: Vector3 = Vector3 {
        x: 1.,
        y: 0.,
        z: 0.,
    };
    pub const LEFT: Vector3 = Vector3 {
        x: -1.,
        y: 0.,
        z: 0.,
    };
    pub const UP: Vector3 = Vector3 {
        x: 0.,
        y: 1.,
        z: 0.,
    };
    pub const DOWN: Vector3 = Vector3 {
        x: 0.,
        y: -1.,
        z: 0.,
    };
    pub const FORWARD: Vector3 = Vector3 {
        x: 0.,
        y: 0.,
        z: 1.,
    };
    pub const BACKWARD: Vector3 = Vector3 {
        x: 0.,
        y: 0.,
        z: 1.,
    };

    pub fn from_xyz(x: f32, y: f32, z: f32) -> Vector3 {
        Vector3 { x, y, z }
    }

    pub fn from_value(value: f32) -> Vector3 {
        Vector3 { x: value, y: value, z: value }
    }

    pub fn from_xy(xy: Vector2, z: f32) -> Vector3 {
        Vector3 {
            x: xy.x,
            y: xy.y,
            z
        }
    }

    pub fn from_xz(xz: Vector2, y: f32) -> Vector3 {
        Vector3 {
            x: xz.x,
            y,
            z: xz.y
        }
    }

    pub fn from_yz(yz: Vector2, x: f32) -> Vector3 {
        Vector3 {
            x,
            y: yz.x,
            z: yz.y
        }
    }

    pub fn len(&self) -> f32 {
        self.len_squared().sqrt()
    }

    pub fn len_squared(&self) -> f32 {
        self.x * self.x + self.y * self.y + self.z * self.z
    }
    
    pub fn normalized(&self) -> Option<Vector3> {
        if self.len_squared() == 0.0 {
            return None;
        }
        
        Some(*self / self.len())
    }
    
    pub fn normalized_or_zero(&self) -> Vector3 {
        self.normalized().unwrap_or(Vector3::ZERO)
    }

    pub fn dot(&self, other: Vector3) -> f32 {
        self.x * other.x + self.y * other.y + self.z * other.z
    }

    pub fn angle_between(&self, other: Vector3) -> f32 {
        self.cos_between(other).acos()
    }

    pub fn cos_between(&self, other: Vector3) -> f32 {
        self.dot(other) / self.len() / other.len()
    }

    pub fn sin_between(&self, other: Vector3) -> f32 {
        self.cross(other).len() / self.len() / other.len()
    }

    pub fn projected_onto(&self, other: Vector3) -> Vector3 {
        other * (other.dot(*self) / other.len_squared())
    }

    pub fn projection_of(&self, other: Vector3) -> Vector3 {
        *self * (self.dot(other) / self.len_squared())
    }

    pub fn rejection_from(&self, other: Vector3) -> Vector3 {
        *self - self.projected_onto(other)
    }

    pub fn rejection_of(&self, other: Vector3) -> Vector3 {
        other - other.projected_onto(*self)
    }

    pub fn cross(&self, other: Vector3) -> Vector3 {
        Vector3 {
            x: self.y * other.z - self.z * other.y,
            y: self.z * other.x - self.x * other.z,
            z: self.x * other.y - self.y * other.x,
        }
    }

    pub fn cross_in_direction_of(&self, other: Vector3, direction: Vector3) -> Vector3 {
        let cross = self.cross(other);

        if direction.dot(cross).is_sign_negative() {
            return -cross;
        }

        cross
    }

    pub fn rotated_around_x_by(&self, rotation_radians: f32) -> Vector3 {
        Vector3::from_yz(self.yz().rotated_by(rotation_radians), self.x)
    }

    pub fn rotated_around_y_by(&self, rotation_radians: f32) -> Vector3 {
        Vector3::from_xz(self.xz().rotated_by(rotation_radians), self.y)
    }

    pub fn rotated_around_z_by(&self, rotation_radians: f32) -> Vector3 {
        Vector3::from_xy(self.xy().rotated_by(rotation_radians), self.z)
    }

    pub fn abs(&self) -> Vector3 {
        Vector3 { x: self.x.abs(), y: self.y.abs(), z: self.z.abs() }
    }

    pub fn sign(&self) -> Vector3 {
        Vector3 { x: self.x.signum(), y: self.y.signum(), z: self.z.signum() }
    }

    pub fn element_wise_product(&self, other: Vector3) -> Vector3 {
        Vector3 { x: self.x * other.x, y: self.y * other.y, z: self.z * other.z }
    }

    pub fn with_sign_of(&self, other: Vector3) -> Vector3 {
        Vector3 { x: self.x.abs() * other.x.signum(), y: self.y.abs() * other.y.signum(), z: self.z.abs() * other.z.signum()}
    }

    pub fn is_almost_zero(&self) -> bool {
        self.len_squared() <= f32::EPSILON * f32::EPSILON
    }

    pub fn is_x_inside_interval(&self, min: f32, max: f32) -> bool {
        min <= self.x && self.x <= max
    }

    pub fn is_y_inside_interval(&self, min: f32, max: f32) -> bool {
        min <= self.y && self.y <= max
    }

    pub fn is_z_inside_interval(&self, min: f32, max: f32) -> bool {
        min <= self.z && self.z <= max
    }

    pub fn flipped_x(&self) -> Vector3 {
        Vector3 { x: -self.x, y: self.y, z: self.z }
    }

    pub fn flipped_y(&self) -> Vector3 {
        Vector3 { x: self.x, y: -self.y, z: self.z }
    }

    pub fn flipped_z(&self) -> Vector3 {
        Vector3 { x: self.x, y: self.y, z: -self.z }
    }

    pub fn flipped_xy(&self) -> Vector3 {
        Vector3 { x: -self.x, y: -self.y, z: self.z }
    }

    pub fn flipped_xz(&self) -> Vector3 {
        Vector3 { x: -self.x, y: self.y, z: -self.z }
    }

    pub fn flipped_yz(&self) -> Vector3 {
        Vector3 { x: self.x, y: -self.y, z: -self.z }
    }
    
    pub fn xy(&self) -> Vector2 {
        Vector2 { x: self.x, y: self.y }
    }
    
    pub fn xz(&self) -> Vector2 {
        Vector2 { x: self.x, y: self.z }
    }
    
    pub fn yz(&self) -> Vector2 {
        Vector2 { x: self.y, y: self.z }
    }
    
    pub fn yx(&self) -> Vector2 {
        Vector2 { x: self.y, y: self.x }
    }

    pub fn zx(&self) -> Vector2 {
        Vector2 { x: self.z, y: self.x }
    }

    pub fn zy(&self) -> Vector2 {
        Vector2 { x: self.z, y: self.y }
    }
}

impl Default for Vector3 {
    fn default() -> Vector3 {
        Vector3::ZERO
    }
}

impl ToString for Vector3 {
    fn to_string(&self) -> String {
        format!("({}, {}, {})", self.x, self.y, self.z)
    }
}

impl ToString for &Vector3 {
    fn to_string(&self) -> String {
        format!("({}, {}, {})", self.x, self.y, self.z)
    }
}

impl Into<mint::Vector3<f32>> for Vector3 {
    fn into(self) -> mint::Vector3<f32> {
        mint::Vector3 { x: self.x, y: self.y, z: self.z }
    }
}

impl IntoMint for Vector3 {
    type MintType = mint::Vector3<f32>;
}

impl Into<Vector3> for mint::Vector3<f32> {
    fn into(self) -> Vector3 {
        Vector3 { x: self.x, y: self.y, z: self.z }
    }
}