From 2ab3c1f16ff8dd5b5da7dc86b745324b494498cd Mon Sep 17 00:00:00 2001 From: harshiltewari2004 Date: Fri, 19 Jun 2026 21:50:38 +0530 Subject: [PATCH] Add friendly warning when p5.Vector.cross() is called on non-3D vectors --- src/math/p5.Vector.js | 18 ++++++++++++------ test/unit/math/p5.Vector.js | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/math/p5.Vector.js b/src/math/p5.Vector.js index e7a90d4218..a764da4a59 100644 --- a/src/math/p5.Vector.js +++ b/src/math/p5.Vector.js @@ -1419,13 +1419,13 @@ class Vector { * // META:norender * function setup() { * // Create p5.Vector objects. - * let v1 = createVector(1, 0); - * let v2 = createVector(3, 4); + * let v1 = createVector(1, 0, 0); + * let v2 = createVector(0, 1, 0); * * // Calculate the cross product. * let cp = v1.cross(v2); * - * // Prints "p5.Vector Object : [0, 0, 4]" to the console. + * // Prints "vector[0, 0, 1]" to the console. * print(cp.toString()); * } * @@ -1433,17 +1433,23 @@ class Vector { * // META:norender * function setup() { * // Create p5.Vector objects. - * let v1 = createVector(1, 0); - * let v2 = createVector(3, 4); + * let v1 = createVector(1, 0, 0); + * let v2 = createVector(0, 1, 0); * * // Calculate the cross product. * let cp = p5.Vector.cross(v1, v2); * - * // Prints "p5.Vector Object : [0, 0, 4]" to the console. + * // Prints "vector[0, 0, 1]" to the console. * print(cp.toString()); * } */ cross(v) { + if (this.dimensions !== 3 || v.dimensions !== 3){ + this._friendlyError( + 'cross() is designed for 3D vectors. It uses only the x, y, and z components, so the result may not be meaningful when either vector is not 3D.', + 'p5.Vector.cross' + ); + } const x = this.y * v.z - this.z * v.y; const y = this.z * v.x - this.x * v.z; const z = this.x * v.y - this.y * v.x; diff --git a/test/unit/math/p5.Vector.js b/test/unit/math/p5.Vector.js index df694d71a6..4abff37dcf 100644 --- a/test/unit/math/p5.Vector.js +++ b/test/unit/math/p5.Vector.js @@ -348,6 +348,15 @@ suite('p5.Vector', function () { v2 = new Vector(-219, -560); expect(v1.angleBetween(v2)).to.be.closeTo(Math.PI, 0.0000001); }); + + test('should not surface cross()\'s 3D warning for genuine 2D vectors', function () { + // angleBetween supports 2D vectors and calls this.cross(v) internally. + // It should not leak cross()'s 3D friendly error to the user. + // RED until #8926 decouples angleBetween from cross(). + FESCalled = false; + new Vector(-11, -20).angleBetween(new Vector(-5.5, -10)); + assert.equal(FESCalled, false); + }); }); suite('p5.Vector.angleBetween() [CLASS]', function () { @@ -1157,6 +1166,23 @@ suite('p5.Vector', function () { expect(res.z).to.eql(-3); }); }); + test('should trigger a friendly error when either vector is not 3D', function () { + // 2D inputs + FESCalled = false; + new Vector(1, 0).cross(new Vector(0, 1)); + assert.equal(FESCalled, true); + + // >3D inputs + FESCalled = false; + new Vector(1, 0, 0, 2).cross(new Vector(0, 0, 1, -1)); + assert.equal(FESCalled, true); + }); + + test('should not trigger a friendly error for two 3D vectors', function () { + FESCalled = false; + new Vector(1, 0, 0).cross(new Vector(0, 1, 0)); + assert.equal(FESCalled, false); + }); }); suite('dist', function () { @@ -1607,6 +1633,15 @@ suite('p5.Vector', function () { expect(v.y).to.eql(22); expect(v.z).to.eql(32); }); + + test('should not surface cross()\'s 3D warning for genuine 2D vectors', function () { + // slerp uses this.cross(v) to find the rotation axis. Calling it with + // genuine 2-component vectors should not leak cross()'s 3D friendly error. + // RED until #8928 decouples slerp from cross(). + FESCalled = false; + new Vector(2, 3).slerp(new Vector(3, -2), 0.3); + assert.equal(FESCalled, false); + }); }); suite('p5.Vector.slerp(v1, v2, amt)', function () {