@inglorious/utils 2.2.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/src/algorithms/decision-tree.test.js +7 -6
  4. package/src/algorithms/index.js +4 -0
  5. package/src/algorithms/path-finding.js +2 -2
  6. package/src/data-structures/index.js +10 -0
  7. package/src/functions/index.js +4 -0
  8. package/src/index.js +8 -0
  9. package/src/math/{geometry/circle.js → circle.js} +6 -6
  10. package/src/math/{geometry/circle.test.js → circle.test.js} +23 -22
  11. package/src/math/{geometry/hitmask.test.js → hitmask.test.js} +16 -15
  12. package/src/math/index.js +35 -0
  13. package/src/math/{geometry/line.js → line.js} +4 -4
  14. package/src/math/{geometry/line.test.js → line.test.js} +11 -10
  15. package/src/math/{geometry/point.js → point.js} +5 -5
  16. package/src/math/{geometry/point.test.js → point.test.js} +23 -22
  17. package/src/math/{linear-algebra/quaternion.js → quaternion.js} +3 -2
  18. package/src/math/{linear-algebra/quaternion.test.js → quaternion.test.js} +1 -1
  19. package/src/math/{linear-algebra/quaternions.test.js → quaternions.test.js} +1 -1
  20. package/src/math/{geometry/rectangle.js → rectangle.js} +3 -3
  21. package/src/math/{geometry/rectangle.test.js → rectangle.test.js} +13 -12
  22. package/src/math/{geometry/segment.js → segment.js} +5 -5
  23. package/src/math/{geometry/segment.test.js → segment.test.js} +48 -47
  24. package/src/math/{geometry/types.d.ts → types.d.ts} +10 -0
  25. package/src/math/{linear-algebra/vector.js → vector.js} +113 -65
  26. package/src/math/{linear-algebra/vector.test.js → vector.test.js} +80 -29
  27. package/src/math/{linear-algebra/vectors.test.js → vectors.test.js} +12 -30
  28. package/src/physics/acceleration.js +3 -3
  29. package/src/physics/friction.js +2 -2
  30. package/src/physics/friction.test.js +7 -6
  31. package/src/physics/gravity.js +2 -2
  32. package/src/physics/gravity.test.js +10 -9
  33. package/src/physics/index.js +7 -0
  34. package/src/physics/jump.js +1 -1
  35. package/src/physics/velocity.js +3 -3
  36. package/src/v.js +18 -0
  37. package/src/math/linear-algebra/2d.js +0 -28
  38. package/src/math/linear-algebra/2d.test.js +0 -17
  39. package/src/math/linear-algebra/types.d.ts +0 -4
  40. /package/src/math/{geometry/hitmask.js → hitmask.js} +0 -0
  41. /package/src/math/{linear-algebra/quaternions.js → quaternions.js} +0 -0
  42. /package/src/math/{geometry/triangle.js → triangle.js} +0 -0
  43. /package/src/math/{geometry/triangle.test.js → triangle.test.js} +0 -0
  44. /package/src/math/{linear-algebra/vectors.js → vectors.js} +0 -0
@@ -1,15 +1,16 @@
1
1
  import { expect, test } from "vitest"
2
2
 
3
+ import { v } from "../v.js"
3
4
  import { intersectsRectangle } from "./rectangle.js"
4
5
 
5
6
  test("it should prove that a rectangle crossing another one intersects with it", () => {
6
7
  const rectangle1 = {
7
- position: [0, 0, 0],
8
- size: [2, 2, 2],
8
+ position: v(0, 0, 0),
9
+ size: v(2, 2, 2),
9
10
  }
10
11
  const rectangle2 = {
11
- position: [1, 1, 1],
12
- size: [2, 2, 2],
12
+ position: v(1, 1, 1),
13
+ size: v(2, 2, 2),
13
14
  }
14
15
 
15
16
  expect(intersectsRectangle(rectangle1, rectangle2)).toBe(true)
@@ -17,12 +18,12 @@ test("it should prove that a rectangle crossing another one intersects with it",
17
18
 
18
19
  test("it should prove that a rectangle right on top of another intersects with it", () => {
19
20
  const rectangle1 = {
20
- position: [0, 0, 0],
21
- size: [2, 2, 2],
21
+ position: v(0, 0, 0),
22
+ size: v(2, 2, 2),
22
23
  }
23
24
  const rectangle2 = {
24
- position: [0, 0, 0],
25
- size: [2, 0, 2],
25
+ position: v(0, 0, 0),
26
+ size: v(2, 0, 2),
26
27
  }
27
28
 
28
29
  expect(intersectsRectangle(rectangle1, rectangle2)).toBe(true)
@@ -30,12 +31,12 @@ test("it should prove that a rectangle right on top of another intersects with i
30
31
 
31
32
  test("it should prove that a rectangle not crossing another one does not intersect with it", () => {
32
33
  const rectangle1 = {
33
- position: [0, 0, 0],
34
- size: [2, 2, 2],
34
+ position: v(0, 0, 0),
35
+ size: v(2, 2, 2),
35
36
  }
36
37
  const rectangle2 = {
37
- position: [3, 3, 3],
38
- size: [2, 2, 2],
38
+ position: v(3, 3, 3),
39
+ size: v(2, 2, 2),
39
40
  }
40
41
 
41
42
  expect(intersectsRectangle(rectangle1, rectangle2)).toBe(false)
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @typedef {import("./types").Segment} Segment
3
- * @typedef {import("./types").Point} Point
4
- * @typedef {import("./types").Circle} Circle
2
+ * @typedef {import("./geometry/types.js").Segment} Segment
3
+ * @typedef {import("./geometry/types.js").Point} Point
4
+ * @typedef {import("./geometry/types.js").Circle} Circle
5
5
  */
6
6
 
7
- import { magnitude, setMagnitude } from "../linear-algebra/vector.js"
8
- import { distance, dot, subtract, sum } from "../linear-algebra/vectors.js"
7
+ import { magnitude, setMagnitude } from "./vector.js"
8
+ import { distance, dot, subtract, sum } from "./vectors.js"
9
9
 
10
10
  const BEFORE_SEGMENT = 0
11
11
 
@@ -1,6 +1,7 @@
1
1
  import { expect, test } from "vitest"
2
2
 
3
- import { isClose } from "../numbers.js"
3
+ import { v } from "../v.js"
4
+ import { isClose } from "./numbers.js"
4
5
  import {
5
6
  closestPoint,
6
7
  coefficients,
@@ -21,64 +22,64 @@ expect.extend({
21
22
 
22
23
  test("it should retrieve values of *a*, *b*, and *c* from a segment, so it looks like a line in the form *ax + by + c = 0*", () => {
23
24
  const segment = {
24
- from: [0, 0, 0],
25
- to: [1, 0, 2],
25
+ from: v(0, 0, 0),
26
+ to: v(1, 0, 2),
26
27
  }
27
- const expectedResult = [-2, 1, 0]
28
+ const expectedResult = v(-2, 1, 0)
28
29
 
29
30
  expect(coefficients(segment)).toStrictEqual(expectedResult)
30
31
  })
31
32
 
32
33
  test("it should find the closest point in a segment to a point projectable on it", () => {
33
34
  const segment = {
34
- from: [0, 0, 0],
35
- to: [2, 0, 2],
35
+ from: v(0, 0, 0),
36
+ to: v(2, 0, 2),
36
37
  }
37
- const point = [2, 0, 0]
38
- const expectedResult = [1, 0, 1]
38
+ const point = v(2, 0, 0)
39
+ const expectedResult = v(1, 0, 1)
39
40
 
40
41
  expect(closestPoint(segment, point)).toStrictEqualVector(expectedResult)
41
42
  })
42
43
 
43
44
  test("it should find the closest point as the point itself when resting on the segment", () => {
44
45
  const segment = {
45
- from: [0, 0, 0],
46
- to: [2, 0, 2],
46
+ from: v(0, 0, 0),
47
+ to: v(2, 0, 2),
47
48
  }
48
- const point = [1, 0, 1]
49
- const expectedResult = [1, 0, 1]
49
+ const point = v(1, 0, 1)
50
+ const expectedResult = v(1, 0, 1)
50
51
 
51
52
  expect(closestPoint(segment, point)).toStrictEqualVector(expectedResult)
52
53
  })
53
54
 
54
55
  test("it return the start of a segment when the point is close to its start", () => {
55
56
  const segment = {
56
- from: [0, 0, 0],
57
- to: [3, 0, 4],
57
+ from: v(0, 0, 0),
58
+ to: v(3, 0, 4),
58
59
  }
59
- const point = [-2, 0, 0]
60
- const expectedResult = [0, 0, 0]
60
+ const point = v(-2, 0, 0)
61
+ const expectedResult = v(0, 0, 0)
61
62
 
62
63
  expect(closestPoint(segment, point)).toStrictEqualVector(expectedResult)
63
64
  })
64
65
 
65
66
  test("it should return the end of a segment when the point is close to its end", () => {
66
67
  const segment = {
67
- from: [0, 0, 0],
68
- to: [3, 0, 4],
68
+ from: v(0, 0, 0),
69
+ to: v(3, 0, 4),
69
70
  }
70
- const point = [5, 0, 4]
71
- const expectedResult = [3, 0, 4]
71
+ const point = v(5, 0, 4)
72
+ const expectedResult = v(3, 0, 4)
72
73
 
73
74
  expect(closestPoint(segment, point)).toStrictEqualVector(expectedResult)
74
75
  })
75
76
 
76
77
  test("it should compute the distance between a segment and a point projectable on it", () => {
77
78
  const segment = {
78
- from: [0, 0, 0],
79
- to: [3, 0, 4],
79
+ from: v(0, 0, 0),
80
+ to: v(3, 0, 4),
80
81
  }
81
- const point = [5, 0, 0]
82
+ const point = v(5, 0, 0)
82
83
  const expectedResult = 4
83
84
 
84
85
  expect(distanceFromPoint(segment, point)).toBe(expectedResult)
@@ -86,10 +87,10 @@ test("it should compute the distance between a segment and a point projectable o
86
87
 
87
88
  test("it should compute the distance between a segment and a point resting on it", () => {
88
89
  const segment = {
89
- from: [0, 0, 0],
90
- to: [2, 0, 2],
90
+ from: v(0, 0, 0),
91
+ to: v(2, 0, 2),
91
92
  }
92
- const point = [1, 0, 1]
93
+ const point = v(1, 0, 1)
93
94
  const expectedResult = 0
94
95
 
95
96
  expect(distanceFromPoint(segment, point)).toBeCloseTo(expectedResult)
@@ -97,10 +98,10 @@ test("it should compute the distance between a segment and a point resting on it
97
98
 
98
99
  test("it should compute the distance between a segment and a point close to the start", () => {
99
100
  const segment = {
100
- from: [0, 0, 0],
101
- to: [3, 0, 4],
101
+ from: v(0, 0, 0),
102
+ to: v(3, 0, 4),
102
103
  }
103
- const point = [-2, 0, 0]
104
+ const point = v(-2, 0, 0)
104
105
  const expectedResult = 2
105
106
 
106
107
  expect(distanceFromPoint(segment, point)).toBe(expectedResult)
@@ -108,10 +109,10 @@ test("it should compute the distance between a segment and a point close to the
108
109
 
109
110
  test("it should compute the distance between a segment and a point close to the end", () => {
110
111
  const segment = {
111
- from: [0, 0, 0],
112
- to: [3, 0, 4],
112
+ from: v(0, 0, 0),
113
+ to: v(3, 0, 4),
113
114
  }
114
- const point = [5, 0, 4]
115
+ const point = v(5, 0, 4)
115
116
  const expectedResult = 2
116
117
 
117
118
  expect(distanceFromPoint(segment, point)).toBeCloseTo(expectedResult)
@@ -119,11 +120,11 @@ test("it should compute the distance between a segment and a point close to the
119
120
 
120
121
  test("it should prove that a segment that crosses a circle intersects with it", () => {
121
122
  const segment = {
122
- from: [0, 0, 0],
123
- to: [2, 0, 2],
123
+ from: v(0, 0, 0),
124
+ to: v(2, 0, 2),
124
125
  }
125
126
  const circle = {
126
- position: [1, 0, 1],
127
+ position: v(1, 0, 1),
127
128
  radius: 1,
128
129
  }
129
130
 
@@ -132,11 +133,11 @@ test("it should prove that a segment that crosses a circle intersects with it",
132
133
 
133
134
  test("it should prove that a segment tangent to a circle intersects with it", () => {
134
135
  const segment = {
135
- from: [0, 0, 0],
136
- to: [0, 0, 2],
136
+ from: v(0, 0, 0),
137
+ to: v(0, 0, 2),
137
138
  }
138
139
  const circle = {
139
- position: [1, 0, 1],
140
+ position: v(1, 0, 1),
140
141
  radius: 1,
141
142
  }
142
143
 
@@ -145,11 +146,11 @@ test("it should prove that a segment tangent to a circle intersects with it", ()
145
146
 
146
147
  test("it should prove that a segment inside of a circle intersects with it", () => {
147
148
  const segment = {
148
- from: [0.5, 0, 0.5],
149
- to: [1.5, 0, 1.5],
149
+ from: v(0.5, 0, 0.5),
150
+ to: v(1.5, 0, 1.5),
150
151
  }
151
152
  const circle = {
152
- position: [1, 0, 1],
153
+ position: v(1, 0, 1),
153
154
  radius: 1,
154
155
  }
155
156
 
@@ -158,11 +159,11 @@ test("it should prove that a segment inside of a circle intersects with it", ()
158
159
 
159
160
  test("it should prove that a segment that does not cross a circle does not intersect with it", () => {
160
161
  const segment = {
161
- from: [0, 0, 0],
162
- to: [-2, 0, 2],
162
+ from: v(0, 0, 0),
163
+ to: v(-2, 0, 2),
163
164
  }
164
165
  const circle = {
165
- position: [1, 0, 1],
166
+ position: v(1, 0, 1),
166
167
  radius: 1,
167
168
  }
168
169
 
@@ -171,11 +172,11 @@ test("it should prove that a segment that does not cross a circle does not inter
171
172
 
172
173
  test("it should prove that a segment that reaches outside of a circle does not intersect with it", () => {
173
174
  const segment = {
174
- from: [0, 0, 0],
175
- to: [-1, 0, -2],
175
+ from: v(0, 0, 0),
176
+ to: v(-1, 0, -2),
176
177
  }
177
178
  const circle = {
178
- position: [1, 0, 1],
179
+ position: v(1, 0, 1),
179
180
  radius: 1,
180
181
  }
181
182
 
@@ -1,3 +1,5 @@
1
+ // geometry
2
+
1
3
  export type Point = [number, number, number] // [x, y, z]
2
4
  export type Size = [number, number, number] // [width, height, depth]
3
5
  export type Line = [number, number, number] // [a, b, c]
@@ -21,3 +23,11 @@ export interface Segment {
21
23
  from: Point
22
24
  to: Point
23
25
  }
26
+
27
+ // linear algebra
28
+
29
+ export type Vector = number[]
30
+ export type Vector2 = [number, number]
31
+ export type Vector3 = [number, number, number]
32
+ export type Quaternion = [number, number, number, number]
33
+ export type Vector7 = [number, number, number, number, number, number, number]
@@ -1,23 +1,24 @@
1
1
  /**
2
+ * @typedef {import('./types').Vector} Vector
2
3
  * @typedef {import('./types').Vector2} Vector2
3
4
  * @typedef {import('./types').Vector3} Vector3
4
5
  */
5
6
 
6
- import { isArray } from "../../data-structures/array.js"
7
- import { hypothenuse } from "../geometry/triangle.js"
7
+ import { isArray } from "../data-structures/array.js"
8
+ import { v } from "../v.js"
8
9
  import {
9
10
  abs as nAbs,
10
11
  clamp as nClamp,
11
12
  mod as nMod,
12
13
  snap as nSnap,
13
- } from "../numbers.js"
14
- import { atan2, cos, sin } from "../trigonometry.js"
15
- import { from2D, to2D } from "./2d.js"
14
+ } from "./numbers.js"
16
15
  import { quaternion } from "./quaternion.js"
16
+ import { hypothenuse } from "./triangle.js"
17
+ import { atan2, cos, sin } from "./trigonometry.js"
17
18
  import { cross, sum } from "./vectors.js"
18
19
 
19
- const ZERO_VECTOR = [0, 0, 0] // eslint-disable-line no-magic-numbers
20
- const UNIT_VECTOR = [1, 0, 0] // eslint-disable-line no-magic-numbers
20
+ const ZERO_VECTOR = v(0, 0, 0) // eslint-disable-line no-magic-numbers
21
+ const UNIT_VECTOR = v(1, 0, 0) // eslint-disable-line no-magic-numbers
21
22
 
22
23
  const X = 0
23
24
  const Y = 1
@@ -30,8 +31,9 @@ const DEFAULT_DECIMALS = 0
30
31
 
31
32
  /**
32
33
  * Returns the absolute value of each component in the vector.
33
- * @param {Vector3} vector - The input vector.
34
- * @returns {Vector3} The vector with absolute values.
34
+ *
35
+ * @param {Vector} vector - The input vector.
36
+ * @returns {Vector} The vector with absolute values.
35
37
  */
36
38
  export function abs(vector) {
37
39
  return vector.map(nAbs)
@@ -39,8 +41,9 @@ export function abs(vector) {
39
41
 
40
42
  /**
41
43
  * Calculates the angle of the vector in radians.
42
- * @param {Vector3} vector - The input vector.
43
- * @returns {number} The angle in radians.
44
+ *
45
+ * @param {Vector} vector - The input vector.
46
+ * @returns {number} The angle of the vector in the XZ plane (for 3D) or XY plane (for 2D), in radians.
44
47
  */
45
48
  export function angle(vector) {
46
49
  return atan2(vector[vector.length - LAST_COORDINATE], vector[X])
@@ -48,10 +51,11 @@ export function angle(vector) {
48
51
 
49
52
  /**
50
53
  * Clamps the magnitude of the vector between the given min and max values.
51
- * @param {Vector3} vector - The input vector.
52
- * @param {number} min - The minimum magnitude.
53
- * @param {number} max - The maximum magnitude.
54
- * @returns {Vector3} The clamped vector.
54
+ *
55
+ * @param {Vector} vector - The input vector.
56
+ * @param {number|Vector} min - The minimum magnitude or a vector representing the lower bounds for each component.
57
+ * @param {number|Vector} max - The maximum magnitude or a vector representing the upper bounds for each component.
58
+ * @returns {Vector} The clamped vector.
55
59
  */
56
60
  export function clamp(vector, min, max) {
57
61
  const length = magnitude(vector)
@@ -75,18 +79,20 @@ export function clamp(vector, min, max) {
75
79
 
76
80
  /**
77
81
  * Returns the conjugate of the vector.
78
- * @param {Vector3} vector - The input vector.
79
- * @returns {Vector3} The conjugated vector.
82
+ *
83
+ * @param {Vector} vector - The input vector.
84
+ * @returns {Vector} The conjugated vector.
80
85
  */
81
86
  export function conjugate(vector) {
82
87
  return vector.map((coordinate, index) => (index ? -coordinate : coordinate))
83
88
  }
84
89
 
85
90
  /**
86
- * Creates a vector with the given magnitude and angle.
91
+ * Creates a 3D vector with the given magnitude and angle.
92
+ *
87
93
  * @param {number} magnitude - The magnitude of the vector.
88
94
  * @param {number} angle - The angle of the vector in radians.
89
- * @returns {Vector3} The created vector.
95
+ * @returns {Vector3} The created 3D vector.
90
96
  */
91
97
  export function createVector(magnitude, angle) {
92
98
  return multiply(fromAngle(angle), magnitude)
@@ -94,16 +100,28 @@ export function createVector(magnitude, angle) {
94
100
 
95
101
  /**
96
102
  * Divides each component of the vector by the given scalar.
97
- * @param {Vector3} vector - The input vector.
103
+ *
104
+ * @param {Vector} vector - The input vector.
98
105
  * @param {number} scalar - The scalar value.
99
- * @returns {Vector3} The resulting vector.
106
+ * @returns {Vector} The resulting vector.
100
107
  */
101
108
  export function divide(vector, scalar) {
102
109
  return vector.map((coordinate) => coordinate / scalar)
103
110
  }
104
111
 
105
112
  /**
106
- * Creates a unit vector from the given angle.
113
+ * Converts a 2D vector [x, z] into a 3D vector [x, 0, z].
114
+ *
115
+ * @param {Vector2} vector - A 2D vector represented as [x, z].
116
+ * @returns {Vector3} A 3D vector represented as [x, 0, z].
117
+ */
118
+ export function from2D(vector) {
119
+ const [x, z] = vector
120
+ return [x, NO_Y, z]
121
+ }
122
+
123
+ /**
124
+ * Creates a 3D unit vector from the given angle in the XZ plane.
107
125
  * @param {number} angle - The angle in radians.
108
126
  * @returns {Vector3} The unit vector.
109
127
  */
@@ -111,35 +129,42 @@ export function fromAngle(angle) {
111
129
  return rotate(UNIT_VECTOR, angle)
112
130
  }
113
131
 
114
- export const length = magnitude
115
-
116
132
  /**
117
133
  * Checks if a value is a vector.
134
+ * A vector is an array of numbers. For performance, vectors created with `v()`
135
+ * are tagged and can be identified more quickly.
118
136
  *
119
137
  * @param {*} value - The value to check.
120
138
  * @returns {boolean} True if the value is a vector, false otherwise.
121
139
  */
122
140
  export function isVector(value) {
123
141
  return (
124
- isArray(value) &&
125
- value.every((coordinate) => typeof coordinate === "number")
142
+ value?.__isVector__ ||
143
+ (isArray(value) &&
144
+ value.every((coordinate) => typeof coordinate === "number"))
126
145
  )
127
146
  }
128
147
 
129
148
  /**
130
- * Calculates the magnitude of the vector.
131
- * @param {Vector3} vector - The input vector.
149
+ * Calculates the magnitude (length) of the vector.
150
+ * Alias: `length`.
151
+ *
152
+ * @param {Vector} vector - The input vector.
132
153
  * @returns {number} The magnitude of the vector.
133
154
  */
134
155
  export function magnitude(vector) {
135
156
  return hypothenuse(...vector)
136
157
  }
137
158
 
159
+ export const length = magnitude
160
+
138
161
  /**
139
162
  * Calculates the modulus of each component in the vector with the given divisor.
140
- * @param {Vector3} vector - The input vector.
163
+ * Alias: `remainder`.
164
+ *
165
+ * @param {Vector} vector - The input vector.
141
166
  * @param {number} divisor - The divisor value.
142
- * @returns {Vector3} The resulting vector.
167
+ * @returns {Vector} The resulting vector.
143
168
  */
144
169
  export function mod(vector, divisor) {
145
170
  return vector.map((coordinate) => nMod(coordinate, divisor))
@@ -147,18 +172,25 @@ export function mod(vector, divisor) {
147
172
 
148
173
  /**
149
174
  * Multiplies each component of the vector by the given scalar.
150
- * @param {Vector3} vector - The input vector.
175
+ * Aliases: `scale`, `times`.
176
+ *
177
+ * @param {Vector} vector - The input vector.
151
178
  * @param {number} scalar - The scalar value.
152
- * @returns {Vector3} The resulting vector.
179
+ * @returns {Vector} The resulting vector.
153
180
  */
154
181
  export function multiply(vector, scalar) {
155
182
  return vector.map((coordinate) => coordinate * scalar)
156
183
  }
157
184
 
185
+ export const scale = multiply
186
+
187
+ export const times = multiply
188
+
158
189
  /**
159
190
  * Normalizes the vector to have a magnitude of 1.
160
- * @param {Vector3} vector - The input vector.
161
- * @returns {Vector3} The normalized vector.
191
+ *
192
+ * @param {Vector} vector - The input vector.
193
+ * @returns {Vector} The normalized vector.
162
194
  */
163
195
  export function normalize(vector) {
164
196
  const length = magnitude(vector)
@@ -168,10 +200,12 @@ export function normalize(vector) {
168
200
  export const remainder = mod
169
201
 
170
202
  /**
171
- * Rotates the vector by the given angle.
172
- * @param {Vector3} vector - The input vector.
203
+ * Rotates the vector by the given angle. Handles 2D and 3D vectors.
204
+ * For 3D vectors, rotation is around the Y-axis.
205
+ *
206
+ * @param {Vector} vector - The input vector (2D or 3D).
173
207
  * @param {number} angle - The angle in radians.
174
- * @returns {Vector3} The rotated vector.
208
+ * @returns {Vector} The rotated vector.
175
209
  */
176
210
  export function rotate(vector, angle) {
177
211
  const is2D = vector.length === TWO_COORDINATES
@@ -184,16 +218,9 @@ export function rotate(vector, angle) {
184
218
  }
185
219
 
186
220
  /**
187
- * Scales the vector by the given scalar. Alias of `multiply`.
188
- * @param {Vector3} vector - The input vector.
189
- * @param {number} scalar - The scalar value.
190
- * @returns {Vector3} The resulting vector.
191
- */
192
- export const scale = multiply
193
-
194
- /**
195
- * Sets the angle of the vector while maintaining its magnitude.
196
- * @param {Vector3} vector - The input vector.
221
+ * Sets the angle of the vector in the XZ plane while maintaining its magnitude.
222
+ *
223
+ * @param {Vector} vector - The input vector.
197
224
  * @param {number} angle - The new angle in radians.
198
225
  * @returns {Vector3} The vector with the updated angle.
199
226
  */
@@ -205,14 +232,17 @@ export function setAngle(vector, angle) {
205
232
 
206
233
  /**
207
234
  * Sets the length of the vector while maintaining its direction. Alias of `setMagnitude`.
235
+ * Alias: `setLength`.
208
236
  */
209
237
  export const setLength = setMagnitude
210
238
 
211
239
  /**
212
240
  * Sets the magnitude of the vector while maintaining its direction.
213
- * @param {Vector3} vector - The input vector.
241
+ * Alias: `setLength`.
242
+ *
243
+ * @param {Vector} vector - The input vector.
214
244
  * @param {number} length - The new magnitude.
215
- * @returns {Vector3} The vector with the updated magnitude.
245
+ * @returns {Vector} The vector with the updated magnitude.
216
246
  */
217
247
  export function setMagnitude(vector, length) {
218
248
  const normalized = normalize(vector)
@@ -221,9 +251,10 @@ export function setMagnitude(vector, length) {
221
251
 
222
252
  /**
223
253
  * Shifts the components of the vector by the given index.
224
- * @param {Vector3} vector - The input vector.
254
+ *
255
+ * @param {Vector} vector - The input vector.
225
256
  * @param {number} index - The index to shift by.
226
- * @returns {Vector3} The shifted vector.
257
+ * @returns {Vector} The shifted vector.
227
258
  */
228
259
  export function shift(vector, index) {
229
260
  return [...vector.slice(index), ...vector.slice(X, index)]
@@ -231,18 +262,29 @@ export function shift(vector, index) {
231
262
 
232
263
  /**
233
264
  * Snaps each component of the vector to the nearest multiple of the given precision.
234
- * @param {Vector3} vector - The input vector.
265
+ *
266
+ * @param {Vector} vector - The input vector.
235
267
  * @param {number} [precision=DEFAULT_PRECISION] - The precision value.
236
- * @returns {Vector3} The snapped vector.
268
+ * @returns {Vector} The snapped vector.
237
269
  */
238
270
  export function snap(vector, precision = DEFAULT_PRECISION) {
239
271
  return vector.map((coordinate) => nSnap(coordinate, -precision, precision))
240
272
  }
241
273
 
242
- export const times = multiply
274
+ /**
275
+ * Converts a 3D vector [x, y, z] into a 2D vector [x, z].
276
+ *
277
+ * @param {Vector3} vector - A 3D vector represented as [x, y, z].
278
+ * @returns {Vector2} A 2D vector represented as [x, z].
279
+ */
280
+ export function to2D(vector) {
281
+ const [x, , z] = vector
282
+ return [x, z]
283
+ }
243
284
 
244
285
  /**
245
- * Converts polar coordinates to Cartesian coordinates.
286
+ * Converts 2D polar coordinates to 2D Cartesian coordinates.
287
+ *
246
288
  * @param {Vector2} vector - The polar coordinates [magnitude, angle].
247
289
  * @returns {Vector2} The Cartesian coordinates [x, y].
248
290
  */
@@ -251,9 +293,10 @@ export function toCartesian([magnitude, angle]) {
251
293
  }
252
294
 
253
295
  /**
254
- * Converts a vector to cylindrical coordinates.
255
- * @param {Vector2} vector - The input vector.
256
- * @returns {Vector2} The cylindrical coordinates [radius, theta, z].
296
+ * Converts a 3D cartesian vector to cylindrical coordinates.
297
+ *
298
+ * @param {Vector3} vector - The input vector [x, y, z].
299
+ * @returns {Vector3} The cylindrical coordinates [radius, theta, z].
257
300
  */
258
301
  export function toCylindrical(vector) {
259
302
  const radius = magnitude(vector)
@@ -262,8 +305,9 @@ export function toCylindrical(vector) {
262
305
  }
263
306
 
264
307
  /**
265
- * Converts a vector to polar coordinates.
266
- * @param {Vector2} vector - The input vector.
308
+ * Converts a 2D cartesian vector to 2D polar coordinates.
309
+ *
310
+ * @param {Vector2} vector - The input vector [x, y].
267
311
  * @returns {Vector2} The polar coordinates [magnitude, angle].
268
312
  */
269
313
  export function toPolar(vector) {
@@ -272,7 +316,8 @@ export function toPolar(vector) {
272
316
 
273
317
  /**
274
318
  * Converts a vector to a string representation.
275
- * @param {Vector3} vector - The input vector.
319
+ *
320
+ * @param {Vector} vector - The input vector.
276
321
  * @param {number} [decimals=DEFAULT_DECIMALS] - The number of decimal places.
277
322
  * @returns {string} The string representation of the vector.
278
323
  */
@@ -309,8 +354,9 @@ export function toSpherical(vector) {
309
354
  }
310
355
 
311
356
  /**
312
- * Creates a unit vector with the given angle.
313
- * @param {number} angle - The angle in radians.
357
+ * Creates a 3D unit vector in the XZ plane with the given angle.
358
+ *
359
+ * @param {number} [angle=0] - The angle in radians.
314
360
  * @returns {Vector3} The unit vector.
315
361
  */
316
362
  export function unit(angle) {
@@ -322,7 +368,8 @@ export function unit(angle) {
322
368
  }
323
369
 
324
370
  /**
325
- * Creates a zero vector.
371
+ * Creates a zero vector of 3 dimensions.
372
+ *
326
373
  * @returns {Vector3} The zero vector.
327
374
  */
328
375
  export function zero() {
@@ -330,7 +377,8 @@ export function zero() {
330
377
  }
331
378
 
332
379
  /**
333
- * Rotates the vector using a quaternion.
380
+ * Rotates a 3D vector around the Y-axis using a quaternion.
381
+ *
334
382
  * @param {Vector3} vector - The input vector.
335
383
  * @param {number} angle - The angle in radians.
336
384
  * @returns {Vector3} The rotated vector.