@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.
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/algorithms/decision-tree.test.js +7 -6
- package/src/algorithms/index.js +4 -0
- package/src/algorithms/path-finding.js +2 -2
- package/src/data-structures/index.js +10 -0
- package/src/functions/index.js +4 -0
- package/src/index.js +8 -0
- package/src/math/{geometry/circle.js → circle.js} +6 -6
- package/src/math/{geometry/circle.test.js → circle.test.js} +23 -22
- package/src/math/{geometry/hitmask.test.js → hitmask.test.js} +16 -15
- package/src/math/index.js +35 -0
- package/src/math/{geometry/line.js → line.js} +4 -4
- package/src/math/{geometry/line.test.js → line.test.js} +11 -10
- package/src/math/{geometry/point.js → point.js} +5 -5
- package/src/math/{geometry/point.test.js → point.test.js} +23 -22
- package/src/math/{linear-algebra/quaternion.js → quaternion.js} +3 -2
- package/src/math/{linear-algebra/quaternion.test.js → quaternion.test.js} +1 -1
- package/src/math/{linear-algebra/quaternions.test.js → quaternions.test.js} +1 -1
- package/src/math/{geometry/rectangle.js → rectangle.js} +3 -3
- package/src/math/{geometry/rectangle.test.js → rectangle.test.js} +13 -12
- package/src/math/{geometry/segment.js → segment.js} +5 -5
- package/src/math/{geometry/segment.test.js → segment.test.js} +48 -47
- package/src/math/{geometry/types.d.ts → types.d.ts} +10 -0
- package/src/math/{linear-algebra/vector.js → vector.js} +23 -32
- package/src/math/{linear-algebra/vector.test.js → vector.test.js} +42 -35
- package/src/math/{linear-algebra/vectors.test.js → vectors.test.js} +12 -30
- package/src/physics/acceleration.js +3 -3
- package/src/physics/friction.js +2 -2
- package/src/physics/friction.test.js +7 -6
- package/src/physics/gravity.js +2 -2
- package/src/physics/gravity.test.js +10 -9
- package/src/physics/index.js +7 -0
- package/src/physics/jump.js +1 -1
- package/src/physics/velocity.js +3 -3
- package/src/v.js +18 -0
- package/src/math/linear-algebra/types.d.ts +0 -5
- /package/src/math/{geometry/hitmask.js → hitmask.js} +0 -0
- /package/src/math/{linear-algebra/quaternions.js → quaternions.js} +0 -0
- /package/src/math/{geometry/triangle.js → triangle.js} +0 -0
- /package/src/math/{geometry/triangle.test.js → triangle.test.js} +0 -0
- /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:
|
|
8
|
-
size:
|
|
8
|
+
position: v(0, 0, 0),
|
|
9
|
+
size: v(2, 2, 2),
|
|
9
10
|
}
|
|
10
11
|
const rectangle2 = {
|
|
11
|
-
position:
|
|
12
|
-
size:
|
|
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:
|
|
21
|
-
size:
|
|
21
|
+
position: v(0, 0, 0),
|
|
22
|
+
size: v(2, 2, 2),
|
|
22
23
|
}
|
|
23
24
|
const rectangle2 = {
|
|
24
|
-
position:
|
|
25
|
-
size:
|
|
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:
|
|
34
|
-
size:
|
|
34
|
+
position: v(0, 0, 0),
|
|
35
|
+
size: v(2, 2, 2),
|
|
35
36
|
}
|
|
36
37
|
const rectangle2 = {
|
|
37
|
-
position:
|
|
38
|
-
size:
|
|
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 "
|
|
8
|
-
import { distance, dot, subtract, sum } from "
|
|
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 {
|
|
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:
|
|
25
|
-
to:
|
|
25
|
+
from: v(0, 0, 0),
|
|
26
|
+
to: v(1, 0, 2),
|
|
26
27
|
}
|
|
27
|
-
const expectedResult =
|
|
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:
|
|
35
|
-
to:
|
|
35
|
+
from: v(0, 0, 0),
|
|
36
|
+
to: v(2, 0, 2),
|
|
36
37
|
}
|
|
37
|
-
const point =
|
|
38
|
-
const expectedResult =
|
|
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:
|
|
46
|
-
to:
|
|
46
|
+
from: v(0, 0, 0),
|
|
47
|
+
to: v(2, 0, 2),
|
|
47
48
|
}
|
|
48
|
-
const point =
|
|
49
|
-
const expectedResult =
|
|
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:
|
|
57
|
-
to:
|
|
57
|
+
from: v(0, 0, 0),
|
|
58
|
+
to: v(3, 0, 4),
|
|
58
59
|
}
|
|
59
|
-
const point =
|
|
60
|
-
const expectedResult =
|
|
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:
|
|
68
|
-
to:
|
|
68
|
+
from: v(0, 0, 0),
|
|
69
|
+
to: v(3, 0, 4),
|
|
69
70
|
}
|
|
70
|
-
const point =
|
|
71
|
-
const expectedResult =
|
|
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:
|
|
79
|
-
to:
|
|
79
|
+
from: v(0, 0, 0),
|
|
80
|
+
to: v(3, 0, 4),
|
|
80
81
|
}
|
|
81
|
-
const point =
|
|
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:
|
|
90
|
-
to:
|
|
90
|
+
from: v(0, 0, 0),
|
|
91
|
+
to: v(2, 0, 2),
|
|
91
92
|
}
|
|
92
|
-
const point =
|
|
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:
|
|
101
|
-
to:
|
|
101
|
+
from: v(0, 0, 0),
|
|
102
|
+
to: v(3, 0, 4),
|
|
102
103
|
}
|
|
103
|
-
const point =
|
|
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:
|
|
112
|
-
to:
|
|
112
|
+
from: v(0, 0, 0),
|
|
113
|
+
to: v(3, 0, 4),
|
|
113
114
|
}
|
|
114
|
-
const point =
|
|
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:
|
|
123
|
-
to:
|
|
123
|
+
from: v(0, 0, 0),
|
|
124
|
+
to: v(2, 0, 2),
|
|
124
125
|
}
|
|
125
126
|
const circle = {
|
|
126
|
-
position:
|
|
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:
|
|
136
|
-
to:
|
|
136
|
+
from: v(0, 0, 0),
|
|
137
|
+
to: v(0, 0, 2),
|
|
137
138
|
}
|
|
138
139
|
const circle = {
|
|
139
|
-
position:
|
|
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:
|
|
149
|
-
to:
|
|
149
|
+
from: v(0.5, 0, 0.5),
|
|
150
|
+
to: v(1.5, 0, 1.5),
|
|
150
151
|
}
|
|
151
152
|
const circle = {
|
|
152
|
-
position:
|
|
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:
|
|
162
|
-
to:
|
|
162
|
+
from: v(0, 0, 0),
|
|
163
|
+
to: v(-2, 0, 2),
|
|
163
164
|
}
|
|
164
165
|
const circle = {
|
|
165
|
-
position:
|
|
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:
|
|
175
|
-
to:
|
|
175
|
+
from: v(0, 0, 0),
|
|
176
|
+
to: v(-1, 0, -2),
|
|
176
177
|
}
|
|
177
178
|
const circle = {
|
|
178
|
-
position:
|
|
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 "
|
|
8
|
-
import {
|
|
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 "
|
|
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 =
|
|
20
|
-
const UNIT_VECTOR =
|
|
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
|
-
|
|
142
|
-
|
|
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 {
|
|
4
|
-
import {
|
|
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 =
|
|
37
|
-
const expectedResult =
|
|
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 =
|
|
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 =
|
|
85
|
-
const expectedResult =
|
|
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 =
|
|
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 =
|
|
99
|
+
const vector = v(4, 8, 12)
|
|
100
100
|
const scalar = 4
|
|
101
|
-
const expectedResult =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 =
|
|
142
|
+
const vector = v(10, 12, -18)
|
|
142
143
|
const divisor = 12
|
|
143
|
-
const expectedResult =
|
|
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 =
|
|
150
|
+
const vector = v(1, 2, 3)
|
|
150
151
|
const scalar = 4
|
|
151
|
-
const expectedResult =
|
|
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 =
|
|
180
|
+
const vector = v(1, 0, 0)
|
|
180
181
|
const angle = 0
|
|
181
|
-
const expectedResult =
|
|
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 =
|
|
188
|
+
const vector = v(1, 0, 0)
|
|
188
189
|
const angle = pi() / 4
|
|
189
|
-
const expectedResult =
|
|
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 =
|
|
196
|
+
const vector = v(-1, 0, 0)
|
|
196
197
|
const angle = pi() / 4
|
|
197
|
-
const expectedResult =
|
|
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
|
|
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 =
|
|
235
|
+
const vector = v(1, 1.5, 1.7)
|
|
235
236
|
const precision = 1
|
|
236
|
-
const expectedResult =
|
|
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 =
|
|
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 =
|
|
257
|
-
const expectedResult =
|
|
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 =
|
|
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(
|
|
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
|
|
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(
|
|
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 =
|
|
313
|
+
const expectedResult = v(0, 0, 0)
|
|
307
314
|
|
|
308
315
|
expect(zero()).toStrictEqual(expectedResult)
|
|
309
316
|
})
|