From c69ed3d4ea9213fd4ba89fd8dc4bedbac3963449 Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 25 Mar 2024 21:58:10 -0700 Subject: [PATCH 1/2] vecX: add truncate and midpoint functions --- src/vec2-impl.ts | 28 +++++++++++++++++++++++++++ src/vec3-impl.ts | 28 +++++++++++++++++++++++++++ src/vec4-impl.ts | 28 +++++++++++++++++++++++++++ test/tests/vec2-test.js | 42 +++++++++++++++++++++++++++++++++++++++++ test/tests/vec3-test.js | 42 +++++++++++++++++++++++++++++++++++++++++ test/tests/vec4-test.js | 42 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 210 insertions(+) diff --git a/src/vec2-impl.ts b/src/vec2-impl.ts index a195b4a..82bddaa 100644 --- a/src/vec2-impl.ts +++ b/src/vec2-impl.ts @@ -680,3 +680,31 @@ export function setLength(a: Vec2, len: number, dst?: Vec2) { normalize(a, dst); return mulScalar(dst, len, dst); } + +/** + * Ensure a vector is not longer than a max length + * + * @param a The vec2 to limit + * @param maxLen The longest length of the resulting vector + * @returns The vector, shortened to maxLen if it's too long + */ +export function truncate(a: Vec2, maxLen: number, dst?: Vec2) { + dst = dst || new VecType(2); + + if (length(a) > maxLen) + return setLength(a, maxLen, dst); + + return copy(a, dst); +} + +/** + * Return the vector exactly between 2 endpoint vectors + * + * @param a Endpoint 1 + * @param b Endpoint 2 + * @returns The vector exactly residing between endpoints 1 and 2 + */ +export function midpoint(a: Vec2, b: Vec2, dst?: Vec2) { + dst = dst || new VecType(2); + return lerp(a, b, 0.5, dst); +} diff --git a/src/vec3-impl.ts b/src/vec3-impl.ts index b584dbe..65fa3d9 100644 --- a/src/vec3-impl.ts +++ b/src/vec3-impl.ts @@ -896,3 +896,31 @@ export function setLength(a: Vec3, len: number, dst?: Vec3) { normalize(a, dst); return mulScalar(dst, len, dst); } + +/** + * Ensure a vector is not longer than a max length + * + * @param a The vec3 to limit + * @param maxLen The longest length of the resulting vector + * @returns The vector, shortened to maxLen if it's too long + */ +export function truncate(a: Vec3, maxLen: number, dst?: Vec3) { + dst = dst || new VecType(3); + + if (length(a) > maxLen) + return setLength(a, maxLen, dst); + + return copy(a, dst); +} + +/** + * Return the vector exactly between 2 endpoint vectors + * + * @param a Endpoint 1 + * @param b Endpoint 2 + * @returns The vector exactly residing between endpoints 1 and 2 + */ +export function midpoint(a: Vec3, b: Vec3, dst?: Vec3) { + dst = dst || new VecType(3); + return lerp(a, b, 0.5, dst); +} diff --git a/src/vec4-impl.ts b/src/vec4-impl.ts index f738e55..f370d0e 100644 --- a/src/vec4-impl.ts +++ b/src/vec4-impl.ts @@ -646,3 +646,31 @@ export function setLength(a: Vec4, len: number, dst?: Vec4) { normalize(a, dst); return mulScalar(dst, len, dst); } + +/** + * Ensure a vector is not longer than a max length + * + * @param a The vec4 to limit + * @param maxLen The longest length of the resulting vector + * @returns The vector, shortened to maxLen if it's too long + */ +export function truncate(a: Vec4, maxLen: number, dst?: Vec4) { + dst = dst || new VecType(4); + + if (length(a) > maxLen) + return setLength(a, maxLen, dst); + + return copy(a, dst); +} + +/** + * Return the vector exactly between 2 endpoint vectors + * + * @param a Endpoint 1 + * @param b Endpoint 2 + * @returns The vector exactly residing between endpoints 1 and 2 + */ +export function midpoint(a: Vec4, b: Vec4, dst?: Vec4) { + dst = dst || new VecType(4); + return lerp(a, b, 0.5, dst); +} diff --git a/test/tests/vec2-test.js b/test/tests/vec2-test.js index 6ca981a..93090a3 100644 --- a/test/tests/vec2-test.js +++ b/test/tests/vec2-test.js @@ -510,5 +510,47 @@ describe('vec2', () => { }); }); + describe('truncate', function() { + describe('limit a vector to a max length', function() { + let vecA; + + beforeEach(function () { + vecA = [10.323759005323593, 10.323759005323593]; + }); + + it("should shorten the vector", function () { + const result = vec2.truncate(vecA, 4.0); + assertEqualApproximately(result, [2.82842712474619, 2.82842712474619]); + assertEqualApproximately(vec2.length(result), 4.0); + }); + + it("should preserve the vector when shorter than maxLen", function () { + const result = vec2.truncate(vecA, 18.0); + assertEqualApproximately(result, [10.323759005323593, 10.323759005323593]); + assertEqualApproximately(vec2.length(result), 14.6); + }); + }); + }); + + describe('midpoint', function() { + describe('return the midpoint between 2 vectors', function() { + + it("should return the midpoint", function () { + const vecA = [ 0, 0 ] + const vecB = [ 10, 10 ] + const result = vec2.midpoint(vecA, vecB); + assertEqualApproximately(result, [ 5, 5 ]); + }); + + it("should handle negatives", function () { + const vecA = [ -10, -10 ] + const vecB = [ 10, 10 ] + const result = vec2.midpoint(vecA, vecB); + assertEqualApproximately(result, [ 0, 0 ]); + }); + + }); + }); + }); diff --git a/test/tests/vec3-test.js b/test/tests/vec3-test.js index 6b51dd6..b054cd4 100644 --- a/test/tests/vec3-test.js +++ b/test/tests/vec3-test.js @@ -566,5 +566,47 @@ describe('vec3', () => { }); }); + describe('truncate', function() { + describe('limit a vector to a max length', function() { + let vecA; + + beforeEach(function () { + vecA = [8.429313930168536, 8.429313930168536, 8.429313930168536]; + }); + + it("should shorten the vector", function () { + const result = vec3.truncate(vecA, 4.0); + assertEqualApproximately(result, [2.309401076758503, 2.309401076758503, 2.309401076758503]); + assertEqualApproximately(vec3.length(result), 4.0); + }); + + it("should preserve the vector when shorter than maxLen", function () { + const result = vec3.truncate(vecA, 18.0); + assertEqualApproximately(result, [8.429313930168536, 8.429313930168536, 8.429313930168536]); + assertEqualApproximately(vec3.length(result), 14.6); + }); + }); + }); + + describe('midpoint', function() { + describe('return the midpoint between 2 vectors', function() { + + it("should return the midpoint", function () { + const vecA = [ 0, 0, 0 ] + const vecB = [ 10, 10, 10 ] + const result = vec3.midpoint(vecA, vecB); + assertEqualApproximately(result, [ 5, 5, 5 ]); + }); + + it("should handle negatives", function () { + const vecA = [ -10, -10, -10 ] + const vecB = [ 10, 10, 10 ] + const result = vec3.midpoint(vecA, vecB); + assertEqualApproximately(result, [ 0, 0, 0 ]); + }); + + }); + }); + }); diff --git a/test/tests/vec4-test.js b/test/tests/vec4-test.js index 1a33f8d..28ff528 100644 --- a/test/tests/vec4-test.js +++ b/test/tests/vec4-test.js @@ -419,5 +419,47 @@ describe('vec4', () => { }); }); + describe('truncate', function() { + describe('limit a vector to a max length', function() { + let vecA; + + beforeEach(function () { + vecA = [8.429313930168536, 8.429313930168536, 8.429313930168536, 8.429313930168536]; + }); + + it("should shorten the vector", function () { + const result = vec4.truncate(vecA, 4.0); + assertEqualApproximately(result, [2, 2, 2, 2]); + assertEqualApproximately(vec4.length(result), 4.0); + }); + + it("should preserve the vector when shorter than maxLen", function () { + const result = vec4.truncate(vecA, 18.0); + assertEqualApproximately(result, [8.429313930168536, 8.429313930168536, 8.429313930168536, 8.429313930168536]); + assertEqualApproximately(vec4.length(result), 16.858627860337073); + }); + }); + }); + + describe('midpoint', function() { + describe('return the midpoint between 2 vectors', function() { + + it("should return the midpoint", function () { + const vecA = [ 0, 0, 0, 0 ] + const vecB = [ 10, 10, 10, 10 ] + const result = vec4.midpoint(vecA, vecB); + assertEqualApproximately(result, [ 5, 5, 5, 5 ]); + }); + + it("should handle negatives", function () { + const vecA = [ -10, -10, -10, -10 ] + const vecB = [ 10, 10, 10, 10 ] + const result = vec4.midpoint(vecA, vecB); + assertEqualApproximately(result, [ 0, 0, 0, 0 ]); + }); + + }); + }); + }); From b4a65eb7469bfc687394918e961c9ac3d966305d Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 26 Mar 2024 11:41:51 -0700 Subject: [PATCH 2/2] who lints ya, baby? --- src/vec2-impl.ts | 5 +++-- src/vec3-impl.ts | 5 +++-- src/vec4-impl.ts | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/vec2-impl.ts b/src/vec2-impl.ts index 82bddaa..2011d27 100644 --- a/src/vec2-impl.ts +++ b/src/vec2-impl.ts @@ -691,9 +691,10 @@ export function setLength(a: Vec2, len: number, dst?: Vec2) { export function truncate(a: Vec2, maxLen: number, dst?: Vec2) { dst = dst || new VecType(2); - if (length(a) > maxLen) + if (length(a) > maxLen) { return setLength(a, maxLen, dst); - + } + return copy(a, dst); } diff --git a/src/vec3-impl.ts b/src/vec3-impl.ts index 65fa3d9..7a9b564 100644 --- a/src/vec3-impl.ts +++ b/src/vec3-impl.ts @@ -907,9 +907,10 @@ export function setLength(a: Vec3, len: number, dst?: Vec3) { export function truncate(a: Vec3, maxLen: number, dst?: Vec3) { dst = dst || new VecType(3); - if (length(a) > maxLen) + if (length(a) > maxLen) { return setLength(a, maxLen, dst); - + } + return copy(a, dst); } diff --git a/src/vec4-impl.ts b/src/vec4-impl.ts index f370d0e..c5c52c2 100644 --- a/src/vec4-impl.ts +++ b/src/vec4-impl.ts @@ -657,9 +657,10 @@ export function setLength(a: Vec4, len: number, dst?: Vec4) { export function truncate(a: Vec4, maxLen: number, dst?: Vec4) { dst = dst || new VecType(4); - if (length(a) > maxLen) + if (length(a) > maxLen) { return setLength(a, maxLen, dst); - + } + return copy(a, dst); }