๐Vector
support vector operations๏ผu + v, u - v, k * v ...
u + v: u.plus(v)
u - v: u.minus(v)
k * v: v.times(k)
au + bv + cw: linearCombination([a,b,c], [u,v,w])
๐ custom
replit โฉ Vector (v1.1) , require -> Number+ext
// 2023.01.22 - 21:04 (/) refactor vec(x,y) -> vec(...args)
// 2023.01.21 - 13:18 (+) .clampInRect()
// 2023.01.15 - 19:56 (+) linearCombination()
// 2023.01.15 - 08:50 (?) refactor, first recorded.
// ------------------------------------------------------
const {sin, cos, sqrt} = Math;
// โญ๏ธ import
// ------------------------------------------------------
import { } from './Number+ext.js'; // ๐ Number + ext
// โญ๏ธ Vector
// ------------------------------------------------------
// - vec(x, y), vec(v)
// - polar(r, theta)
// - linearCombination(scalars, vectors)
// ------------------------------------------------------
// ๐ธ .x
// ๐ธ .y
// ๐ธ .coords : [x, y]
// ๐ธ .inverse : -v (additive inverse)
// ๐น .plus(...args) : (v), (x, y)
// ๐น .minus(...args) : (v), (x, y)
// ๐น .times(k) : u * k (scalar product)
// ------------------------------------------------------
// ๐ธ .length
// ๐น .distanceTo(...args) : (v), (x, y)
// ------------------------------------------------------
// ๐น .toString()
// ------------------------------------------------------
//
class Vector {
// ๐ง Vector.zero
static get zero() { return new Vector(0, 0) }
// init
constructor(x, y) {
this.x = x;
this.y = y;
}
// ๐ธ .coords
get coords() { return [this.x, this.y] }
// -----------
// -v
// -----------
// ๐ธ .inverse
get inverse() { return new Vector(-this.x, -this.y) }
// -------------
// u + v
// -------------
// ๐น u.plus(v) or u.plus(x, y)
plus(...args) {
// treat as u + v
if (args.length === 1) {
const v = args[0];
return new Vector(this.x + v.x, this.y + v.y)
}
// treat as u + (x, y)
if (args.length === 2) return this.plus(vec(...args));
// throw error otherwise
throw new Error(`Vector.plus() is expecting 1 or 2 arguments, but got ${args.length}.`);
}
// -------------
// u - v
// -------------
// ๐น u.minus(v) or u.minus(x, y)
minus(...args) {
// treat as u - v
if (args.length === 1) {
const v = args[0];
return new Vector(this.x - v.x, this.y - v.y);
}
// treat as u - (x, y)
if (args.length === 2) return this.minus(vec(...args));
// throw error otherwise
throw new Error(`Vector.minus() is expecting 1 or 2 arguments, but got ${args.length}.`);
}
// -------------
// k * v
// -------------
// ๐น .times(k)
times(k) { return new Vector(this.x * k, this.y * k) }
// ------------------------
// distance related
// ------------------------
// ๐ธ .length
get length() {
const {x, y} = this;
return sqrt(x*x + y*y);
}
// ๐น .distanceTo(v) or .distanceTo(x, y)
distanceTo(...args) {
// u.distanceTo(v)
if (args.length === 1) {
const v = args[0];
return this.minus(v).length;
}
// u.distanceTo(x, y)
if (args.length === 2) {
return this.distanceTo(vec(...args));
}
// throw error otherwise
throw new Error(`Vector.distanceTo() is expecting 1 or 2 arguments, but got ${args.length}.`);
}
// ๐น .isEqualTo(v)
isEqualTo(v, {threshold = 100 * Number.EPSILON}={}) {
return areEqualNumbers(0, this.distanceTo(v), {threshold});
}
// ---------------
// rect
// ---------------
clampInRect(rect) {
const {x: x1, y: y1} = rect.origin;
const {x: x2, y: y2} = rect.bottomRight;
return vec(this.x.clamp(x1, x2), this.y.clamp(y1, y2)); // ๐ Number + ext
}
// ---------------
// debug
// ---------------
// ๐น .toString()
toString() { return `(${this.x}, ${this.y})` }
// โญ๏ธ custom type name
// โ๏ธ note: typeof vec(1,2) === 'object'
get [Symbol.toStringTag]() { return 'Vector' }
}
// ----------------------------------------
// โญ๏ธ convenience factory functions
// ----------------------------------------
// vec(x, y), vec(v) // ๐ Vector (v1.1)
function vec(...args) {
const len = args.length;
// treat as vec(x, y)
if (len === 2) return new Vector(...args);
// treat as vec(v)
if (len === 1) {
const {x, y} = args[0];
return new Vector(x, y)
};
// throw error otherwise
throw new Error(`vec(): expecting 1 or 2 arguments, but got ${len}!`);
}
// polar(r, theta)
function polar(r, theta) {
return vec(r * cos(theta), r * sin(theta))
}
// linear combination: a1*v1 + a2*v2 + ... + an*vn
function linearCombination(scalars, vectors) {
return vectors
.map((v, i) => v.times(scalars[i] || 0))
.reduce((sum, vec) => sum.plus(vec), Vector.zero);
}
// --------------
// โญ๏ธ helpers
// --------------
// โญ๏ธ areEqualNumbers(x, y {threshold})
// - Number.EPSILON = 2^(-52) โ 2.2 * 10^(-16)
function areEqualNumbers(x, y, {threshold = Number.EPSILON}={}) {
return Math.abs(x - y) < threshold;
}
// ๐ค export
// -----------------------------
export { vec, polar, Vector, linearCombination }; // export ES module
// module.exports = { vec, polar, Vector, linearCombination };
Rect - origin, size, width, height ...
Canvas+ext - use
vec()
.elem.position() - (.borderBox) position relative to some coordinates system.
History
replit โฉ vector (with canvas example)
0: (?) first recorded, refactor.
1: (+) linearCombination()
2: (+) .clampInRect()
// 2023.01.15 - 08:50 (?) first recorded
// ------------------------------------------------------
const {sin, cos} = Math;
// โญ๏ธ Vector
// ------------------------------------------------------
// ๐ธ .x
// ๐ธ .y
// ๐ธ .coords : [x, y]
// ๐ธ .inverse : -v (additive inverse)
// ๐น .add(v) : u + v
// ๐น .plus(x, y) : u + (x, y)
// ๐น .minus(v) : u - v
// ๐น .subtract(x, y) : u - (x, y)
// ๐น .times(k) : u * k (scalar product)
// ------------------------------------------------------
// ๐น .toString()
//
class Vector {
// init
constructor(x, y) {
this.x = x;
this.y = y;
}
// ๐ธ .coords
get coords() { return [this.x, this.y] }
// -------------
// u + v
// -------------
// ๐น u.add(v)
add(v) { return new Vector(this.x + v.x, this.y + v.y) }
// ๐น u.plus(x, y)
plus(x, y) { return this.add(new Vector(x, y)) }
// -----------
// -v
// -----------
// ๐ธ .inverse
get inverse() { return new Vector(-this.x, -this.y) }
// -------------
// u - v
// -------------
// ๐น u.minus(v)
subtract(v) { return new Vector(this.x - v.x, this.y - v.y) }
// ๐น u.subtract(x, y)
minus(x, y) { return this.subtract(new Vector(x, y)) }
// -------------
// k * v
// -------------
// ๐น .times(k)
times(k) { return new Vector(this.x * k, this.y * k) }
// ---------------
// helpers
// ---------------
// ๐น .toString()
toString() { return `(${this.x}, ${this.y})` }
}
// ----------------------------------------
// โญ๏ธ convenience factory functions
// ----------------------------------------
function vec(x, y) { return new Vector(x, y) }
function polar(r, theta) {
return vec(r * cos(theta), r * sin(theta))
}
// export
export {
vec, polar, Vector,
};
// 2023.01.15 - 19:56 (+) linearCombination()
// 2023.01.15 - 08:50 (?) refactor, first recorded.
// ------------------------------------------------------
const {sin, cos, sqrt} = Math;
// โญ๏ธ Vector
// ------------------------------------------------------
// - vec(x, y)
// - polar(r, theta)
// - linearCombination(scalars, vectors)
// ------------------------------------------------------
// ๐ธ .x
// ๐ธ .y
// ๐ธ .coords : [x, y]
// ๐ธ .inverse : -v (additive inverse)
// ๐น .plus(...args) : (v), (x, y)
// ๐น .minus(...args) : (v), (x, y)
// ๐น .times(k) : u * k (scalar product)
// ------------------------------------------------------
// ๐ธ .length
// ๐น .distanceTo(...args) : (v), (x, y)
// ------------------------------------------------------
// ๐น .toString()
// ------------------------------------------------------
//
class Vector {
// ๐ง Vector.zero
static get zero() { return new Vector(0, 0) }
// init
constructor(x, y) {
this.x = x;
this.y = y;
}
// ๐ธ .coords
get coords() { return [this.x, this.y] }
// -----------
// -v
// -----------
// ๐ธ .inverse
get inverse() { return new Vector(-this.x, -this.y) }
// -------------
// u + v
// -------------
// ๐น u.plus(v) or u.plus(x, y)
plus(...args) {
// treat as u + v
if (args.length === 1) {
const v = args[0];
return new Vector(this.x + v.x, this.y + v.y)
}
// treat as u + (x, y)
if (args.length === 2) return this.plus(vec(...args));
// throw error otherwise
throw new Error(`Vector.plus() is expecting 1 or 2 arguments, but got ${args.length}.`);
}
// -------------
// u - v
// -------------
// ๐น u.minus(v) or u.minus(x, y)
minus(...args) {
// treat as u - v
if (args.length === 1) {
const v = args[0];
return new Vector(this.x - v.x, this.y - v.y);
}
// treat as u - (x, y)
if (args.length === 2) return this.minus(vec(...args));
// throw error otherwise
throw new Error(`Vector.minus() is expecting 1 or 2 arguments, but got ${args.length}.`);
}
// -------------
// k * v
// -------------
// ๐น .times(k)
times(k) { return new Vector(this.x * k, this.y * k) }
// ------------------------
// distance related
// ------------------------
// ๐ธ .length
get length() {
const {x, y} = this;
return sqrt(x*x + y*y);
}
// ๐น .distanceTo(v) or .distanceTo(x, y)
distanceTo(...args) {
// u.distanceTo(v)
if (args.length === 1) {
const v = args[0];
return this.minus(v).length;
}
// u.distanceTo(x, y)
if (args.length === 2) {
return this.distanceTo(vec(...args));
}
// throw error otherwise
throw new Error(`Vector.distanceTo() is expecting 1 or 2 arguments, but got ${args.length}.`);
}
// ๐น .isEqualTo(v)
isEqualTo(v, {threshold = 100 * Number.EPSILON}={}) {
return areEqualNumbers(0, this.distanceTo(v), {threshold});
}
// ---------------
// debug
// ---------------
// ๐น .toString()
toString() { return `(${this.x}, ${this.y})` }
// โญ๏ธ custom type name
// โ๏ธ note: typeof vec(1,2) === 'object'
get [Symbol.toStringTag]() { return 'Vector' }
}
// ----------------------------------------
// โญ๏ธ convenience factory functions
// ----------------------------------------
// vec(x, y)
function vec(x, y) { return new Vector(x, y) }
// polar(r, theta)
function polar(r, theta) {
return vec(r * cos(theta), r * sin(theta))
}
// linear combination: a1*v1 + a2*v2 + ... + an*vn
function linearCombination(scalars, vectors) {
return vectors
.map((v, i) => v.times(scalars[i] || 0))
.reduce((sum, vec) => sum.plus(vec), Vector.zero);
}
// --------------
// โญ๏ธ helpers
// --------------
// โญ๏ธ areEqualNumbers(x, y {threshold})
// - Number.EPSILON = 2^(-52) โ 2.2 * 10^(-16)
function areEqualNumbers(x, y, {threshold = Number.EPSILON}={}) {
return Math.abs(x - y) < threshold;
}
// ๐ค export
// -----------------------------
// export { vec, polar, Vector, linearCombination }; // export ES module
module.exports = { vec, polar, Vector, linearCombination };
๐พ replit โฉ Vector.js , require -> Number+ext
// 2023.01.21 - 13:18 (+) .clampInRect()
// 2023.01.15 - 19:56 (+) linearCombination()
// 2023.01.15 - 08:50 (?) refactor, first recorded.
// ------------------------------------------------------
const {sin, cos, sqrt} = Math;
// โญ๏ธ import
// ------------------------------------------------------
import { } from './Number+ext.js'; // ๐ Number + ext
// โญ๏ธ Vector
// ------------------------------------------------------
// - vec(x, y)
// - polar(r, theta)
// - linearCombination(scalars, vectors)
// ------------------------------------------------------
// ๐ธ .x
// ๐ธ .y
// ๐ธ .coords : [x, y]
// ๐ธ .inverse : -v (additive inverse)
// ๐น .plus(...args) : (v), (x, y)
// ๐น .minus(...args) : (v), (x, y)
// ๐น .times(k) : u * k (scalar product)
// ------------------------------------------------------
// ๐ธ .length
// ๐น .distanceTo(...args) : (v), (x, y)
// ------------------------------------------------------
// ๐น .toString()
// ------------------------------------------------------
//
class Vector {
// ๐ง Vector.zero
static get zero() { return new Vector(0, 0) }
// init
constructor(x, y) {
this.x = x;
this.y = y;
}
// ๐ธ .coords
get coords() { return [this.x, this.y] }
// -----------
// -v
// -----------
// ๐ธ .inverse
get inverse() { return new Vector(-this.x, -this.y) }
// -------------
// u + v
// -------------
// ๐น u.plus(v) or u.plus(x, y)
plus(...args) {
// treat as u + v
if (args.length === 1) {
const v = args[0];
return new Vector(this.x + v.x, this.y + v.y)
}
// treat as u + (x, y)
if (args.length === 2) return this.plus(vec(...args));
// throw error otherwise
throw new Error(`Vector.plus() is expecting 1 or 2 arguments, but got ${args.length}.`);
}
// -------------
// u - v
// -------------
// ๐น u.minus(v) or u.minus(x, y)
minus(...args) {
// treat as u - v
if (args.length === 1) {
const v = args[0];
return new Vector(this.x - v.x, this.y - v.y);
}
// treat as u - (x, y)
if (args.length === 2) return this.minus(vec(...args));
// throw error otherwise
throw new Error(`Vector.minus() is expecting 1 or 2 arguments, but got ${args.length}.`);
}
// -------------
// k * v
// -------------
// ๐น .times(k)
times(k) { return new Vector(this.x * k, this.y * k) }
// ------------------------
// distance related
// ------------------------
// ๐ธ .length
get length() {
const {x, y} = this;
return sqrt(x*x + y*y);
}
// ๐น .distanceTo(v) or .distanceTo(x, y)
distanceTo(...args) {
// u.distanceTo(v)
if (args.length === 1) {
const v = args[0];
return this.minus(v).length;
}
// u.distanceTo(x, y)
if (args.length === 2) {
return this.distanceTo(vec(...args));
}
// throw error otherwise
throw new Error(`Vector.distanceTo() is expecting 1 or 2 arguments, but got ${args.length}.`);
}
// ๐น .isEqualTo(v)
isEqualTo(v, {threshold = 100 * Number.EPSILON}={}) {
return areEqualNumbers(0, this.distanceTo(v), {threshold});
}
// ---------------
// rect
// ---------------
clampInRect(rect) {
const {x: x1, y: y1} = rect.origin;
const {x: x2, y: y2} = rect.bottomRight;
return vec(this.x.clamp(x1, x2), this.y.clamp(y1, y2)); // ๐ Number + ext
}
// ---------------
// debug
// ---------------
// ๐น .toString()
toString() { return `(${this.x}, ${this.y})` }
// โญ๏ธ custom type name
// โ๏ธ note: typeof vec(1,2) === 'object'
get [Symbol.toStringTag]() { return 'Vector' }
}
// ----------------------------------------
// โญ๏ธ convenience factory functions
// ----------------------------------------
// vec(x, y)
function vec(x, y) { return new Vector(x, y) }
// polar(r, theta)
function polar(r, theta) {
return vec(r * cos(theta), r * sin(theta))
}
// linear combination: a1*v1 + a2*v2 + ... + an*vn
function linearCombination(scalars, vectors) {
return vectors
.map((v, i) => v.times(scalars[i] || 0))
.reduce((sum, vec) => sum.plus(vec), Vector.zero);
}
// --------------
// โญ๏ธ helpers
// --------------
// โญ๏ธ areEqualNumbers(x, y {threshold})
// - Number.EPSILON = 2^(-52) โ 2.2 * 10^(-16)
function areEqualNumbers(x, y, {threshold = Number.EPSILON}={}) {
return Math.abs(x - y) < threshold;
}
// ๐ค export
// -----------------------------
export { vec, polar, Vector, linearCombination }; // export ES module
// module.exports = { vec, polar, Vector, linearCombination };
Last updated