@inglorious/utils 2.3.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 (42) 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} +23 -32
  26. package/src/math/{linear-algebra/vector.test.js → vector.test.js} +42 -35
  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/types.d.ts +0 -5
  38. /package/src/math/{geometry/hitmask.js → hitmask.js} +0 -0
  39. /package/src/math/{linear-algebra/quaternions.js → quaternions.js} +0 -0
  40. /package/src/math/{geometry/triangle.js → triangle.js} +0 -0
  41. /package/src/math/{geometry/triangle.test.js → triangle.test.js} +0 -0
  42. /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]
@@ -4,20 +4,21 @@
4
4
  * @typedef {import('./types').Vector3} Vector3
5
5
  */
6
6
 
7
- import { isArray } from "../../data-structures/array.js"
8
- import { hypothenuse } from "../geometry/triangle.js"
7
+ import { isArray } from "../data-structures/array.js"
8
+ import { v } from "../v.js"
9
9
  import {
10
10
  abs as nAbs,
11
11
  clamp as nClamp,
12
12
  mod as nMod,
13
13
  snap as nSnap,
14
- } from "../numbers.js"
15
- import { atan2, cos, sin } from "../trigonometry.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
@@ -128,23 +129,25 @@ export function fromAngle(angle) {
128
129
  return rotate(UNIT_VECTOR, angle)
129
130
  }
130
131
 
131
- export const length = magnitude
132
-
133
132
  /**
134
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.
135
136
  *
136
137
  * @param {*} value - The value to check.
137
138
  * @returns {boolean} True if the value is a vector, false otherwise.
138
139
  */
139
140
  export function isVector(value) {
140
141
  return (
141
- isArray(value) &&
142
- value.every((coordinate) => typeof coordinate === "number")
142
+ value?.__isVector__ ||
143
+ (isArray(value) &&
144
+ value.every((coordinate) => typeof coordinate === "number"))
143
145
  )
144
146
  }
145
147
 
146
148
  /**
147
149
  * Calculates the magnitude (length) of the vector.
150
+ * Alias: `length`.
148
151
  *
149
152
  * @param {Vector} vector - The input vector.
150
153
  * @returns {number} The magnitude of the vector.
@@ -153,8 +156,11 @@ export function magnitude(vector) {
153
156
  return hypothenuse(...vector)
154
157
  }
155
158
 
159
+ export const length = magnitude
160
+
156
161
  /**
157
162
  * Calculates the modulus of each component in the vector with the given divisor.
163
+ * Alias: `remainder`.
158
164
  *
159
165
  * @param {Vector} vector - The input vector.
160
166
  * @param {number} divisor - The divisor value.
@@ -166,6 +172,7 @@ export function mod(vector, divisor) {
166
172
 
167
173
  /**
168
174
  * Multiplies each component of the vector by the given scalar.
175
+ * Aliases: `scale`, `times`.
169
176
  *
170
177
  * @param {Vector} vector - The input vector.
171
178
  * @param {number} scalar - The scalar value.
@@ -175,6 +182,10 @@ export function multiply(vector, scalar) {
175
182
  return vector.map((coordinate) => coordinate * scalar)
176
183
  }
177
184
 
185
+ export const scale = multiply
186
+
187
+ export const times = multiply
188
+
178
189
  /**
179
190
  * Normalizes the vector to have a magnitude of 1.
180
191
  *
@@ -206,15 +217,6 @@ export function rotate(vector, angle) {
206
217
  return is2D ? to2D(result) : result
207
218
  }
208
219
 
209
- /**
210
- * Scales the vector by the given scalar. Alias of `multiply`.
211
- *
212
- * @param {Vector} vector - The input vector.
213
- * @param {number} scalar - The scalar value.
214
- * @returns {Vector} The resulting vector.
215
- */
216
- export const scale = multiply
217
-
218
220
  /**
219
221
  * Sets the angle of the vector in the XZ plane while maintaining its magnitude.
220
222
  *
@@ -230,11 +232,13 @@ export function setAngle(vector, angle) {
230
232
 
231
233
  /**
232
234
  * Sets the length of the vector while maintaining its direction. Alias of `setMagnitude`.
235
+ * Alias: `setLength`.
233
236
  */
234
237
  export const setLength = setMagnitude
235
238
 
236
239
  /**
237
240
  * Sets the magnitude of the vector while maintaining its direction.
241
+ * Alias: `setLength`.
238
242
  *
239
243
  * @param {Vector} vector - The input vector.
240
244
  * @param {number} length - The new magnitude.
@@ -267,8 +271,6 @@ export function snap(vector, precision = DEFAULT_PRECISION) {
267
271
  return vector.map((coordinate) => nSnap(coordinate, -precision, precision))
268
272
  }
269
273
 
270
- export const times = multiply
271
-
272
274
  /**
273
275
  * Converts a 3D vector [x, y, z] into a 2D vector [x, z].
274
276
  *
@@ -365,17 +367,6 @@ export function unit(angle) {
365
367
  return setAngle(UNIT_VECTOR, angle)
366
368
  }
367
369
 
368
- /**
369
- * A utility function to create a vector from a list of coordinates.
370
- * This is a shorthand for `[x, y, z, ...]`.
371
- *
372
- * @param {...number} coords - The coordinates of the vector.
373
- * @returns {Vector} The created vector.
374
- */
375
- export function v(...coords) {
376
- return coords
377
- }
378
-
379
370
  /**
380
371
  * Creates a zero vector of 3 dimensions.
381
372
  *
@@ -1,7 +1,8 @@
1
1
  import { expect, test } from "vitest"
2
2
 
3
- import { sqrt } from "../numbers.js"
4
- import { cos, pi, sin } from "../trigonometry.js"
3
+ import { v } from "../v.js"
4
+ import { sqrt } from "./numbers.js"
5
+ import { cos, pi, sin } from "./trigonometry.js"
5
6
  import {
6
7
  abs,
7
8
  angle,
@@ -28,13 +29,12 @@ import {
28
29
  toSpherical,
29
30
  toString,
30
31
  unit,
31
- v,
32
32
  zero,
33
33
  } from "./vector.js"
34
34
 
35
35
  test("it should compute the absolute value of a vector's coordinates", () => {
36
- const vector = [-2, 0, 3]
37
- const expectedResult = [2, 0, 3]
36
+ const vector = v(-2, 0, 3)
37
+ const expectedResult = v(2, 0, 3)
38
38
 
39
39
  expect(abs(vector)).toStrictEqual(expectedResult)
40
40
  })
@@ -47,7 +47,7 @@ test("it should compute the angle of a 2D vector", () => {
47
47
  })
48
48
 
49
49
  test("it should compute the angle of a 3D vector", () => {
50
- const vector = [1, 0, 1]
50
+ const vector = v(1, 0, 1)
51
51
  const expectedResult = pi() / 4
52
52
 
53
53
  expect(angle(vector)).toBe(expectedResult)
@@ -81,8 +81,8 @@ test("it should clamp the magnitude of a vector to the values of other vector bo
81
81
  })
82
82
 
83
83
  test("it should conjugate a vector", () => {
84
- const vector = [1, 2, 3]
85
- const expectedResult = [1, -2, -3]
84
+ const vector = v(1, 2, 3)
85
+ const expectedResult = v(1, -2, -3)
86
86
 
87
87
  expect(conjugate(vector)).toStrictEqual(expectedResult)
88
88
  })
@@ -90,29 +90,29 @@ test("it should conjugate a vector", () => {
90
90
  test("it should create a 3D vector given its magnitude and angle", () => {
91
91
  const magnitude = sqrt(2)
92
92
  const angle = pi() / 4
93
- const expectedResult = [1, -0, 1.0000000000000002] // close to [1, 0, 1]
93
+ const expectedResult = v(1, -0, 1.0000000000000002) // close to v(1, 0, 1)
94
94
 
95
95
  expect(createVector(magnitude, angle)).toStrictEqual(expectedResult)
96
96
  })
97
97
 
98
98
  test("it should divide a vector by a scalar", () => {
99
- const vector = [4, 8, 12]
99
+ const vector = v(4, 8, 12)
100
100
  const scalar = 4
101
- const expectedResult = [1, 2, 3]
101
+ const expectedResult = v(1, 2, 3)
102
102
 
103
103
  expect(divide(vector, scalar)).toStrictEqual(expectedResult)
104
104
  })
105
105
 
106
106
  test("it should build a 3D vector from a 2D one", () => {
107
107
  const vector = [3, 4]
108
- const expectedResult = [3, 0, 4]
108
+ const expectedResult = v(3, 0, 4)
109
109
 
110
110
  expect(from2D(vector)).toStrictEqual(expectedResult)
111
111
  })
112
112
 
113
113
  test("it should create a 3D unit vector from an angle", () => {
114
114
  const angle = pi() / 4
115
- const expectedResult = [0.7071067811865475, -0, 0.7071067811865476] // close to [cos(angle), 0, sin(angle)]
115
+ const expectedResult = v(0.7071067811865475, -0, 0.7071067811865476) // close to [cos(angle), 0, sin(angle)]
116
116
 
117
117
  expect(fromAngle(angle)).toStrictEqual(expectedResult)
118
118
  })
@@ -125,8 +125,9 @@ test("it should compute the magnitude of a vector (aka length)", () => {
125
125
  })
126
126
 
127
127
  test("it should check if a value is a vector", () => {
128
- expect(isVector([1, 2, 3])).toBe(true)
128
+ expect(isVector(v(1, 2, 3))).toBe(true)
129
129
  expect(isVector([])).toBe(true)
130
+ expect(isVector(v(1, 2, 3))).toBe(true)
130
131
  })
131
132
 
132
133
  test("it should check if a value is not a vector", () => {
@@ -138,17 +139,17 @@ test("it should check if a value is not a vector", () => {
138
139
  })
139
140
 
140
141
  test("it should apply the mod operator (aka remainder) on a vector", () => {
141
- const vector = [10, 12, -18]
142
+ const vector = v(10, 12, -18)
142
143
  const divisor = 12
143
- const expectedResult = [10, 0, 6]
144
+ const expectedResult = v(10, 0, 6)
144
145
 
145
146
  expect(mod(vector, divisor)).toStrictEqual(expectedResult)
146
147
  })
147
148
 
148
149
  test("it should multiply a vector with a scalar (aka times)", () => {
149
- const vector = [1, 2, 3]
150
+ const vector = v(1, 2, 3)
150
151
  const scalar = 4
151
- const expectedResult = [4, 8, 12]
152
+ const expectedResult = v(4, 8, 12)
152
153
 
153
154
  expect(multiply(vector, scalar)).toStrictEqual(expectedResult)
154
155
  })
@@ -176,32 +177,32 @@ test("it should rotate a 2D vector by a certain angle", () => {
176
177
  })
177
178
 
178
179
  test("it should not rotate a vector when the angle is zero", () => {
179
- const vector = [1, 0, 0]
180
+ const vector = v(1, 0, 0)
180
181
  const angle = 0
181
- const expectedResult = [1, 0, 0]
182
+ const expectedResult = v(1, 0, 0)
182
183
 
183
184
  expect(rotate(vector, angle)).toStrictEqual(expectedResult)
184
185
  })
185
186
 
186
187
  test("it should rotate a vector by a certain angle", () => {
187
- const vector = [1, 0, 0]
188
+ const vector = v(1, 0, 0)
188
189
  const angle = pi() / 4
189
- const expectedResult = [0.7071067811865475, -0, 0.7071067811865476] // close to [cos(pi/4), 0, sin(pi/4)]
190
+ const expectedResult = v(0.7071067811865475, -0, 0.7071067811865476) // close to [cos(pi/4), 0, sin(pi/4)]
190
191
 
191
192
  expect(rotate(vector, angle)).toStrictEqual(expectedResult)
192
193
  })
193
194
 
194
195
  test("it should rotate a vector that faces left by a certain angle", () => {
195
- const vector = [-1, 0, 0]
196
+ const vector = v(-1, 0, 0)
196
197
  const angle = pi() / 4
197
- const expectedResult = [-0.7071067811865475, -0, -0.7071067811865476] // close to [cos(-3/4pi), 0, sin(-3/4pi)]
198
+ const expectedResult = v(-0.7071067811865475, -0, -0.7071067811865476) // close to [cos(-3/4pi), 0, sin(-3/4pi)]
198
199
 
199
200
  expect(rotate(vector, angle)).toStrictEqual(expectedResult)
200
201
  })
201
202
 
202
203
  test("it should change the angle of a vector", () => {
203
204
  const vector = [cos(pi() / 4), 0, sin(pi() / 4)]
204
- const expectedResult = [6.123233995736766e-17, 0, 1] // close to [0, 0, 1]
205
+ const expectedResult = [6.123233995736766e-17, 0, 1] // close to v(0, 0, 1)
205
206
 
206
207
  expect(setAngle(vector, 1.5707963267948966)).toStrictEqual(expectedResult)
207
208
  })
@@ -231,15 +232,15 @@ test("it should shift a vector at a certain index", () => {
231
232
  })
232
233
 
233
234
  test("it should snap a floating vector to a certain precision", () => {
234
- const vector = [1, 1.5, 1.7]
235
+ const vector = v(1, 1.5, 1.7)
235
236
  const precision = 1
236
- const expectedResult = [1, 1, 2]
237
+ const expectedResult = v(1, 1, 2)
237
238
 
238
239
  expect(snap(vector, precision)).toStrictEqual(expectedResult)
239
240
  })
240
241
 
241
242
  test("it should build a 2D vector from a 3D one", () => {
242
- const vector = [3, 0, 4]
243
+ const vector = v(3, 0, 4)
243
244
  const expectedResult = [3, 4]
244
245
 
245
246
  expect(to2D(vector)).toStrictEqual(expectedResult)
@@ -253,8 +254,8 @@ test("it should convert a 2D polar vector to cartesian coordinates", () => {
253
254
  })
254
255
 
255
256
  test("it should convert a 3D cartesian vector to cylindrical coordinates", () => {
256
- const vector = [1, 1, 1]
257
- const expectedResult = [1.2247448713915892, 1.224744871391589, 1]
257
+ const vector = v(1, 1, 1)
258
+ const expectedResult = v(1.2247448713915892, 1.224744871391589, 1)
258
259
 
259
260
  expect(toCylindrical(vector)).toStrictEqual(expectedResult)
260
261
  })
@@ -267,7 +268,7 @@ test("it should convert a 2D cartesian vector to polar coordinates", () => {
267
268
  })
268
269
 
269
270
  test("it should convert a 3D cartesian vector to spherical coordinates", () => {
270
- const vector = [1, 1, 1]
271
+ const vector = v(1, 1, 1)
271
272
  const expectedResult = [sqrt(3), Math.acos(1 / sqrt(3)), pi() / 4]
272
273
 
273
274
  expect(toSpherical(vector)).toStrictEqual(expectedResult)
@@ -289,21 +290,27 @@ test("it should create a string representation of a float vector", () => {
289
290
  })
290
291
 
291
292
  test("it should create a unit vector oriented on the X-axis", () => {
292
- expect(unit()).toStrictEqual([1, 0, 0])
293
+ expect(unit()).toStrictEqual(v(1, 0, 0))
293
294
  })
294
295
 
295
296
  test("it should create a unit vector oriented on the Z-axis", () => {
296
- expect(unit(pi() / 2)).toStrictEqual([6.123233995736766e-17, 0, 1]) // close to [0, 0, 1]
297
+ expect(unit(pi() / 2)).toStrictEqual([6.123233995736766e-17, 0, 1]) // close to v(0, 0, 1)
297
298
  })
298
299
 
299
300
  test("it should create a vector from a list of coordinates", () => {
300
- expect(v(1, 2, 3)).toStrictEqual([1, 2, 3])
301
+ expect(v(1, 2, 3)).toStrictEqual(v(1, 2, 3))
301
302
  expect(v()).toStrictEqual([])
302
303
  expect(v(0, -5.5)).toStrictEqual([0, -5.5])
303
304
  })
304
305
 
306
+ test("it should create a vector with a __isVector__ property", () => {
307
+ const vector = v(1, 2, 3)
308
+ expect(vector).toStrictEqual(v(1, 2, 3))
309
+ expect(vector.__isVector__).toBe(true)
310
+ })
311
+
305
312
  test("it should create a 3D zero vector", () => {
306
- const expectedResult = [0, 0, 0]
313
+ const expectedResult = v(0, 0, 0)
307
314
 
308
315
  expect(zero()).toStrictEqual(expectedResult)
309
316
  })