Skip to content

Commit

Permalink
feat(math): Add Vec2.rotate()
Browse files Browse the repository at this point in the history
  • Loading branch information
jespertheend committed Aug 9, 2024
1 parent f6dd4d6 commit 7406a23
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 1 deletion.
32 changes: 31 additions & 1 deletion src/math/Vec2.js
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ export class Vec2 {
}

/**
* Computes the cross product between this and another vector and changes the value of this vector.
* Computes the cross product between this and another vector.
*
* [Cross product visualisation](https://www.geogebra.org/m/psMTGDgc) (in 3d)
*
Expand Down Expand Up @@ -525,6 +525,36 @@ export class Vec2 {
return this.set(other);
}

/**
* Rotates the vector (around 0, 0) and modifies it.
* Positive angles rotate the vector clockwise. (Positive x is right, positive y is down)
*
* For instance, say you have a `Vec2<1, 1>`:
* ```none
* o
* \
* \
* V
* ```
* then calling `rotate(Math.PI * 0.5)` results in a `Vec2<-1, 1>`:
* ```none
* o
* /
* /
* V
* ```
* @param {number} angle Angle in radians.
*/
rotate(angle) {
const cos = Math.cos(angle);
const sin = Math.sin(angle);

return this.set(
this._x * cos - this._y * sin,
this._x * sin + this._y * cos,
);
}

/**
* @returns {[x: number, y: number]}
*/
Expand Down
53 changes: 53 additions & 0 deletions test/unit/src/math/Vec2.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,48 @@ Deno.test({
},
});

Deno.test({
name: "rotate()",
fn() {
const tests = [
{ vec: [0, 1], angle: 0, result: [0, 1] },
{ vec: [0, 1], angle: Math.PI, result: [0, -1] },
{ vec: [1, 0], angle: Math.PI * 0.5, result: [0, 1] },
{ vec: [1, 1], angle: Math.PI * 0.5, result: [-1, 1] },
{ vec: [0, 0], angle: 100, result: [0, 0] },
{ vec: [12, 34], angle: Math.PI * 2, result: [12, 34] },
{ vec: [12, 34], angle: 0.1, result: [8.54571, 35.02814] },
];

for (const { vec, angle, result } of tests) {
const actual = new Vec2(vec).rotate(angle);

assertVecAlmostEquals(actual, result);
}
},
});

Deno.test({
name: "rotate() angle matches the direction of clockwiseAngleTo",
fn() {
const tests = [
[0.123, -0.456],
[0.5, 2],
[-10, 20],
[-10, -20],
];

for (const test of tests) {
const vec = new Vec2(test);
const newVec = new Vec2(0, 1);
const angle = newVec.clockwiseAngleTo(vec);
newVec.rotate(angle);
newVec.magnitude = vec.magnitude;
assertVecAlmostEquals(newVec, test);
}
},
});

// ======== onChange Callbacks ========

Deno.test({
Expand Down Expand Up @@ -894,6 +936,17 @@ Deno.test({
fireResults.push(-1);
expectedResult.push(-1);

vec.set(0, 1);
expectedResult.push(0x11);

vec.rotate(0);
// rotating 0 radians shouldn't fire the callback
fireResults.push(-1);
expectedResult.push(-1);

vec.rotate(0.5);
expectedResult.push(0x11);

assertEquals(fireResults, expectedResult);
},
});

0 comments on commit 7406a23

Please sign in to comment.