From 70443ea7a4d7c713a1c81a1b3fa49199ced183be Mon Sep 17 00:00:00 2001 From: Stefan Eckert Date: Tue, 31 Mar 2020 00:37:25 +0200 Subject: [PATCH] fix(vector): correct jdocs generic types --- src/point.js | 114 ++++++++------------------------------ src/vector.js | 142 ++++++++++++----------------------------------- test/point.js | 2 +- test/vector.js | 146 ++++++++++++++++++++++++++----------------------- 4 files changed, 137 insertions(+), 267 deletions(-) diff --git a/src/point.js b/src/point.js index 35c09609..ed144d33 100644 --- a/src/point.js +++ b/src/point.js @@ -115,8 +115,8 @@ class APoint { const sa = Math.sin(angle); const ca = Math.cos(angle); - const x = (this.x * ca) - (this.y * sa); - const y = (this.x * sa) + (this.y * ca); + const x = this.x * ca - this.y * sa; + const y = this.x * sa + this.y * ca; return new this.constructor(x, y); } @@ -272,16 +272,6 @@ cachedMethod(APoint, 'getRad'); cachedGetter(APoint, 'length'); cachedGetter(APoint, 'lengthSq'); -/** - * Point - * - * new Point(x: *number*, y: *number*): [[Point]] - * - * new Point(arr: *[number, number]*): [[Point]] - * - * new Point(alg: (*function*(): *number*)): [[Point]] - * - */ export class Point extends APoint { /** * @@ -331,16 +321,6 @@ export class Point extends APoint { } } -/** - * IPoint - * - * new IPoint(x: *number*, y: *number*): [[IPoint]] - * - * new IPoint(arr: *[number, number]*): [[IPoint]] - * - * new IPoint(alg: (*function*(): *number*)): [[IPoint]] - * - */ export class IPoint extends APoint { /** * @returns {PointType} @@ -362,82 +342,34 @@ export function calc(alg) { const pointFactory = cachedFactory(Point); /** - * @typedef {() => PointType} PointZero - * @typedef {(alg: Alg) => PointType} PointAlg - * @typedef {(x: number , y: number) => PointType} PointCon - * @typedef {(data: [number, number]) => PointType} PointArr - * @typedef {PointAlg & PointCon & PointArr & PointZero} point - * - * @param {number | [number, number] | Alg} [x] - * @param {number} [y] - * @returns {PointType} - * @hidden + * @template P + * @typedef {() => P} Zero + */ +/** + * @template P + * @typedef {(alg: Alg) => P} Algh + */ +/** + * @template P + * @typedef {(x: number, y: number) => P} Con + */ +/** + * @template P + * @typedef {(data: [number, number]) => P} Arr */ -export const point = function point(x, y) { - return pointFactory(x, y); -}; + +/** + * @type {Zero & Algh & Con & Arr} + */ +export const point = (...args) => pointFactory(...args); const ipointFactory = cachedFactory(IPoint); /** - * @typedef {() => IPointType} IPointZero - * @typedef {(alg: Alg) => IPointType} IPointAlg - * @typedef {(x: number , y: number) => IPointType} IPointCon - * @typedef {(data: [number, number]) => IPointType} IPointArr - * @typedef {IPointAlg & IPointCon & IPointArr & IPointType & IPointZero} - * - * @param {number | [number, number] | Alg} [x] - * @param {number} [y] - * @returns {IPointType} - * @hidden + * @type {Zero & Algh & Con & Arr} */ -export function ipoint(x, y) { - return ipointFactory(x, y); -} +export const ipoint = (x, y) => ipointFactory(x, y); export const ZERO = ipoint(0, 0); export const FORWARD = ipoint(0, -1); export const LEFT = ipoint(-1, 0); - -export const Export = { - /** - * @param {Alg} alg - * @return {PointType | IPointType} - */ - calc: alg => operatorCalc(alg), - - /** - * @type {PointZero} - */ - point: () => pointFactory(), - - /** - * @type {PointAlg} - */ - point: alg => pointFactory(alg), - - /** - * @type {PointArr} - */ - point: arr => pointFactory(arr), - - /** - * @type {PointCon} - */ - point: (x, y) => pointFactory(x, y), - - /** - * @type {IPointAlg} - */ - ipoint: alg => ipointFactory(alg), - - /** - * @type {IPointArr} - */ - ipoint: arr => ipointFactory(arr), - - /** - * @type {IPointCon} - */ - ipoint: (x, y) => ipointFactory(x, y) -}; diff --git a/src/vector.js b/src/vector.js index d78441cd..38f826bb 100644 --- a/src/vector.js +++ b/src/vector.js @@ -50,7 +50,6 @@ class AVector { } } - /** * @returns {number} */ @@ -63,7 +62,11 @@ class AVector { */ normalize() { const { length } = this; - return new this.constructor(this.x / length, this.y / length, this.z / length); + return new this.constructor( + this.x / length, + this.y / length, + this.z / length + ); } /** @@ -154,7 +157,9 @@ class AVector { * @returns {number} */ distance(v) { - return Math.sqrt(square(this.x - v.x) + square(this.y - v.y) + square(this.z - v.z)); + return Math.sqrt( + square(this.x - v.x) + square(this.y - v.y) + square(this.z - v.z) + ); } /** @@ -174,11 +179,10 @@ class AVector { return [this.x, this.y, this.z]; } - /** - * @param {string} target - * @returns {VectorType | VictorType | IPointType} - */ + * @param {string} target + * @returns {VectorType | VictorType | IPointType} + */ swizzle(target) { const data = target.split('').map(t => this[t]); if (data.length === 2) { @@ -219,7 +223,9 @@ class AVector { * @returns {string} */ toString() { - return `{ x: ${formatNumber(this.x)}, y: ${formatNumber(this.y)}, z: ${formatNumber(this.z)} }`; + return `{ x: ${formatNumber(this.x)}, y: ${formatNumber( + this.y + )}, z: ${formatNumber(this.z)} }`; } /** @@ -390,17 +396,6 @@ cachedMethod(AVector, 'toArray'); cachedGetter(AVector, 'length'); cachedGetter(AVector, 'lengthSq'); -/** - * - * Vector - * - * new Vector(x: *number*, y: *number*, z: *number*): [[Vector]] - * - * new Vector(arr: *[number, number, number]*): [[Vector]] - * - * new Vector(alg: (*function*(): *number*)): [[Vector]] - * - */ export class Vector extends AVector { /** * @@ -466,17 +461,6 @@ export class Vector extends AVector { } } -/** - * Victor - * - * new Victor(x: *number*, y: *number*, z: *number*): [[Victor]] - * - * new Victor(arr: *[number, number, number]*): [[Victor]] - * - * new Victor(alg: (*function*(): *number*)): [[Victor]] - * - * - */ export class Victor extends AVector { /** * @returns {VictorType} @@ -505,89 +489,33 @@ export function calc(alg) { const vectorFactory = cachedFactory(Vector); /** - * @typedef {() => VectorType} VectorZero - * @typedef {(alg: Alg) => VectorType} VectorAlg - * @typedef {(x: number , y: number, z: number) => VectorType} VectorCon - * @typedef {(data: [number, number, number]) => VectorType} VectorArr - * @typedef {VectorAlg & VectorCon & VectorArr & VectorZero} - * - * @param {number | [number, number, number] | Alg} [x] - * @param {number} [y] - * @param {number} [z] - * @returns {VectorType} - * @hidden + * @template Vec + * @typedef {() => Vec} Zero */ -export function vector(x, y, z) { - return vectorFactory(x, y, z); -} - -const victorFactory = cachedFactory(Victor); - /** - * @typedef {() => VictorType} VictorZero - * @typedef {(alg: Alg) => VictorType} VictorAlg - * @typedef {(x: number , y: number, z: number) => VictorType} VictorCon - * @typedef {(data: [number, number, number]) => VictorType} VictorArr - * @typedef {VictorAlg & VictorCon & VictorArr & VictorZero} - * - * @param {number | [number, number, number] | Alg} [x] - * @param {number} [y] - * @param {number} [z] - * @returns {VictorType} - * @hidden + * @template Vec + * @typedef {(alg: Alg) => Vec} Algh + */ +/** + * @template Vec + * @typedef {(x: number, y: number, z: number) => Vec} Con + */ +/** + * @template Vec + * @typedef {(data: [number, number, number]) => Vec} Arr */ -export function victor(x, y, z) { - return victorFactory(x, y, z); -} - -export const Export = { - - /** - * @param {Alg} alg - * @return {VectorType | VictorType} - */ - calc: alg => operatorCalc(alg), - - /** - * @type {VectorZero} - */ - vector: () => vectorFactory(), - - /** - * @type {VectorAlg} - */ - vector: alg => vectorFactory(alg), - - /** - * @type {VectorArr} - */ - vector: arr => vectorFactory(arr), - - /** - * @type {VectorCon} - */ - vector: (x, y, z) => vectorFactory(x, y, z), - - /** - * @type {VictorZero} - */ - victor: () => victorFactory(), - /** - * @type {VictorAlg} - */ - victor: alg => victorFactory(alg), +/** + * @type {Zero & Algh & Con & Arr} + */ +export const vector = (...args) => vectorFactory(...args); - /** - * @type {VictorArr} - */ - victor: arr => victorFactory(arr), +const victorFactory = cachedFactory(Victor); - /** - * @type {VictorCon} - */ - victor: (x, y, z) => victorFactory(x, y, z) -}; +/** + * @type {Zero & Algh & Con & Arr} + */ +export const victor = (...args) => victorFactory(...args); export const ZERO = victor(0, 0, 0); export const FORWARD = victor(0, 0, -1); diff --git a/test/point.js b/test/point.js index a08b6bf4..82370072 100644 --- a/test/point.js +++ b/test/point.js @@ -4,7 +4,7 @@ import { } from '../src/point'; /** - * @param {ipoint | point} vec2 + * @param {(typeof ipoint) | (typeof point)} vec2 * @param {(typeof Point) | (typeof IPoint)} Vec2 */ const pointTest = (vec2, Vec2) => { diff --git a/test/vector.js b/test/vector.js index 25363621..177b4c1a 100644 --- a/test/vector.js +++ b/test/vector.js @@ -1,36 +1,34 @@ -import { assert } from 'chai'; -import { - Vector, Victor, vector, victor, calc -} from '../src/vector'; -import * as Examples from '../examples'; +import { assert } from "chai"; +import { Vector, Victor, vector, victor, calc } from "../src/vector"; +import "../examples"; /** - * @param {victor | vector} vec3 + * @param {(typeof vector) | (typeof victor)} vec3 * @param {(typeof Vector) | (typeof Victor)} Vec3 */ const vectorTest = (vec3, Vec3) => { - it('should create empty vector', () => { + it("should create empty vector", () => { const pos = vec3(); assert.equal(pos.x, 0); assert.equal(pos.y, 0); assert.equal(pos.z, 0); }); - it('should create x y z values', () => { + it("should create x y z values", () => { const pos = vec3(5, 6, 7); assert.equal(pos.x, 5); assert.equal(pos.y, 6); assert.equal(pos.z, 7); }); - it('should create x y z values via array', () => { + it("should create x y z values via array", () => { const pos = vec3([5, 6, 7]); assert.equal(pos.x, 5); assert.equal(pos.y, 6); assert.equal(pos.z, 7); }); - it('should be calculated by assigned statement', () => { + it("should be calculated by assigned statement", () => { const pos = vec3(5, 6, 7); const dir = vec3(1, 0, 0); const scale = vec3(() => dir * pos); @@ -40,7 +38,7 @@ const vectorTest = (vec3, Vec3) => { assert.equal(scale.z, 0); }); - it('should be calculated by assigned statement with only numbers', () => { + it("should be calculated by assigned statement with only numbers", () => { const vec = vec3(() => 2 * 2 + 3); assert.equal(vec.x, 7); @@ -48,7 +46,7 @@ const vectorTest = (vec3, Vec3) => { assert.equal(vec.z, 7); }); - it('calling of calc should automatically detect assigned Vector types', () => { + it("calling of calc should automatically detect assigned Vector types", () => { const pos = vec3(2, 2, 2); const vec = vec3(() => 2 * pos + 3); @@ -58,7 +56,7 @@ const vectorTest = (vec3, Vec3) => { assert.equal(vec.z, 7); }); - it('should compares lengths of vector.', () => { + it("should compares lengths of vector.", () => { const pos = vec3(1, 1, 1); const dir = vec3(2, 2, 2); @@ -68,23 +66,29 @@ const vectorTest = (vec3, Vec3) => { assert.isFalse(dir.len < pos.len, `${dir} should be longer than ${pos}`); }); - it('should change length to 1 when calling normalize', () => { + it("should change length to 1 when calling normalize", () => { const pos = vec3(5, 6, 7); const dir = pos.normalize(); const length = dir.length; - assert(length > 0.99 && length < 1.01, `${dir} should have length 1, but is ${length}`); + assert( + length > 0.99 && length < 1.01, + `${dir} should have length 1, but is ${length}` + ); }); - it('should change length to 1 when normalize via arithmetic', () => { + it("should change length to 1 when normalize via arithmetic", () => { const pos = vec3(5, 6, 7); const dir = vec3(() => pos / pos.length); const length = dir.length; - assert(length > 0.99 && length < 1.01, `${dir} should have length 1, but is ${length}`); + assert( + length > 0.99 && length < 1.01, + `${dir} should have length 1, but is ${length}` + ); }); - it('should calculate the cross product', () => { + it("should calculate the cross product", () => { const dir1 = vec3(0, 1, 0); const dir2 = vec3(-1, 0, 1); const cross = dir1.cross(dir2); @@ -94,7 +98,7 @@ const vectorTest = (vec3, Vec3) => { assert.equal(cross.z, 1); }); - it('should set opposite axis to 1 when calling the cross product', () => { + it("should set opposite axis to 1 when calling the cross product", () => { const dir1 = vec3(0, 1, 0); const dir2 = vec3(-1, 0, 0); const cross = dir1.crossNormalize(dir2); @@ -104,7 +108,7 @@ const vectorTest = (vec3, Vec3) => { assert.equal(cross.z, 1); }); - it('should set opposite axis to 1 when calling the cross also when handling operators', () => { + it("should set opposite axis to 1 when calling the cross also when handling operators", () => { const dir1 = vec3(0, 1, 0); const dir2 = vec3(-1, 0, 0); const cross = vec3(() => dir1.crossNormalize(dir2) * 50); @@ -114,14 +118,14 @@ const vectorTest = (vec3, Vec3) => { assert.equal(cross.z, 50); }); - it('should create polar coordinates when calling toAngles()', () => { + it("should create polar coordinates when calling toAngles()", () => { const dir1 = vec3(0, 1, 1).normalize(); const angles = dir1.toAngles(); assert.closeTo(angles.theta, 1.57, 0.1); assert.closeTo(angles.phi, 0.78, 0.1); }); - it('should calculate correct angle between to vectors indepenetend of their lengths', () => { + it("should calculate correct angle between to vectors indepenetend of their lengths", () => { const dir1 = vec3(0, 10, 0); const dir2 = vec3(-12, 0, 0); @@ -132,7 +136,7 @@ const vectorTest = (vec3, Vec3) => { assert.closeTo(angle1, angle2, 0.1); }); - it('should create an array with x y z values', () => { + it("should create an array with x y z values", () => { const dir1 = vec3(7, 10, 12); const arr = dir1.toArray(); @@ -141,40 +145,46 @@ const vectorTest = (vec3, Vec3) => { assert.closeTo(arr[2], 12, 0.1); }); - it('should be all Vector methods usable inside operation handling', () => { + it("should be all Vector methods usable inside operation handling", () => { const dir1 = vec3(0, 1, 0); const dir2 = vec3(-1, 0, 0); - const cross1 = vec3(() => dir1.crossNormalize(dir2) * (50 + dir1.angleTo(dir2))); + const cross1 = vec3( + () => dir1.crossNormalize(dir2) * (50 + dir1.angleTo(dir2)) + ); assert.closeTo(cross1.x, 0, 0.01); assert.closeTo(cross1.y, 0, 0.01); assert.closeTo(cross1.z, 51.5707, 0.01); - const cross2 = vec3(() => dir1.crossNormalize(dir2) * (50 + dir1.toAngles().phi)); + const cross2 = vec3( + () => dir1.crossNormalize(dir2) * (50 + dir1.toAngles().phi) + ); assert.closeTo(cross2.x, 0, 0.01); assert.closeTo(cross2.y, 0, 0.01); assert.closeTo(cross2.z, 51.5707, 0.01); - const cross3 = vec3(() => dir1.crossNormalize(dir2) * (50 + dir2.toArray()[0])); + const cross3 = vec3( + () => dir1.crossNormalize(dir2) * (50 + dir2.toArray()[0]) + ); assert.closeTo(cross3.x, 0, 0.01); assert.closeTo(cross3.y, 0, 0.01); assert.closeTo(cross3.z, 49, 0.01); }); - it('should swizzle x y z values', () => { - const pos = vec3(5, 6, 7).swizzle('zxy'); + it("should swizzle x y z values", () => { + const pos = vec3(5, 6, 7).swizzle("zxy"); assert.equal(pos.x, 7); assert.equal(pos.y, 5); assert.equal(pos.z, 6); }); - it('should work when using calc function directly returns vector', () => { + it("should work when using calc function directly returns vector", () => { const dir0 = vec3(4, 4, 0); assert.throws(() => calc(() => dir0)); }); - it('should work when using calc function indirectly returns vector', () => { + it("should work when using calc function indirectly returns vector", () => { const dir0 = vec3(4, 4, 0); const res0 = calc(() => +dir0); @@ -184,23 +194,23 @@ const vectorTest = (vec3, Vec3) => { assert.equal(res0.z, 0); }); - it('should throw an error when using calc function directly with ||', () => { + it("should throw an error when using calc function directly with ||", () => { const dir0 = vec3(4, 4, 0); const pos0 = vec3(6, 0, 0); - assert.throws(() => calc(() => (pos0 * dir0) || pos0)); + assert.throws(() => calc(() => pos0 * dir0 || pos0)); const dir1 = vec3(0, 0, 0); const pos1 = vec3(6, 0, 0); - assert.throws(() => calc(() => (pos1 * dir1) || pos1)); + assert.throws(() => calc(() => pos1 * dir1 || pos1)); }); - it('should work when using calc function indirectly with ||', () => { + it("should work when using calc function indirectly with ||", () => { const dir0 = vec3(4, 4, 0); const pos0 = vec3(6, 0, 0); - const res0 = calc(() => (pos0 * dir0) || +pos0); + const res0 = calc(() => pos0 * dir0 || +pos0); assert.equal(res0.x, 24); assert.equal(res0.y, 0); @@ -209,17 +219,17 @@ const vectorTest = (vec3, Vec3) => { const dir1 = vec3(0, 0, 0); const pos1 = vec3(6, 0, 0); - const res1 = calc(() => (pos1 * dir1) || +pos1); + const res1 = calc(() => pos1 * dir1 || +pos1); assert.equal(res1.x, 6); assert.equal(res1.y, 0); assert.equal(res1.z, 0); }); - it('conditional checks inside calc should return truthy values', () => { + it("conditional checks inside calc should return truthy values", () => { const dir0 = vec3(4, 2, 5); - const res0 = calc(() => dir0 > 3 ? true : false); + const res0 = calc(() => (dir0 > 3 ? true : false)); assert.equal(res0.x, 1); assert.equal(res0.y, 0); @@ -227,17 +237,17 @@ const vectorTest = (vec3, Vec3) => { }); }; -describe('standard Vector test.', () => { +describe("standard Vector test.", () => { vectorTest(vector, Vector); }); -describe('standard Victor test.', () => { +describe("standard Victor test.", () => { vectorTest(victor, Victor); }); -describe('special Victor test.', () => { - it('should throw error when tying to change x y z values', () => { - const pos = new Victor(5, 6, 7); +describe("special Victor test.", () => { + it("should throw error when tying to change x y z values", () => { + const pos = victor(5, 6, 7); assert.throws(() => (pos.x = 27), Error); assert.equal(pos.x, 5); @@ -247,8 +257,8 @@ describe('special Victor test.', () => { assert.equal(pos.z, 7); }); - it('should toVector() create a mutable Vector copy', () => { - const ipos = new Victor(5, 6, 7); + it("should toVector() create a mutable Vector copy", () => { + const ipos = victor(5, 6, 7); const pos = ipos.toVector(); assert.instanceOf(pos, Vector); @@ -258,9 +268,9 @@ describe('special Victor test.', () => { }); }); -describe('special Vector test.', () => { - it('should change x y z values when setting directly', () => { - const pos = new Vector(5, 6, 7); +describe("special Vector test.", () => { + it("should change x y z values when setting directly", () => { + const pos = vector(5, 6, 7); pos.x = 27; assert.equal(pos.x, 27); @@ -270,7 +280,7 @@ describe('special Vector test.', () => { assert.equal(pos.z, 29); }); - it('should change x y z values when calling local calc method', () => { + it("should change x y z values when calling local calc method", () => { const pos = vector(5, 6, 7); const res = pos.calc(p => p * 25); @@ -281,23 +291,23 @@ describe('special Vector test.', () => { assert.equal(pos.z, 175); }); - it('should work throw error when using local calc method with directly ||', () => { + it("should work throw error when using local calc method with directly ||", () => { const dir0 = vector(4, 4, 0); const pos0 = vector(6, 0, 0); - assert.throws(() => pos0.calc(p => (p * dir0) || p), Error); + assert.throws(() => pos0.calc(p => p * dir0 || p), Error); - const dir1 = vector(0, 0); - const pos1 = vector(6, 0); + const dir1 = vector(0, 0, 0); + const pos1 = vector(6, 0, 0); - assert.throws(() => pos1.calc(p => (p * dir1) || p), Error); + assert.throws(() => pos1.calc(p => p * dir1 || p), Error); }); - it('should work when using local calc method with indirect ||', () => { + it("should work when using local calc method with indirect ||", () => { const dir0 = vector(4, 4, 0); const pos0 = vector(6, 0, 0); - const res0 = pos0.calc(p => (p * dir0) || +p); + const res0 = pos0.calc(p => p * dir0 || +p); assert.isTrue(pos0 === res0); assert.equal(pos0, res0); @@ -305,10 +315,10 @@ describe('special Vector test.', () => { assert.equal(res0.y, 0); assert.equal(res0.z, 0); - const dir1 = vector(0, 0); - const pos1 = vector(6, 0); + const dir1 = vector(0, 0, 0); + const pos1 = vector(6, 0, 0); - const res1 = pos1.calc(p => (p * dir1) || +p); + const res1 = pos1.calc(p => p * dir1 || +p); assert.isTrue(pos1 === res1); assert.equal(pos1, res1); @@ -317,14 +327,14 @@ describe('special Vector test.', () => { assert.equal(res1.z, 0); }); - it('should work throw an error using local calc method directly returns vector', () => { + it("should work throw an error using local calc method directly returns vector", () => { const dir0 = vector(4, 4, 0); const pos0 = vector(6, 0, 0); assert.throws(() => pos0.calc(() => dir0), Error); }); - it('should work when using local calc method indirectly returns vector', () => { + it("should work when using local calc method indirectly returns vector", () => { const dir0 = vector(4, 4, 0); const pos0 = vector(6, 0, 0); @@ -338,8 +348,8 @@ describe('special Vector test.', () => { }); }); -describe('calc test.', () => { - it('calling of calc should generate only numbers if no vector is in use', () => { +describe("calc test.", () => { + it("calling of calc should generate only numbers if no vector is in use", () => { const vec = calc(() => 2 * 2 + 3); assert.equal(vec, 7); }); @@ -350,8 +360,8 @@ describe('performance test', () => { it('should be fast', () => { let time = new Date().getTime(); - const v1 = new Vector(1, 2, 3); - const v2 = new Vector(4, 5, 6); + const v1 = vector(1, 2, 3); + const v2 = vector(4, 5, 6); for (let i = 0; i < 10000; i++) { const v3 = calc(() => v1.cross(v2) + v2 * v1 - v1 / v2 + (v2 * v2) / v1); } @@ -362,8 +372,8 @@ describe('performance test', () => { it('should be faster', () => { let time = new Date().getTime(); - const v1 = new Vector(1, 2, 3); - const v2 = new Vector(4, 5, 6); + const v1 = vector(1, 2, 3); + const v2 = vector(4, 5, 6); const fn = () => v1 + v2 * v1 - v1 / v2 + (v2 * v2) / v1; for (let i = 0; i < 10000; i++) {