import { lerp } from "./util.js"
/**
*
* @returns new Vector with Random x,y, and z normalized between 0-1
*/
export function randomUnitVector() {
for (; ;) {
let x = Math.random() * 2 - 1
let y = Math.random() * 2 - 1
let z = Math.random() * 2 - 1
if (x * x + y * y + z * z > 1) {
continue
}
return new Vector(x, y, z).normalize()
}
}
export function min(a, b) {
return Math.min(a, b)
}
export function max(a, b) {
return Math.max(a, b)
}
/**
* Takes 3 params for the positions of the vector , default values zero.
* All operations are NOT done in place, they return new vectors.
* @param {float} x
* @param {float} y
* @param {float} z
*/
export class Vector {
constructor(x = 0, y = 0, z = 0) {
this.x = x
this.y = y
this.z = z
}
lerp(lerpTo,factor){
let lerpFrom = this
return new Vector(lerp(this.x,lerpTo.x,factor),lerp(this.y,lerpTo.y,factor),lerp(this.z,lerpTo.z,factor))
}
/**
*
* @returns the length of the vector
*/
length() {
let a = this
return Math.sqrt(a.x * a.x + a.y * a.y + a.z * a.z)
}
/**
*
* @param {Vector} b is the point to check distance to
* @returns distance as float
*/
distance(b) {
let a = this
a = a.sub(b)
return a.length()
}
/**
*
* @returns {Number}The length of the curren vector
*/
lengthSquared() {
let a = this
return a.x * a.x + a.y * a.y + a.z * a.z
}
/**
*
* @param {Vector} b
* @returns {Number}
*/
distanceSquared(b) {
return this.sub(b).lengthSquared()
}
/**
* dot product @see {@link https://en.wikipedia.org/wiki/Dot_product}
* @param {Vector} b
* @returns {Number}
*/
dot(b) {
let a = this
return (a.x * b.x) + (a.y * b.y) + (a.z * b.z)
}
/**
*
* @param {Vector} b
* @returns {Vector}
*/
cross(b) {
let a = this
let x = a.y * b.z - a.z * b.y
let y = a.z * b.x - a.x * b.z
let z = a.x * b.y - a.y * b.x
return new Vector(x, y, z)
}
/**
*
* @returns {Vector} Vector between 0 and 1
*/
normalize() {
let a = this
let d = a.length()
return new Vector(a.x / d, a.y / d, a.z / d)
}
/**
*
* @param {Vector} b
* @returns {Vector}
*/
add(b) {
let a = this
return new Vector(a.x + b.x, a.y + b.y, a.z + b.z)
}
/**
*
* @param {Vector} b
* @returns {Vector}
*/
sub(b) {
let a = this
return new Vector(a.x - b.x, a.y - b.y, a.z - b.z)
}
/**
*
* @param {Vector} b
* @returns {Vector}
*/
mult(b) {
let a = this
return new Vector(a.x * b.x, a.y * b.y, a.z * b.z)
}
/**
*
* @param {Vector} b
* @returns {Vector}
*/
div(b) {
let a = this
return new Vector(a.x / b.x, a.y / b.y, a.z / b.z)
}
/**
*
* @param {Float} b
* @returns {Vector}
*/
addScalar(b) {
let a = this
return new Vector(a.x + b, a.y + b, a.z + b)
}
/**
*
* @param {Float} b
* @returns {Vector}
*/
subScalar(b) {
let a = this
return new Vector(a.x - b, a.y - b, a.z - b)
}
/**
*
* @param {Float} b
* @returns {Vector}
*/
mulScalar(b) {
let a = this
return new Vector(a.x * b, a.y * b, a.z * b)
}
/**
*
* @param {Float} b
* @returns {Vector}
*/
divScalar(b) {
let a = this
return new Vector(a.x / b, a.y / b, a.z / b)
}
min(b) {
let a = this
return new Vector(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z))
}
max(b) {
let a = this
return new Vector(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z))
}
minAxis() {
let a = this
let x = abs(a.x)
let y = abs(a.y)
let z = abs(a.z)
switch (true) {
case (x <= y && x <= z):
return new Vector(1, 0, 0)
case (y <= x && y <= z):
return new Vector(0, 1, 0)
default:
return new Vector(0, 0, 1)
}
}
/**
*
* @returns whatever vector is lowest
*/
minComponent() {
let a = this
return min(min(a.x, a.y), a.z)
}
/**
*
* @param {Vector} v
* @param {Number} w
* @returns {Vector}
*/
segmentDistance(v, w) {
let p = this
let l2 = v.distanceSquared(w)
if (l2 == 0) {
return p.distance(v)
}
let t = p.sub(v).dot(w.sub(v)) / l2
if (t < 0) {
return p.distance(v)
}
if (t > 1) {
return p.distance(w)
}
return v.add(w.sub(v).mulScalar(t)).distance(p)
}
}