@benev/math 0.0.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 (48) hide show
  1. package/license +23 -0
  2. package/package.json +41 -0
  3. package/readme.md +3 -0
  4. package/s/concepts/angles.ts +74 -0
  5. package/s/concepts/circular.ts +72 -0
  6. package/s/concepts/noise.ts +23 -0
  7. package/s/concepts/quat.ts +131 -0
  8. package/s/concepts/randy.ts +116 -0
  9. package/s/concepts/scalar.ts +224 -0
  10. package/s/concepts/spline.ts +88 -0
  11. package/s/concepts/vec2.ts +392 -0
  12. package/s/concepts/vec3.ts +439 -0
  13. package/s/concepts/vec4.ts +74 -0
  14. package/s/index.ts +12 -0
  15. package/x/concepts/angles.d.ts +29 -0
  16. package/x/concepts/angles.js +62 -0
  17. package/x/concepts/angles.js.map +1 -0
  18. package/x/concepts/circular.d.ts +17 -0
  19. package/x/concepts/circular.js +70 -0
  20. package/x/concepts/circular.js.map +1 -0
  21. package/x/concepts/noise.d.ts +9 -0
  22. package/x/concepts/noise.js +20 -0
  23. package/x/concepts/noise.js.map +1 -0
  24. package/x/concepts/quat.d.ts +35 -0
  25. package/x/concepts/quat.js +110 -0
  26. package/x/concepts/quat.js.map +1 -0
  27. package/x/concepts/randy.d.ts +39 -0
  28. package/x/concepts/randy.js +95 -0
  29. package/x/concepts/randy.js.map +1 -0
  30. package/x/concepts/scalar.d.ts +51 -0
  31. package/x/concepts/scalar.js +219 -0
  32. package/x/concepts/scalar.js.map +1 -0
  33. package/x/concepts/spline.d.ts +9 -0
  34. package/x/concepts/spline.js +59 -0
  35. package/x/concepts/spline.js.map +1 -0
  36. package/x/concepts/vec2.d.ts +114 -0
  37. package/x/concepts/vec2.js +314 -0
  38. package/x/concepts/vec2.js.map +1 -0
  39. package/x/concepts/vec3.d.ts +117 -0
  40. package/x/concepts/vec3.js +357 -0
  41. package/x/concepts/vec3.js.map +1 -0
  42. package/x/concepts/vec4.d.ts +21 -0
  43. package/x/concepts/vec4.js +62 -0
  44. package/x/concepts/vec4.js.map +1 -0
  45. package/x/importmap.json +9 -0
  46. package/x/index.d.ts +10 -0
  47. package/x/index.js +11 -0
  48. package/x/index.js.map +1 -0
@@ -0,0 +1,439 @@
1
+
2
+ import {Scalar} from "./scalar.js"
3
+
4
+ export type Vec3Array = [number, number, number]
5
+ export type Xyz = {x: number, y: number, z: number}
6
+
7
+ /** https://github.com/microsoft/TypeScript/issues/5863 */
8
+ type TsHack<T> = {new(...a: ConstructorParameters<typeof Vec3>): T}
9
+
10
+ export class Vec3 {
11
+ constructor(
12
+ public x: number,
13
+ public y: number,
14
+ public z: number,
15
+ ) {}
16
+
17
+ ///////////////////////////////////////////////////////////////////////
18
+
19
+ static new<T extends Vec3>(this: TsHack<T>, x: number, y: number, z: number) {
20
+ return new this(x, y, z)
21
+ }
22
+
23
+ static zero<T extends Vec3>(this: TsHack<T>) {
24
+ return new this(0, 0, 0)
25
+ }
26
+
27
+ static all<T extends Vec3>(this: TsHack<T>, value: number) {
28
+ return new this(value, value, value)
29
+ }
30
+
31
+ static array<T extends Vec3>(this: TsHack<T>, v: Vec3Array) {
32
+ return new this(...v)
33
+ }
34
+
35
+ static import<T extends Vec3>(this: TsHack<T>, {x, y, z}: Xyz): Vec3 {
36
+ return new this(x, y, z)
37
+ }
38
+
39
+ static from(v: Vec3Array | Xyz) {
40
+ return Array.isArray(v)
41
+ ? this.array(v)
42
+ : this.import(v)
43
+ }
44
+
45
+ static magnitudeSquared(x: number, y: number, z: number) {
46
+ return (x ** 2) + (y ** 2) + (z ** 2)
47
+ }
48
+
49
+ static magnitude(x: number, y: number, z: number) {
50
+ return Math.sqrt(this.magnitudeSquared(x, y, z))
51
+ }
52
+
53
+ static average(...vecs: Xyz[]) {
54
+ return this.zero()
55
+ .add(...vecs)
56
+ .divideBy(vecs.length)
57
+ }
58
+
59
+ static min(...vecs: Vec3[]) {
60
+ return new Vec3(
61
+ Math.min(...vecs.map(v => v.x)),
62
+ Math.min(...vecs.map(v => v.y)),
63
+ Math.min(...vecs.map(v => v.z)),
64
+ )
65
+ }
66
+
67
+ static max(...vecs: Vec3[]) {
68
+ return new Vec3(
69
+ Math.max(...vecs.map(v => v.x)),
70
+ Math.max(...vecs.map(v => v.y)),
71
+ Math.max(...vecs.map(v => v.z)),
72
+ )
73
+ }
74
+
75
+ static hexColor(hex: string): Vec3 {
76
+ if (hex.startsWith("#") && hex.length === 7) {
77
+ const r = parseInt(hex.slice(1, 3), 16) / 255
78
+ const g = parseInt(hex.slice(3, 5), 16) / 255
79
+ const b = parseInt(hex.slice(5, 7), 16) / 255
80
+ return new this(r, g, b)
81
+ } else {
82
+ throw new Error("invalid hex color format")
83
+ }
84
+ }
85
+
86
+ ///////////////////////////////////////////////////////////////////////
87
+
88
+ clone() {
89
+ return new Vec3(this.x, this.y, this.z)
90
+ }
91
+
92
+ array(): Vec3Array {
93
+ return [this.x, this.y, this.z]
94
+ }
95
+
96
+ toString() {
97
+ return `(Vec3 x${this.x.toFixed(2)}, y${this.y.toFixed(2)}, z${this.z.toFixed(2)})`
98
+ }
99
+
100
+ set_(x: number, y: number, z: number) {
101
+ this.x = x
102
+ this.y = y
103
+ this.z = z
104
+ return this
105
+ }
106
+
107
+ set({x, y, z}: Xyz) {
108
+ this.x = x
109
+ this.y = y
110
+ this.z = z
111
+ return this
112
+ }
113
+
114
+ ///////////////////////////////////////////////////////////////////////
115
+
116
+ magnitudeSquared() {
117
+ return Vec3.magnitudeSquared(this.x, this.y, this.z)
118
+ }
119
+
120
+ magnitude() {
121
+ return Vec3.magnitude(this.x, this.y, this.z)
122
+ }
123
+
124
+ hexColor() {
125
+ const to255 = (val: number) => Math.round(val * 255)
126
+ const toHex = (val: number) => to255(val).toString(16).padStart(2, '0')
127
+ return `#${toHex(this.x)}${toHex(this.y)}${toHex(this.z)}`
128
+ }
129
+
130
+ ///////////////////////////////////////////////////////////////////////
131
+
132
+ equals_(x: number, y: number, z: number) {
133
+ return (
134
+ this.x === x &&
135
+ this.y === y &&
136
+ this.z === z
137
+ )
138
+ }
139
+
140
+ equals(...vecs: Xyz[]) {
141
+ return vecs.every(v => this.equals_(v.x, v.y, v.z))
142
+ }
143
+
144
+ distanceSquared_(x: number, y: number, z: number) {
145
+ const dx = this.x - x
146
+ const dy = this.y - y
147
+ const dz = this.z - z
148
+ return (dx ** 2) + (dy ** 2) + (dz ** 2)
149
+ }
150
+
151
+ distanceSquared({x, y, z}: Xyz) {
152
+ return this.distanceSquared_(x, y, z)
153
+ }
154
+
155
+ distance_(x: number, y: number, z: number) {
156
+ return Math.sqrt(this.distanceSquared_(x, y, z))
157
+ }
158
+
159
+ distance({x, y, z}: Xyz) {
160
+ return this.distance_(x, y, z)
161
+ }
162
+
163
+ dot_(x: number, y: number, z: number) {
164
+ return (this.x * x) + (this.y * y) + (this.z * z)
165
+ }
166
+
167
+ dot({x, y, z}: Xyz) {
168
+ return this.dot_(x, y, z)
169
+ }
170
+
171
+ inRange_(x: number, y: number, z: number, radius: number) {
172
+ const d2 = this.distanceSquared_(x, y, z)
173
+ return d2 < (radius ** 2)
174
+ }
175
+
176
+ inRange({x, y, z}: Xyz, radius: number) {
177
+ return this.inRange_(x, y, z, radius)
178
+ }
179
+
180
+ angleBetween_(x: number, y: number, z: number) {
181
+ const dotProduct = this.dot_(x, y, z)
182
+ const magnitudes = this.magnitude() * Vec3.new(x, y, z).magnitude()
183
+ return Math.acos(dotProduct / magnitudes)
184
+ }
185
+
186
+ angleBetween({x, y, z}: Xyz) {
187
+ return this.angleBetween_(x, y, z)
188
+ }
189
+
190
+ ///////////////////////////////////////////////////////////////////////
191
+
192
+ /** mutator */
193
+ add_(x: number, y: number, z: number) {
194
+ this.x += x
195
+ this.y += y
196
+ this.z += z
197
+ return this
198
+ }
199
+
200
+ /** mutator */
201
+ add(...vecs: Xyz[]) {
202
+ for (const {x, y, z} of vecs) this.add_(x, y, z)
203
+ return this
204
+ }
205
+
206
+ /** mutator */
207
+ subtract_(x: number, y: number, z: number) {
208
+ this.x -= x
209
+ this.y -= y
210
+ this.z -= z
211
+ return this
212
+ }
213
+
214
+ /** mutator */
215
+ subtract(...vecs: Xyz[]) {
216
+ for (const {x, y, z} of vecs) this.subtract_(x, y, z)
217
+ return this
218
+ }
219
+
220
+ /** mutator */
221
+ multiply_(x: number, y: number, z: number) {
222
+ this.x *= x
223
+ this.y *= y
224
+ this.z *= z
225
+ return this
226
+ }
227
+
228
+ /** mutator */
229
+ multiply(...vecs: Vec3[]) {
230
+ for (const {x, y, z} of vecs) this.multiply_(x, y, z)
231
+ return this
232
+ }
233
+
234
+ /** mutator */
235
+ divide_(x: number, y: number, z: number) {
236
+ this.x /= x
237
+ this.y /= y
238
+ this.z /= z
239
+ return this
240
+ }
241
+
242
+ /** mutator */
243
+ divide(...vecs: Vec3[]) {
244
+ for (const {x, y, z} of vecs) this.divide_(x, y, z)
245
+ return this
246
+ }
247
+
248
+ ///////////////////////////////////////////////////////////////////////
249
+
250
+ /** mutator */
251
+ half() {
252
+ return this.divideBy(2)
253
+ }
254
+
255
+ /** mutator */
256
+ double() {
257
+ return this.multiplyBy(2)
258
+ }
259
+
260
+ /** mutator */
261
+ abs() {
262
+ return this.map(x => Math.abs(x))
263
+ }
264
+
265
+ /** mutator */
266
+ map(fn: (a: number, index: number) => number) {
267
+ this.x = fn(this.x, 0)
268
+ this.y = fn(this.y, 1)
269
+ this.z = fn(this.z, 2)
270
+ return this
271
+ }
272
+
273
+ /** mutator */
274
+ negate() {
275
+ this.x = -this.x
276
+ this.y = -this.y
277
+ this.z = -this.z
278
+ return this
279
+ }
280
+
281
+ /** mutator */
282
+ addBy(delta: number) {
283
+ this.x += delta
284
+ this.y += delta
285
+ this.z += delta
286
+ return this
287
+ }
288
+
289
+ /** mutator */
290
+ multiplyBy(delta: number) {
291
+ this.x *= delta
292
+ this.y *= delta
293
+ this.z *= delta
294
+ return this
295
+ }
296
+
297
+ /** mutator */
298
+ divideBy(divisor: number) {
299
+ if (divisor === 0) return this
300
+ this.x /= divisor
301
+ this.y /= divisor
302
+ this.z /= divisor
303
+ return this
304
+ }
305
+
306
+ /** mutator */
307
+ normalize() {
308
+ return this.divideBy(this.magnitude())
309
+ }
310
+
311
+ /** mutator */
312
+ clampMagnitude(max: number) {
313
+ const magnitude = this.magnitude()
314
+ if (magnitude > max) this.normalize().multiplyBy(max)
315
+ return this
316
+ }
317
+
318
+ /** mutator */
319
+ floor(): this {
320
+ this.x = Math.floor(this.x)
321
+ this.y = Math.floor(this.y)
322
+ this.z = Math.floor(this.z)
323
+ return this
324
+ }
325
+
326
+ /** mutator */
327
+ ceil(): this {
328
+ this.x = Math.ceil(this.x)
329
+ this.y = Math.ceil(this.y)
330
+ this.z = Math.ceil(this.z)
331
+ return this
332
+ }
333
+
334
+ /** mutator */
335
+ round(): this {
336
+ this.x = Math.round(this.x)
337
+ this.y = Math.round(this.y)
338
+ this.z = Math.round(this.z)
339
+ return this
340
+ }
341
+
342
+ ///////////////////////////////////////////////////////////////////////
343
+
344
+ /** mutator */
345
+ cross_(x2: number, y2: number, z2: number) {
346
+ const {x: x1, y: y1, z: z1} = this
347
+ this.x = (y1 * z2) - (z1 * y2)
348
+ this.y = (z1 * x2) - (x1 * z2)
349
+ this.z = (x1 * y2) - (y1 * x2)
350
+ return this
351
+ }
352
+
353
+ /** mutator */
354
+ cross({x, y, z}: Xyz) {
355
+ return this.cross_(x, y, z)
356
+ }
357
+
358
+ /** mutator */
359
+ lerp_(x: number, y: number, z: number, fraction: number): this {
360
+ this.x += (x - this.x) * fraction
361
+ this.y += (y - this.y) * fraction
362
+ this.z += (z - this.z) * fraction
363
+ return this
364
+ }
365
+
366
+ /** mutator */
367
+ lerp({x, y, z}: Xyz, fraction: number) {
368
+ return this.lerp_(x, y, z, fraction)
369
+ }
370
+
371
+ approach_(x: number, y: number, z: number, speed: number, deltaTime: number, speedLimit?: number) {
372
+ this.x = Scalar.approach(this.x, x, speed, deltaTime, speedLimit)
373
+ this.y = Scalar.approach(this.y, y, speed, deltaTime, speedLimit)
374
+ this.z = Scalar.approach(this.z, z, speed, deltaTime, speedLimit)
375
+ return this
376
+ }
377
+
378
+ approach({x, y, z}: Xyz, speed: number, deltaTime: number, speedLimit?: number) {
379
+ return this.approach_(x, y, z, speed, deltaTime, speedLimit)
380
+ }
381
+
382
+ /** mutator */
383
+ projectOnto_(x: number, y: number, z: number) {
384
+ const scalar = this.dot_(x, y, z) / Vec3.magnitudeSquared(x, y, z)
385
+ this.x = scalar * x
386
+ this.y = scalar * y
387
+ this.z = scalar * z
388
+ return this
389
+ }
390
+
391
+ /** mutator */
392
+ projectOnto({x, y, z}: Vec3) {
393
+ return this.projectOnto_(x, y, z)
394
+ }
395
+
396
+ /** mutator */
397
+ reflect_(x: number, y: number, z: number) {
398
+ const dot = this.dot_(x, y, z) * 2
399
+ this.x -= dot * x
400
+ this.y -= dot * y
401
+ this.z -= dot * z
402
+ return this
403
+ }
404
+
405
+ /** mutator */
406
+ reflect({x, y, z}: Xyz) {
407
+ return this.reflect_(x, y, z)
408
+ }
409
+
410
+ /** mutator */
411
+ rotateAroundAxis_(ux: number, uy: number, uz: number, angle: number): this {
412
+ const cos = Math.cos(angle)
413
+ const sin = Math.sin(angle)
414
+ const {x, y, z} = this
415
+ this.x = (cos + (1 - cos) * ux * ux) * x + ((1 - cos) * ux * uy - uz * sin) * y + ((1 - cos) * ux * uz + uy * sin) * z
416
+ this.y = ((1 - cos) * uy * ux + uz * sin) * x + (cos + (1 - cos) * uy * uy) * y + ((1 - cos) * uy * uz - ux * sin) * z
417
+ this.z = ((1 - cos) * uz * ux - uy * sin) * x + ((1 - cos) * uz * uy + ux * sin) * y + (cos + (1 - cos) * uz * uz) * z
418
+ return this
419
+ }
420
+
421
+ /** mutator */
422
+ rotateAroundAxis({x, y, z}: Xyz, angle: number) {
423
+ return this.rotateAroundAxis_(x, y, z, angle)
424
+ }
425
+
426
+ /** mutator */
427
+ smooth_(x: number, y: number, z: number, smoothing: number) {
428
+ this.x = Scalar.smooth(this.x, x, smoothing)
429
+ this.y = Scalar.smooth(this.y, y, smoothing)
430
+ this.z = Scalar.smooth(this.z, z, smoothing)
431
+ return this
432
+ }
433
+
434
+ /** mutator */
435
+ smooth({x, y, z}: Xyz, smoothing: number) {
436
+ return this.smooth_(x, y, z, smoothing)
437
+ }
438
+ }
439
+
@@ -0,0 +1,74 @@
1
+
2
+ import {Xyzw} from "./quat.js"
3
+
4
+ export type Vec4Array = [number, number, number, number]
5
+
6
+ export class Vec4 {
7
+ constructor(
8
+ public x: number,
9
+ public y: number,
10
+ public z: number,
11
+ public w: number,
12
+ ) {}
13
+
14
+ static new(x: number, y: number, z: number, w: number) {
15
+ return new this(x, y, z, w)
16
+ }
17
+
18
+ static zero() {
19
+ return new this(0, 0, 0, 0)
20
+ }
21
+
22
+ static array(v: Vec4Array) {
23
+ return new this(...v)
24
+ }
25
+
26
+ static import({x, y, z, w}: Xyzw) {
27
+ return new this(x, y, z, w)
28
+ }
29
+
30
+ static from(v: Vec4Array | Xyzw) {
31
+ return Array.isArray(v)
32
+ ? this.array(v)
33
+ : this.import(v)
34
+ }
35
+
36
+ array(): Vec4Array {
37
+ const {x, y, z, w} = this
38
+ return [x, y, z, w]
39
+ }
40
+
41
+ toString() {
42
+ return `(Vec4 x${this.x.toFixed(2)}, y${this.y.toFixed(2)}, z${this.z.toFixed(2)}, w${this.w.toFixed(2)})`
43
+ }
44
+
45
+ clone() {
46
+ return new Vec4(...this.array())
47
+ }
48
+
49
+ set_(x: number, y: number, z: number, w: number) {
50
+ this.x = x
51
+ this.y = y
52
+ this.z = z
53
+ this.w = w
54
+ return this
55
+ }
56
+
57
+ set({x, y, z, w}: Xyzw) {
58
+ this.x = x
59
+ this.y = y
60
+ this.z = z
61
+ this.w = w
62
+ return this
63
+ }
64
+
65
+ /** mutator */
66
+ map(fn: (a: number, index: number) => number) {
67
+ this.x = fn(this.x, 0)
68
+ this.y = fn(this.y, 1)
69
+ this.z = fn(this.z, 2)
70
+ this.w = fn(this.w, 3)
71
+ return this
72
+ }
73
+ }
74
+
package/s/index.ts ADDED
@@ -0,0 +1,12 @@
1
+
2
+ export * from "./concepts/angles.js"
3
+ export * from "./concepts/circular.js"
4
+ export * from "./concepts/noise.js"
5
+ export * from "./concepts/quat.js"
6
+ export * from "./concepts/randy.js"
7
+ export * from "./concepts/scalar.js"
8
+ export * from "./concepts/spline.js"
9
+ export * from "./concepts/vec2.js"
10
+ export * from "./concepts/vec3.js"
11
+ export * from "./concepts/vec4.js"
12
+
@@ -0,0 +1,29 @@
1
+ export declare const Radians: {
2
+ pi: number;
3
+ circle: number;
4
+ /** @deprecated use Radians.toDegrees instead */
5
+ to: {
6
+ degrees(r: number): number;
7
+ arcseconds(r: number): number;
8
+ turns(r: number): number;
9
+ };
10
+ /** @deprecated use Degrees.toRadians instead */
11
+ from: {
12
+ turns(t: number): number;
13
+ degrees(d: number): number;
14
+ arcseconds(a: number): number;
15
+ };
16
+ toDegrees(r: number): number;
17
+ toArcseconds(r: number): number;
18
+ toTurns(r: number): number;
19
+ circleDistance(radiansA: number, radiansB: number): number;
20
+ };
21
+ export declare const Turns: {
22
+ toRadians(t: number): number;
23
+ };
24
+ export declare const Arcseconds: {
25
+ toRadians(a: number): number;
26
+ };
27
+ export declare const Degrees: {
28
+ toRadians(d: number): number;
29
+ };
@@ -0,0 +1,62 @@
1
+ import { Scalar } from "./scalar.js";
2
+ const pi = Math.PI;
3
+ const circle = 2 * Math.PI;
4
+ const to = {
5
+ degrees(r) {
6
+ return r * (180 / pi);
7
+ },
8
+ arcseconds(r) {
9
+ return to.degrees(r) * 3600;
10
+ },
11
+ turns(r) {
12
+ return r / circle;
13
+ },
14
+ };
15
+ const from = {
16
+ turns(t) {
17
+ return t * circle;
18
+ },
19
+ degrees(d) {
20
+ return d * (pi / 180);
21
+ },
22
+ arcseconds(a) {
23
+ return from.degrees(a / 3600);
24
+ }
25
+ };
26
+ export const Radians = {
27
+ pi,
28
+ circle,
29
+ /** @deprecated use Radians.toDegrees instead */
30
+ to,
31
+ /** @deprecated use Degrees.toRadians instead */
32
+ from,
33
+ toDegrees(r) {
34
+ return r * (180 / pi);
35
+ },
36
+ toArcseconds(r) {
37
+ return to.degrees(r) * 3600;
38
+ },
39
+ toTurns(r) {
40
+ return r / circle;
41
+ },
42
+ circleDistance(radiansA, radiansB) {
43
+ const diff = Math.abs(Scalar.wrap(radiansA - radiansB, 0, Radians.circle));
44
+ return Math.min(diff, Radians.circle - diff);
45
+ },
46
+ };
47
+ export const Turns = {
48
+ toRadians(t) {
49
+ return t * circle;
50
+ },
51
+ };
52
+ export const Arcseconds = {
53
+ toRadians(a) {
54
+ return from.degrees(a / 3600);
55
+ },
56
+ };
57
+ export const Degrees = {
58
+ toRadians(d) {
59
+ return d * (pi / 180);
60
+ },
61
+ };
62
+ //# sourceMappingURL=angles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"angles.js","sourceRoot":"","sources":["../../s/concepts/angles.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAA;AAElC,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAA;AAClB,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,CAAA;AAE1B,MAAM,EAAE,GAAG;IACV,OAAO,CAAC,CAAS;QAChB,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,CAAA;IACtB,CAAC;IACD,UAAU,CAAC,CAAS;QACnB,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;IAC5B,CAAC;IACD,KAAK,CAAC,CAAS;QACd,OAAO,CAAC,GAAG,MAAM,CAAA;IAClB,CAAC;CACD,CAAA;AAED,MAAM,IAAI,GAAG;IACZ,KAAK,CAAC,CAAS;QACd,OAAO,CAAC,GAAG,MAAM,CAAA;IAClB,CAAC;IACD,OAAO,CAAC,CAAS;QAChB,OAAO,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,CAAA;IACtB,CAAC;IACD,UAAU,CAAC,CAAS;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;IAC9B,CAAC;CACD,CAAA;AAED,MAAM,CAAC,MAAM,OAAO,GAAG;IACtB,EAAE;IACF,MAAM;IAEN,gDAAgD;IAChD,EAAE;IAEF,gDAAgD;IAChD,IAAI;IAEJ,SAAS,CAAC,CAAS;QAClB,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,CAAA;IACtB,CAAC;IACD,YAAY,CAAC,CAAS;QACrB,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;IAC5B,CAAC;IACD,OAAO,CAAC,CAAS;QAChB,OAAO,CAAC,GAAG,MAAM,CAAA;IAClB,CAAC;IAED,cAAc,CAAC,QAAgB,EAAE,QAAgB;QAChD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,GAAG,QAAQ,EAAE,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAA;QAC1E,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAC7C,CAAC;CACD,CAAA;AAED,MAAM,CAAC,MAAM,KAAK,GAAG;IACpB,SAAS,CAAC,CAAS;QAClB,OAAO,CAAC,GAAG,MAAM,CAAA;IAClB,CAAC;CACD,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG;IACzB,SAAS,CAAC,CAAS;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;IAC9B,CAAC;CACD,CAAA;AAED,MAAM,CAAC,MAAM,OAAO,GAAG;IACtB,SAAS,CAAC,CAAS;QAClB,OAAO,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,CAAA;IACtB,CAAC;CACD,CAAA"}
@@ -0,0 +1,17 @@
1
+ export declare class Circular {
2
+ x: number;
3
+ constructor(x: number);
4
+ clone(): Circular;
5
+ set(x: number): this;
6
+ static value(x: number | Circular): number;
7
+ static normalize(x: number): number;
8
+ normalize(): this;
9
+ static difference(x: number, y: number): number;
10
+ difference(y: number | Circular): number;
11
+ static lerp(x: number, y: number, fraction: number, max?: number): number;
12
+ lerp(y: number | Circular, fraction: number, max?: number): this;
13
+ static step(x: number, y: number, delta: number): number;
14
+ step(y: number | Circular, delta: number): this;
15
+ static approach(x: number, y: number, speed: number, deltaTime: number, speedLimit?: number): number;
16
+ approach(y: number | Circular, speed: number, deltaTime: number, speedLimit?: number): this;
17
+ }
@@ -0,0 +1,70 @@
1
+ import { Scalar } from "./scalar.js";
2
+ export class Circular {
3
+ x;
4
+ constructor(x) {
5
+ this.x = x;
6
+ }
7
+ clone() {
8
+ return new Circular(this.x);
9
+ }
10
+ set(x) {
11
+ this.x = x;
12
+ return this;
13
+ }
14
+ static value(x) {
15
+ return typeof x === "number"
16
+ ? x
17
+ : x.x;
18
+ }
19
+ static normalize(x) {
20
+ return Scalar.wrap(x, 0, 2 * Math.PI);
21
+ }
22
+ normalize() {
23
+ this.x = Circular.normalize(this.x);
24
+ return this;
25
+ }
26
+ static difference(x, y) {
27
+ x = this.normalize(x);
28
+ y = this.normalize(y);
29
+ let delta = y - x;
30
+ if (delta > Math.PI)
31
+ delta -= 2 * Math.PI;
32
+ if (delta < -Math.PI)
33
+ delta += 2 * Math.PI;
34
+ return delta;
35
+ }
36
+ difference(y) {
37
+ return Circular.difference(this.x, Circular.value(y));
38
+ }
39
+ static lerp(x, y, fraction, max) {
40
+ const difference = this.difference(x, y);
41
+ let delta = difference * fraction;
42
+ if (max !== undefined && Math.abs(delta) > max)
43
+ delta = Math.sign(delta) * max;
44
+ return this.normalize(x + delta);
45
+ }
46
+ lerp(y, fraction, max) {
47
+ this.x = Circular.lerp(this.x, Circular.value(y), fraction, max);
48
+ return this;
49
+ }
50
+ static step(x, y, delta) {
51
+ const difference = this.difference(x, y);
52
+ return this.normalize(Math.abs(difference) <= delta
53
+ ? y
54
+ : x + (Math.sign(difference) * delta));
55
+ }
56
+ step(y, delta) {
57
+ this.x = Circular.step(this.x, Circular.value(y), delta);
58
+ return this;
59
+ }
60
+ static approach(x, y, speed, deltaTime, speedLimit) {
61
+ const difference = this.difference(x, y);
62
+ const change = Scalar.creep(difference, speed, deltaTime, speedLimit);
63
+ return this.normalize(x + change);
64
+ }
65
+ approach(y, speed, deltaTime, speedLimit) {
66
+ this.x = Circular.approach(this.x, Circular.value(y), speed, deltaTime, speedLimit);
67
+ return this;
68
+ }
69
+ }
70
+ //# sourceMappingURL=circular.js.map