From e18598cd621fa29d98dd19f01f36dfdff99237e1 Mon Sep 17 00:00:00 2001 From: elexis Date: Sun, 8 Oct 2017 15:25:21 +0000 Subject: [PATCH] Fix Vector.js rotate oversight in 7778a7b436 (this.x may not be modified before reading again and sin/cos should not be computed twice). Extend the tests of rotate in 99494251a1 to reveal the bug. Add non-static clone functions for vectors (as the static ones were incorrectly removed in e95f4e9744). Math.pow performance is investigated separately, refs P85. Checks and balances by mimo, leper, FeXoR and fatherbushido This was SVN commit r20272. --- .../data/mods/public/globalscripts/vector.js | 21 +++++++- .../components/tests/test_Vector.js | 49 ++++++++++++++++++- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/binaries/data/mods/public/globalscripts/vector.js b/binaries/data/mods/public/globalscripts/vector.js index 3c451658d4..f792830a45 100644 --- a/binaries/data/mods/public/globalscripts/vector.js +++ b/binaries/data/mods/public/globalscripts/vector.js @@ -16,6 +16,11 @@ function Vector2D(x, y) this.set(0, 0); } +Vector2D.prototype.clone = function() +{ + return new Vector2D(this.x, this.y); +}; + // Mutating 2D functions // // These functions modify the current object, @@ -70,8 +75,15 @@ Vector2D.prototype.normalize = function() */ Vector2D.prototype.rotate = function(a) { - this.x = this.x * Math.cos(a) + this.y * Math.sin(a); - this.y = this.y * Math.cos(a) - this.x * Math.sin(a); + let sin = Math.sin(a); + let cos = Math.cos(a); + + let x = this.x * cos + this.y * sin; + let y = this.y * cos - this.x * sin; + + this.x = x; + this.y = y; + return this; }; @@ -179,6 +191,11 @@ function Vector3D(x, y, z) this.set(0, 0, 0); } +Vector3D.prototype.clone = function() +{ + return new Vector3D(this.x, this.y, this.z); +}; + // Mutating 3D functions // // These functions modify the current object, diff --git a/binaries/data/mods/public/simulation/components/tests/test_Vector.js b/binaries/data/mods/public/simulation/components/tests/test_Vector.js index e89dbffe4b..c70e35bd55 100644 --- a/binaries/data/mods/public/simulation/components/tests/test_Vector.js +++ b/binaries/data/mods/public/simulation/components/tests/test_Vector.js @@ -35,6 +35,43 @@ var brokenVector = { TS_ASSERT_EQUALS(v4.x, -2); TS_ASSERT_EQUALS(v4.y, 5); + // Result of rotating (1, 0) + let unitCircle = [ + { + "angle": Math.PI / 2, + "x": 0, + "y": 1 + }, + { + "angle": Math.PI / 3, + "x": 1/2, + "y": Math.sqrt(3) / 2 + }, + { + "angle": Math.PI / 4, + "x": Math.sqrt(2) / 2, + "y": Math.sqrt(2) / 2 + }, + { + "angle": Math.PI / 6, + "x": Math.sqrt(3) / 2, + "y": 1/2 + } + ]; + + let epsilon = 0.00000001; + + for (let expectedVector of unitCircle) + { + let computedVector = new Vector2D(1, 0).rotate(-expectedVector.angle); + for (let s of ["x", "y"]) + if (Math.abs(expectedVector[s] - computedVector[s]) > epsilon) + { + TS_FAIL("Expected " + uneval(expectedVector) + " got " + uneval(computedVector)); + break; + } + } + TS_ASSERT_EQUALS(new Vector2D(2, 3).dot(new Vector2D(4, 5)), 23); TS_ASSERT_EQUALS(new Vector2D(3, 5).cross(new Vector2D(-4, -1/3)), 19); TS_ASSERT_EQUALS(new Vector2D(20, 21).length(), 29); @@ -44,6 +81,11 @@ var brokenVector = { TS_ASSERT_EQUALS(v5.compareLength(new Vector2D(500, 800)), -1); TS_ASSERT_EQUALS(v5.compareLength(new Vector2D(10, 20)), 0); TS_ASSERT(isNaN(v5.compareLength(brokenVector))); + + let v6 = v5.clone(); + TS_ASSERT_EQUALS(v5.x, v6.x); + TS_ASSERT_EQUALS(v5.y, v6.y); + TS_ASSERT(Math.abs(v5.dot(v6.rotate(Math.PI / 2))) < epsilon); } // Test Vector3D @@ -59,4 +101,9 @@ var brokenVector = { TS_ASSERT_EQUALS(new Vector3D(1, 2, 3).dot(new Vector3D(4, 5, 6)), 32); -} \ No newline at end of file + let v3 = new Vector3D(9, 10, 11); + let v4 = v3.clone(); + TS_ASSERT_EQUALS(v3.x, v4.x); + TS_ASSERT_EQUALS(v3.y, v4.y); + TS_ASSERT_EQUALS(v3.z, v4.z); +}