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.
This commit is contained in:
elexis 2017-10-08 15:25:21 +00:00
parent 8bbe94c926
commit e18598cd62
2 changed files with 67 additions and 3 deletions

View file

@ -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,

View file

@ -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);
}
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);
}