// vector for 0,0 as origin
/**
* @class Vector
* @description Vector class for 0,0 as origin
* @param {number} x
* @param {number} y
*/
export class Vector implements Vector {
public x: number
public y: number
public angle: number
public length: number
constructor(x: number, y: number) {
this.x = x
this.y = y
this.angle = Math.atan2(this.y, this.x)
this.length = Math.sqrt(this.x * this.x + this.y * this.y)
}
/**
* @function add
* @param {Vector} v
* @returns {Vector}
* @description add vector
* @memberof Vector
*/
public add(v: Vector): Vector {
this.x += v.x
this.y += v.y
return this
}
/**
* @function substract
* @param {Vector} v
* @returns {Vector}
* @description substract vector
* @memberof Vector
*/
public subtract(v: Vector): Vector {
this.x -= v.x
this.y -= v.y
return this
}
/**
* @function scale
* @param {number} v
* @returns {Vector}
* @description scale vector
* @memberof Vector
*/
public scale(s: number): Vector {
return new Vector(this.x * s, this.y * s)
}
/**
* @function distanceTo
* @param {Vector} v
* @returns {number}
* @description distance to vector
* @memberof Vector
*/
public distanceTo(v: Vector) {
return Math.sqrt(Math.pow(this.x - v.x, 2) + Math.pow(this.y - v.y, 2))
}
/**
* @function angleTo
* @param {number} v
* @returns {Vector}
* @description angle to vector
* @memberof Vector
*/
public angleTo(v: Vector) {
return Math.atan2(v.y - this.y, v.x - this.x)
}
/**
* @function getlength
* @returns {number}
* @description get length
*/
public getlength(): number {
return this.length
}
/**
* @function getAngle
* @returns {number}
* @description get angle
* @memberof Vector
*/
public getAngle(): number {
return this.angle
}
/**
* @function normalize
* @returns {number}
* @description normalize vector
* @memberof Vector
*/
public normalize(): Vector {
return this.scale(1 / this.length)
}
/**
* @funciton dot
* @param {Vector} v
* @returns {number}
* @description dot product
* @memberof Vector
*/
public dot(v: Vector): number {
return this.x * v.x + this.y * v.y
}
/**
* @function setLength
* @param {number}
* @description set length
* @memberof Vector
*/
public setLength(l: number) {
this.length = l
this.x = Math.cos(this.angle) * l
this.y = Math.sin(this.angle) * l
}
/**
* @function setAngle
* @param {number} a
* @description set angle
* @memberof Vector
*/
public setAngle(a: number) {
this.angle = a
this.x = Math.cos(a) * this.length
this.y = Math.sin(a) * this.length
}
/**
* @function rotate
* @param {number} angle
* @description rotate vector
* @memberof Vector
*/
public rotate(angle: number) {
this.angle += angle
this.x = Math.cos(this.angle) * this.length
this.y = Math.sin(this.angle) * this.length
}
/**
* @function rotateAround
* @param {number} angle
* @param {Vector} center
* @description rotate around vector
* @memberof Vector
*/
public rotateAround(angle: number, center: Vector) {
this.x = center.x + (this.x - center.x) * Math.cos(angle) - (this.y - center.y) * Math.sin(angle),
this.y = center.y + (this.x - center.x) * Math.sin(angle) + (this.y - center.y) * Math.cos(angle)
}
}
/**
* @deprecated
* @class VectorAround
* @description Vector class for any point as origin
* Not Yet Implemented
*/
// vector for another vector as origin
export class VectorAround extends Vector {
public origin: Vector
constructor(x: number, y: number, origin: Vector) {
super(x + origin.x, y + origin.y)
this.origin = origin
}
public override getAngle(): number {
return this.angle - this.origin.angle
}
public override setAngle(a: number): void {
this.angle = a
this.x = Math.cos(a) * this.length + this.origin.x
this.y = Math.sin(a) * this.length + this.origin.y
}
}
/**
* @function addVectors
* @param {Vector[]} vectors
* @returns {Vector}
*/
export function addVectors(...vectors: Vector[]): Vector {
let x = 0
let y = 0
for (let vector of vectors) {
x += vector.x
y += vector.y
}
return new Vector(x, y)
}
/**
* @function subtractVectors
* @param {Vector[]} vectors
* @returns {Vector}
*/
export function subtractVectors(...vectors: Vector[]): Vector {
let x = 0
let y = 0
for (let vector of vectors) {
x -= vector.x
y -= vector.y
}
return new Vector(x, y)
}
/**
* @function angleBetweenVectors
* @param {Vector} vector1
* @param {Vector} vector2
* @param {"degree" | "radian"} type
* @returns {number}
*/
export function angleBetweenVectors(vector1: Vector, vector2: Vector, type: "radian" | "degree" = "radian"): number {
// angle in degrees
if (type === "degree") {
return Math.atan2(vector2.y - vector1.y, vector2.x - vector1.x) * 180 / Math.PI
}
// angle in radians
return Math.atan2(vector2.y - vector1.y, vector2.x - vector1.x)
}
/**
* @function distanceBetweenVectors
* @param {Vector} vector1
* @param {Vector} vector2
* @returns {number}
*/
export function distanceBetweenVectors(vector1: Vector, vector2: Vector): number {
return Math.sqrt(Math.pow(vector2.x - vector1.x, 2) + Math.pow(vector2.y - vector1.y, 2))
}
/**
* @function moveTowardVector
* @param {Vector} vector1
* @param {Vector} vector2
* @param {number} distance
* @returns {Vector}
* @description returns a vector if a vector1 moves to vector2 by distance
*/
export function moveTowardVector(vector1: Vector, vector2: Vector, distance: number): Vector {
let angle = angleBetweenVectors(vector1, vector2)
let x = vector1.x + Math.cos(angle) * distance
let y = vector1.y + Math.sin(angle) * distance
return new Vector(x, y)
}
export function moveVectorByVelocity(vector: Vector, velocity: Vector): Vector {
return vector.add(velocity)
}
/**
* @function getNewVelocityByAccelaration
* @param {Vector} velocity
* @param {Vector} accelation
* @returns {Vector}
* @description returns a new velocity vector if the acceleration is applied to the velocity
*/
export function getNewVelocityByAccelaration(velocity: Vector, accelation: Vector): Vector {
return velocity.add(accelation)
}