orep-js/sunpy/core/vector.js

116 lines
3.4 KiB
JavaScript
Raw Normal View History

2020-04-21 00:03:26 +02:00
const DIM_NAMES = ["xr", "yg", "zb", "wa"];
const ARRAY_TYPES = [
Int8Array, Int16Array, Int32Array,
Uint8Array, Uint16Array, Uint32Array,
Float32Array, Float64Array,
BigInt64Array, BigUint64Array // Note: These requires values to be of type BigInt
];
export class Vector {
constructor(...values) {
this.type = Float32Array;
for (const value of values) {
if (ARRAY_TYPES.includes(value)) {
this.type = value;
break;
}
}
this.values = new this.type(values.filter(v => !ARRAY_TYPES.includes(v)));
const defineMacro = (index, key) => {
Object.defineProperty(this, key, {
get() { return this.values[index] },
set(value) { this.values[index] = value }
});
};
for (const i in this.values) {
defineMacro(i, i);
if (i >= DIM_NAMES.length)
continue;
for (const names of DIM_NAMES[i]) {
for (const char of names) {
defineMacro(i, char);
}
}
}
}
clone() {
return new Vector(this.type, ...this.values);
}
static _requireSameVector(vecA, vecB) {
if (!(vecA instanceof Vector))
throw new TypeError("vecA has to be instance of `Vector`");
if (!(vecB instanceof Vector))
throw new TypeError("vecB has to be instance of `Vector`");
if (vecA.values.length !== vecB.values.length)
throw new TypeError("Vectors are of different lengths");
if (vecA.type !== vecB.type)
console.warn("Vectors are not of same array type.. be careful!");
}
_modifyComponents(vec, func) {
if (vec instanceof Vector) {
Vector._requireSameVector(this, vec);
for (const i in vec.values) {
this[i] = func(this[i], vec[i]);
}
return this;
}
for (const i in this.values) {
this[i] = func(this[i], vec); // vec is number here
}
return this;
}
// Basic operations
add = (vec) => this._modifyComponents(vec, (a, b) => a + b);
subtract = (vec) => this._modifyComponents(vec, (a, b) => a - b);
multiply = (vec) => this._modifyComponents(vec, (a, b) => a * b);
divide = (vec) => this._modifyComponents(vec, (a, b) => a / b);
// Basic algebra
length() {
return Math.sqrt( this.values.map(v => v * v).reduce((a, b) => a + b, 0) );
}
static normalize(vec) {
return vec.clone().divide(vec.length());
}
static distance(vecA, vecB) {
Vector._requireSameVector(vecA, vecB);
return Math.sqrt( vecA.values.map((v, i) => v - vecB[i]).map(v => v * v).reduce((a, b) => a + b, 0) );
}
static dot(vecA, vecB) {
Vector._requireSameVector(vecA, vecB);
return vecA.values.map((v, i) => v * vecB[i]).reduce((a, b) => a + b, 0);
}
static cross(vecA, vecB) {
Vector._requireSameVector(vecA, vecB);
if (vecA.values.length !== 3)
throw TypeError(`Vector3 required, got Vector${vecA.values.length}`);
return new Vector(vecA.type,
vecA.y * vecB.z - vecA.z * vecB.y,
vecA.z * vecB.x - vecA.x * vecB.z,
vecA.x * vecB.y - vecA.y * vecB.x
);
}
}