@benev/math 0.2.0-0 → 0.2.0-2

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 (90) hide show
  1. package/README.md +110 -23
  2. package/package.json +5 -4
  3. package/s/{primitives → core}/quat.ts +56 -16
  4. package/s/{primitives → core}/vec2.ts +52 -38
  5. package/s/{primitives → core}/vec3.ts +73 -47
  6. package/s/{primitives → core}/vec4.ts +13 -16
  7. package/s/index.ts +11 -12
  8. package/s/optimizers/hash-map.ts +4 -0
  9. package/s/optimizers/hash-set.ts +4 -0
  10. package/s/optimizers/zen.ts +27 -26
  11. package/s/physics/2d/collide2d.ts +2 -2
  12. package/s/physics/2d/intersect2d.ts +9 -6
  13. package/s/shapes/2d/circle.ts +25 -7
  14. package/s/shapes/2d/rect.ts +48 -19
  15. package/s/shapes/3d/box.ts +65 -20
  16. package/s/shapes/3d/segment.ts +12 -10
  17. package/s/{utils → tools}/angles.ts +7 -1
  18. package/s/{primitives → tools}/circular.ts +5 -3
  19. package/s/{primitives → tools}/scalar.ts +11 -11
  20. package/s/{utils → tools}/spline.ts +12 -11
  21. package/x/{primitives → core}/quat.d.ts +10 -5
  22. package/x/{primitives → core}/quat.js +49 -12
  23. package/x/core/quat.js.map +1 -0
  24. package/x/{primitives → core}/vec2.d.ts +16 -17
  25. package/x/{primitives → core}/vec2.js +38 -22
  26. package/x/core/vec2.js.map +1 -0
  27. package/x/{primitives → core}/vec3.d.ts +23 -20
  28. package/x/{primitives → core}/vec3.js +60 -27
  29. package/x/core/vec3.js.map +1 -0
  30. package/x/{primitives → core}/vec4.d.ts +5 -7
  31. package/x/{primitives → core}/vec4.js +12 -12
  32. package/x/core/vec4.js.map +1 -0
  33. package/x/index.d.ts +10 -10
  34. package/x/index.js +10 -10
  35. package/x/index.js.map +1 -1
  36. package/x/optimizers/hash-map.d.ts +1 -0
  37. package/x/optimizers/hash-map.js +3 -0
  38. package/x/optimizers/hash-map.js.map +1 -1
  39. package/x/optimizers/hash-set.d.ts +1 -0
  40. package/x/optimizers/hash-set.js +3 -0
  41. package/x/optimizers/hash-set.js.map +1 -1
  42. package/x/optimizers/zen.d.ts +14 -13
  43. package/x/optimizers/zen.js +29 -28
  44. package/x/optimizers/zen.js.map +1 -1
  45. package/x/physics/2d/collide2d.d.ts +1 -1
  46. package/x/physics/2d/collide2d.js +2 -2
  47. package/x/physics/2d/collide2d.js.map +1 -1
  48. package/x/physics/2d/intersect2d.d.ts +1 -1
  49. package/x/physics/2d/intersect2d.js +7 -5
  50. package/x/physics/2d/intersect2d.js.map +1 -1
  51. package/x/shapes/2d/circle.d.ts +11 -3
  52. package/x/shapes/2d/circle.js +19 -7
  53. package/x/shapes/2d/circle.js.map +1 -1
  54. package/x/shapes/2d/rect.d.ts +20 -10
  55. package/x/shapes/2d/rect.js +47 -24
  56. package/x/shapes/2d/rect.js.map +1 -1
  57. package/x/shapes/3d/box.d.ts +21 -8
  58. package/x/shapes/3d/box.js +56 -17
  59. package/x/shapes/3d/box.js.map +1 -1
  60. package/x/shapes/3d/segment.d.ts +5 -5
  61. package/x/shapes/3d/segment.js +11 -9
  62. package/x/shapes/3d/segment.js.map +1 -1
  63. package/x/{utils → tools}/angles.d.ts +2 -0
  64. package/x/{utils → tools}/angles.js +7 -1
  65. package/x/tools/angles.js.map +1 -0
  66. package/x/{primitives → tools}/circular.js +4 -3
  67. package/x/tools/circular.js.map +1 -0
  68. package/x/{utils → tools}/noise.js.map +1 -1
  69. package/x/{utils → tools}/randy.js.map +1 -1
  70. package/x/{primitives → tools}/scalar.d.ts +4 -4
  71. package/x/{primitives → tools}/scalar.js +11 -11
  72. package/x/tools/scalar.js.map +1 -0
  73. package/x/{utils → tools}/spline.d.ts +3 -3
  74. package/x/{utils → tools}/spline.js +4 -2
  75. package/x/tools/spline.js.map +1 -0
  76. package/x/primitives/circular.js.map +0 -1
  77. package/x/primitives/quat.js.map +0 -1
  78. package/x/primitives/scalar.js.map +0 -1
  79. package/x/primitives/vec2.js.map +0 -1
  80. package/x/primitives/vec3.js.map +0 -1
  81. package/x/primitives/vec4.js.map +0 -1
  82. package/x/utils/angles.js.map +0 -1
  83. package/x/utils/spline.js.map +0 -1
  84. /package/s/{utils → tools}/noise.ts +0 -0
  85. /package/s/{utils → tools}/randy.ts +0 -0
  86. /package/x/{primitives → tools}/circular.d.ts +0 -0
  87. /package/x/{utils → tools}/noise.d.ts +0 -0
  88. /package/x/{utils → tools}/noise.js +0 -0
  89. /package/x/{utils → tools}/randy.d.ts +0 -0
  90. /package/x/{utils → tools}/randy.js +0 -0
@@ -1,38 +1,83 @@
1
1
 
2
- import {Vec3} from "../../primitives/vec3.js"
2
+ import {Vec3, XyzArray, Xyz} from "../../core/vec3.js"
3
+
4
+ export type BoxJson = [min: XyzArray, max: XyzArray]
5
+ export type BoxLike = {min: Xyz, max: Xyz}
3
6
 
4
7
  export class Box {
5
8
  constructor(
6
- public center: Vec3,
7
- public extent: Vec3,
8
- ) {
9
- if (extent.x < 0 || extent.y < 0 || extent.z < 0)
10
- throw new Error(`invalid negative extent, ${extent.toString()}`)
9
+ public min: Vec3,
10
+ public max: Vec3,
11
+ ) {}
12
+
13
+ static from(data: BoxJson | BoxLike) {
14
+ return Array.isArray(data)
15
+ ? new this(Vec3.from(data[0]), Vec3.from(data[1]))
16
+ : new this(Vec3.from(data.min), Vec3.from(data.max))
11
17
  }
12
18
 
13
- static fromCorner(min: Vec3, extent: Vec3) {
14
- return new this(
15
- min.clone().add(extent.clone().half()),
16
- extent,
17
- )
19
+ static fromCorner(min: Vec3, size: Vec3) {
20
+ return new this(min, min.clone().add(size))
18
21
  }
19
22
 
20
- get min() {
21
- return this.center.clone()
22
- .subtract(this.extent.clone().half())
23
+ static fromCenter(center: Vec3, size: Vec3) {
24
+ const halfSize = size.clone().half()
25
+ const min = center.clone().subtract(halfSize)
26
+ const max = center.clone().add(halfSize)
27
+ return new this(min, max)
23
28
  }
24
29
 
25
- get max() {
26
- return this.center.clone()
27
- .add(this.extent.clone().half())
30
+ toJSON(): BoxJson {
31
+ return [this.min.toJSON(), this.max.toJSON()]
28
32
  }
29
33
 
30
34
  clone() {
31
- return new Box(this.center.clone(), this.extent.clone())
35
+ return new Box(this.min.clone(), this.max.clone())
36
+ }
37
+
38
+ set(box: BoxLike) {
39
+ this.min.set(box.min)
40
+ this.max.set(box.max)
41
+ }
42
+
43
+ size() {
44
+ return this.max.clone().subtract(this.min)
45
+ }
46
+
47
+ center() {
48
+ return this.min.clone().add(this.size().half())
49
+ }
50
+
51
+ normalize() {
52
+ const {min, max} = this
53
+ this.min.set(Vec3.min(min, max))
54
+ this.max.set(Vec3.max(min, max))
55
+ return this
56
+ }
57
+
58
+ translate_(x: number, y: number, z: number) {
59
+ this.min.add_(x, y, z)
60
+ this.max.add_(x, y, z)
61
+ return this
62
+ }
63
+
64
+ translate(delta: Vec3) {
65
+ this.min.add(delta)
66
+ this.max.add(delta)
67
+ return this
68
+ }
69
+
70
+ grow(increase: Vec3) {
71
+ const halfIncrease = increase.clone().half()
72
+ this.min.subtract(halfIncrease)
73
+ this.max.add(halfIncrease)
74
+ return this
32
75
  }
33
76
 
34
- grow(increase: number) {
35
- this.extent.addBy(increase)
77
+ growBy(increase: number) {
78
+ const halfIncrease = increase / 2
79
+ this.min.subtractBy(halfIncrease)
80
+ this.max.addBy(halfIncrease)
36
81
  return this
37
82
  }
38
83
  }
@@ -1,5 +1,5 @@
1
1
 
2
- import {Vec3} from "../../primitives/vec3.js"
2
+ import {Vec3} from "../../core/vec3.js"
3
3
 
4
4
  export class Segment {
5
5
  constructor(
@@ -7,18 +7,18 @@ export class Segment {
7
7
  public end: Vec3,
8
8
  ) {}
9
9
 
10
- get vector() {
10
+ vector() {
11
11
  return this.end.clone().subtract(this.start)
12
12
  }
13
13
 
14
- get length() {
14
+ length() {
15
15
  return this.start.distance(this.end)
16
16
  }
17
17
 
18
- get center() {
18
+ center() {
19
19
  return this.start.clone()
20
20
  .add(this.end)
21
- .divideBy(2)
21
+ .half()
22
22
  }
23
23
 
24
24
  clone() {
@@ -29,18 +29,20 @@ export class Segment {
29
29
  }
30
30
 
31
31
  fromStart(length: number) {
32
- const direction = this.vector.normalize()
32
+ const direction = this.vector().normalize()
33
33
  return this.start.clone().add(direction.multiplyBy(length))
34
34
  }
35
35
 
36
36
  point(fraction: number) {
37
- return this.start.clone().add(this.vector.multiplyBy(fraction))
37
+ return this.start.clone().add(this.vector().multiplyBy(fraction))
38
38
  }
39
39
 
40
40
  scale(fraction: number) {
41
- const newHalfVector = this.vector.multiplyBy(fraction / 2)
42
- this.start.set(this.center.subtract(newHalfVector))
43
- this.end.set(this.center.add(newHalfVector))
41
+ const {center} = this
42
+ const newHalfVector = this.vector().multiplyBy(fraction / 2)
43
+ this.start.set(center().subtract(newHalfVector))
44
+ this.end.set(center().add(newHalfVector))
45
+ return this
44
46
  }
45
47
  }
46
48
 
@@ -1,5 +1,5 @@
1
1
 
2
- import {Scalar} from "../primitives/scalar.js"
2
+ import {Scalar} from "./scalar.js"
3
3
 
4
4
  const pi = Math.PI
5
5
 
@@ -27,6 +27,9 @@ export const Turns = {
27
27
  toRadians(t: number) {
28
28
  return t * Radians.circle
29
29
  },
30
+ toDegrees(t: number) {
31
+ return Radians.toDegrees(Turns.toRadians(t))
32
+ },
30
33
  }
31
34
 
32
35
  export const Arcseconds = {
@@ -39,5 +42,8 @@ export const Degrees = {
39
42
  toRadians(d: number) {
40
43
  return d * (pi / 180)
41
44
  },
45
+ toTurns(d: number) {
46
+ return Radians.toTurns(Degrees.toRadians(d))
47
+ },
42
48
  }
43
49
 
@@ -1,6 +1,8 @@
1
1
 
2
2
  import {Scalar} from "./scalar.js"
3
3
 
4
+ const circle = 2 * Math.PI
5
+
4
6
  export class Circular {
5
7
  constructor(public x: number) {}
6
8
 
@@ -20,7 +22,7 @@ export class Circular {
20
22
  }
21
23
 
22
24
  static normalize(x: number) {
23
- return Scalar.wrap(x, 0, 2 * Math.PI)
25
+ return Scalar.wrap(x, 0, circle)
24
26
  } normalize() {
25
27
  this.x = Circular.normalize(this.x)
26
28
  return this
@@ -30,8 +32,8 @@ export class Circular {
30
32
  x = this.normalize(x)
31
33
  y = this.normalize(y)
32
34
  let delta = y - x
33
- if (delta > Math.PI) delta -= 2 * Math.PI
34
- if (delta < -Math.PI) delta += 2 * Math.PI
35
+ if (delta > Math.PI) delta -= circle
36
+ if (delta < -Math.PI) delta += circle
35
37
  return delta
36
38
  } difference(y: number | Circular) {
37
39
  return Circular.difference(this.x, Circular.value(y))
@@ -43,7 +43,7 @@ export class Scalar {
43
43
  x += n
44
44
  return x
45
45
  } add(...nums: number[]) {
46
- this.x = Scalar.add(...nums)
46
+ this.x = Scalar.add(this.x, ...nums)
47
47
  return this
48
48
  }
49
49
 
@@ -53,23 +53,23 @@ export class Scalar {
53
53
  return this
54
54
  }
55
55
 
56
- static min(x: number, minimum: number = 0) {
57
- return Math.max(x, minimum)
58
- } min(minimum: number = 0) {
59
- this.x = Scalar.min(this.x, minimum)
56
+ static atLeast(x: number, least: number = 0) {
57
+ return Math.max(x, least)
58
+ } atLeast(least: number = 0) {
59
+ this.x = Scalar.atLeast(this.x, least)
60
60
  return this
61
61
  }
62
62
 
63
- static max(x: number, maximum: number = 1) {
64
- return Math.min(x, maximum)
65
- } max(maximum: number = 1) {
66
- this.x = Scalar.max(this.x, maximum)
63
+ static atMost(x: number, most: number = 1) {
64
+ return Math.min(x, most)
65
+ } atMost(most: number = 1) {
66
+ this.x = Scalar.atMost(this.x, most)
67
67
  return this
68
68
  }
69
69
 
70
70
  static clamp(x: number, a: number = 0, b: number = 1) {
71
- x = Scalar.min(x, Math.min(a, b))
72
- x = Scalar.max(x, Math.max(a, b))
71
+ x = Scalar.atLeast(x, Math.min(a, b))
72
+ x = Scalar.atMost(x, Math.max(a, b))
73
73
  return x
74
74
  } clamp(a: number = 0, b: number = 1) {
75
75
  this.x = Scalar.clamp(this.x, a, b)
@@ -1,15 +1,14 @@
1
1
 
2
- import {Scalar} from "../primitives/scalar.js"
3
- import {Vec2Array} from "../primitives/vec2.js"
2
+ import {Scalar} from "./scalar.js"
3
+ import {XyArray} from "../core/vec2.js"
4
4
 
5
5
  /** resolve a number within a linear spline. */
6
- export function linear(x: number, points: Vec2Array[]): number {
6
+ export function linear(x: number, points: XyArray[]): number {
7
7
  if (points.length < 2)
8
8
  throw new Error("need at least two points, come on")
9
9
 
10
10
  const [first] = points.at(0)!
11
11
  const [last] = points.at(-1)!
12
-
13
12
  x = Scalar.clamp(x, first, last)
14
13
 
15
14
  for (let i = 0; i < points.length - 1; i++) {
@@ -26,11 +25,13 @@ export function linear(x: number, points: Vec2Array[]): number {
26
25
  }
27
26
 
28
27
  /** resolve a number within a catmull-rom spline, that's all smooth-like. */
29
- export function catmullRom(x: number, points: Vec2Array[]) {
28
+ export function catmullRom(x: number, points: XyArray[]) {
30
29
  if (points.length < 4)
31
30
  throw new Error("need at least four points for this magic")
32
31
 
33
- x = Scalar.clamp(x)
32
+ const [first] = points.at(0)!
33
+ const [last] = points.at(-1)!
34
+ x = Scalar.clamp(x, first, last)
34
35
 
35
36
  // find the segment where 'x' fits
36
37
  for (let i = 1; i < points.length - 2; i++) {
@@ -54,7 +55,7 @@ export const ez = {
54
55
  throw new Error("need at least two points, come on")
55
56
 
56
57
  const points2 = points.map(
57
- (p, index): Vec2Array =>
58
+ (p, index): XyArray =>
58
59
  [Scalar.clamp(index / (points.length - 1)), p]
59
60
  )
60
61
 
@@ -67,10 +68,10 @@ namespace helpers {
67
68
  /** internal big-brain maths for the catmull-rom implementation */
68
69
  export function catmullRom(
69
70
  t: number,
70
- [,p0]: Vec2Array,
71
- [,p1]: Vec2Array,
72
- [,p2]: Vec2Array,
73
- [,p3]: Vec2Array,
71
+ [,p0]: XyArray,
72
+ [,p1]: XyArray,
73
+ [,p2]: XyArray,
74
+ [,p3]: XyArray,
74
75
  ) {
75
76
 
76
77
  const t2 = t * t
@@ -1,5 +1,5 @@
1
1
  import { Xyz } from "./vec3.js";
2
- export type QuatArray = [number, number, number, number];
2
+ export type XyzwArray = [x: number, y: number, z: number, w: number];
3
3
  export type Xyzw = {
4
4
  x: number;
5
5
  y: number;
@@ -14,14 +14,19 @@ export declare class Quat {
14
14
  constructor(x: number, y: number, z: number, w: number);
15
15
  static new(x: number, y: number, z: number, w: number): Quat;
16
16
  static identity(): Quat;
17
- static array(q: QuatArray): Quat;
18
- static import({ x, y, z, w }: Xyzw): Quat;
19
- static from(q: QuatArray | Xyzw): Quat;
17
+ static from(q: XyzwArray | Xyzw): Quat;
20
18
  static rotate_(pitch: number, yaw: number, roll: number): Quat;
21
19
  static rotate(vec: Xyz): Quat;
22
- array(): QuatArray;
20
+ toJSON(): XyzwArray;
23
21
  toString(): string;
24
22
  clone(): Quat;
23
+ lengthSquared(): number;
24
+ length(): number;
25
+ isUnit(epsilon?: number): boolean;
26
+ ensureUnit(): this;
27
+ normalize(): this;
28
+ conjugate(): this;
29
+ invert(): this;
25
30
  transform_(x: number, y: number, z: number, w: number, global?: boolean): Quat;
26
31
  transform({ x, y, z, w }: Xyzw, global?: boolean): Quat;
27
32
  rotate_(pitch: number, yaw: number, roll: number, global?: boolean): Quat;
@@ -15,16 +15,10 @@ export class Quat {
15
15
  static identity() {
16
16
  return new this(0, 0, 0, 1);
17
17
  }
18
- static array(q) {
19
- return new this(...q);
20
- }
21
- static import({ x, y, z, w }) {
22
- return new this(x, y, z, w);
23
- }
24
18
  static from(q) {
25
19
  return Array.isArray(q)
26
- ? this.array(q)
27
- : this.import(q);
20
+ ? new this(...q)
21
+ : new this(q.x, q.y, q.z, q.w);
28
22
  }
29
23
  static rotate_(pitch, yaw, roll) {
30
24
  return this.identity().rotate_(pitch, yaw, roll);
@@ -32,7 +26,7 @@ export class Quat {
32
26
  static rotate(vec) {
33
27
  return this.identity().rotate(vec);
34
28
  }
35
- array() {
29
+ toJSON() {
36
30
  const { x, y, z, w } = this;
37
31
  return [x, y, z, w];
38
32
  }
@@ -40,12 +34,55 @@ export class Quat {
40
34
  return `(Quat x${this.x.toFixed(2)}, y${this.y.toFixed(2)}, z${this.z.toFixed(2)}, w${this.w.toFixed(2)})`;
41
35
  }
42
36
  clone() {
43
- return new Quat(...this.array());
37
+ return new Quat(...this.toJSON());
38
+ }
39
+ lengthSquared() {
40
+ return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
41
+ }
42
+ length() {
43
+ return Math.sqrt(this.lengthSquared());
44
+ }
45
+ isUnit(epsilon = 1e-6) {
46
+ return Math.abs(this.length() - 1) <= epsilon;
47
+ }
48
+ ensureUnit() {
49
+ if (!this.isUnit())
50
+ this.normalize();
51
+ return this;
52
+ }
53
+ normalize() {
54
+ const m = this.length();
55
+ if (!m) {
56
+ this.x = this.y = this.z = 0;
57
+ this.w = 1;
58
+ return this;
59
+ }
60
+ this.x /= m;
61
+ this.y /= m;
62
+ this.z /= m;
63
+ this.w /= m;
64
+ return this;
65
+ }
66
+ conjugate() {
67
+ this.x *= -1;
68
+ this.y *= -1;
69
+ this.z *= -1;
70
+ return this;
71
+ }
72
+ invert() {
73
+ const len2 = this.lengthSquared();
74
+ if (!len2)
75
+ return this.set_(0, 0, 0, 1);
76
+ this.x = -this.x / len2;
77
+ this.y = -this.y / len2;
78
+ this.z = -this.z / len2;
79
+ this.w = this.w / len2;
80
+ return this;
44
81
  }
45
82
  transform_(x, y, z, w, global = false) {
46
83
  if (global) {
47
- const original = this.array();
48
- return this.set_(x, y, z, w).multiply_(...original);
84
+ const original = this.clone();
85
+ return this.set_(x, y, z, w).multiply(original);
49
86
  }
50
87
  else {
51
88
  return this.multiply_(x, y, z, w);
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quat.js","sourceRoot":"","sources":["../../s/core/quat.ts"],"names":[],"mappings":"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"}
@@ -1,29 +1,25 @@
1
- export type Vec2Array = [number, number];
1
+ export type XyArray = [x: number, y: number];
2
2
  export type Xy = {
3
3
  x: number;
4
4
  y: number;
5
5
  };
6
- /** https://github.com/microsoft/TypeScript/issues/5863 */
7
- type TsHack<T> = {
8
- new (...a: ConstructorParameters<typeof Vec2>): T;
9
- };
10
6
  export declare class Vec2 implements Xy {
11
7
  x: number;
12
8
  y: number;
13
9
  constructor(x: number, y: number);
14
- static new<T extends Vec2>(this: TsHack<T>, x: number, y: number): T;
15
- static zero<T extends Vec2>(this: TsHack<T>): T;
16
- static all<T extends Vec2>(this: TsHack<T>, value: number): T;
17
- static array<T extends Vec2>(this: TsHack<T>, v: Vec2Array): T;
18
- static import<T extends Vec2>(this: TsHack<T>, { x, y }: Xy): T;
19
- static from(v: Vec2Array | Xy): Vec2;
10
+ static new(x: number, y: number): Vec2;
11
+ static zero(): Vec2;
12
+ static all(value: number): Vec2;
13
+ static from(v: XyArray | Xy): Vec2;
20
14
  static magnitudeSquared(x: number, y: number): number;
21
15
  static magnitude(x: number, y: number): number;
22
16
  static average(...vectors: Xy[]): Vec2;
23
- static min(...vecs: Vec2[]): Vec2;
24
- static max(...vecs: Vec2[]): Vec2;
17
+ static min(...vecs: Xy[]): Vec2;
18
+ static max(...vecs: Xy[]): Vec2;
19
+ static fromAngle(radians: number): Vec2;
25
20
  clone(): Vec2;
26
- array(): Vec2Array;
21
+ [Symbol.iterator](): Generator<number, void, unknown>;
22
+ toJSON(): XyArray;
27
23
  toString(): string;
28
24
  /** mutator */
29
25
  set_(x: number, y: number): this;
@@ -34,6 +30,8 @@ export declare class Vec2 implements Xy {
34
30
  rotation(): number;
35
31
  equals_(x: number, y: number): boolean;
36
32
  equals(...vecs: Xy[]): boolean;
33
+ near_(x: number, y: number, epsilon?: number): boolean;
34
+ near({ x, y }: Xy, epsilon?: number): boolean;
37
35
  dot_(x: number, y: number): number;
38
36
  dot({ x, y }: Xy): number;
39
37
  distanceSquared_(x: number, y: number): number;
@@ -65,7 +63,9 @@ export declare class Vec2 implements Xy {
65
63
  /** mutator */
66
64
  map(fn: (a: number, index: number) => number): this;
67
65
  /** mutator */
68
- clamp(min: number, max: number): this;
66
+ clamp(min?: Xy, max?: Xy): this;
67
+ /** mutator */
68
+ clampBy(min?: number, max?: number): this;
69
69
  /** mutator */
70
70
  negate(): this;
71
71
  /** mutator */
@@ -105,10 +105,9 @@ export declare class Vec2 implements Xy {
105
105
  /** mutator */
106
106
  rotateAroundPoint_(x: number, y: number, radians: number): this;
107
107
  /** mutator */
108
- rotateAroundPoint({ x, y }: Vec2, radians: number): this;
108
+ rotateAroundPoint({ x, y }: Xy, radians: number): this;
109
109
  /** mutator */
110
110
  smooth_(x: number, y: number, smoothing: number): this;
111
111
  /** mutator */
112
112
  smooth({ x, y }: Xy, smoothing: number): this;
113
113
  }
114
- export {};
@@ -1,4 +1,4 @@
1
- import { Scalar } from "./scalar.js";
1
+ import { Scalar } from "../tools/scalar.js";
2
2
  export class Vec2 {
3
3
  x;
4
4
  y;
@@ -6,7 +6,6 @@ export class Vec2 {
6
6
  this.x = x;
7
7
  this.y = y;
8
8
  }
9
- ///////////////////////////////////////////////////////////////////////
10
9
  static new(x, y) {
11
10
  return new this(x, y);
12
11
  }
@@ -16,16 +15,10 @@ export class Vec2 {
16
15
  static all(value) {
17
16
  return new this(value, value);
18
17
  }
19
- static array(v) {
20
- return new this(...v);
21
- }
22
- static import({ x, y }) {
23
- return new this(x, y);
24
- }
25
18
  static from(v) {
26
19
  return Array.isArray(v)
27
- ? this.array(v)
28
- : this.import(v);
20
+ ? new this(...v)
21
+ : new this(v.x, v.y);
29
22
  }
30
23
  static magnitudeSquared(x, y) {
31
24
  return (x * x) + (y * y);
@@ -39,16 +32,22 @@ export class Vec2 {
39
32
  .divideBy(vectors.length);
40
33
  }
41
34
  static min(...vecs) {
42
- return new Vec2(Math.min(...vecs.map(v => v.x)), Math.min(...vecs.map(v => v.y)));
35
+ return new this(Math.min(...vecs.map(v => v.x)), Math.min(...vecs.map(v => v.y)));
43
36
  }
44
37
  static max(...vecs) {
45
- return new Vec2(Math.max(...vecs.map(v => v.x)), Math.max(...vecs.map(v => v.y)));
38
+ return new this(Math.max(...vecs.map(v => v.x)), Math.max(...vecs.map(v => v.y)));
39
+ }
40
+ static fromAngle(radians) {
41
+ return new this(Math.cos(radians), Math.sin(radians));
46
42
  }
47
- ///////////////////////////////////////////////////////////////////////
48
43
  clone() {
49
44
  return new Vec2(this.x, this.y);
50
45
  }
51
- array() {
46
+ *[Symbol.iterator]() {
47
+ yield this.x;
48
+ yield this.y;
49
+ }
50
+ toJSON() {
52
51
  return [this.x, this.y];
53
52
  }
54
53
  toString() {
@@ -66,7 +65,6 @@ export class Vec2 {
66
65
  this.y = y;
67
66
  return this;
68
67
  }
69
- ///////////////////////////////////////////////////////////////////////
70
68
  magnitudeSquared() {
71
69
  return Vec2.magnitudeSquared(this.x, this.y);
72
70
  }
@@ -83,6 +81,13 @@ export class Vec2 {
83
81
  equals(...vecs) {
84
82
  return vecs.every(({ x, y }) => this.equals_(x, y));
85
83
  }
84
+ near_(x, y, epsilon = 1e-6) {
85
+ return (Math.abs(this.x - x) <= epsilon &&
86
+ Math.abs(this.y - y) <= epsilon);
87
+ }
88
+ near({ x, y }, epsilon = 1e-6) {
89
+ return this.near_(x, y, epsilon);
90
+ }
86
91
  dot_(x, y) {
87
92
  return (this.x * x) + (this.y * y);
88
93
  }
@@ -106,12 +111,14 @@ export class Vec2 {
106
111
  angleBetween_(x, y) {
107
112
  const dot = this.dot_(x, y);
108
113
  const magnitudes = this.magnitude() * Vec2.magnitude(x, y);
109
- return Math.acos(dot / magnitudes);
114
+ if (magnitudes === 0)
115
+ return 0;
116
+ const ratio = Scalar.clamp(dot / magnitudes, -1, 1);
117
+ return Math.acos(ratio);
110
118
  }
111
119
  angleBetween({ x, y }) {
112
120
  return this.angleBetween_(x, y);
113
121
  }
114
- ///////////////////////////////////////////////////////////////////////
115
122
  /** mutator */
116
123
  normalize() {
117
124
  return this.divideBy(this.magnitude());
@@ -174,9 +181,16 @@ export class Vec2 {
174
181
  return this;
175
182
  }
176
183
  /** mutator */
177
- clamp(min, max) {
178
- const clamp = (val) => Math.max(min, Math.min(max, val));
179
- return this.map(clamp);
184
+ clamp(min = { x: 0, y: 0 }, max = { x: 1, y: 1 }) {
185
+ this.x = Scalar.clamp(this.x, min.x, max.x);
186
+ this.y = Scalar.clamp(this.y, min.y, max.y);
187
+ return this;
188
+ }
189
+ /** mutator */
190
+ clampBy(min = 0, max = 1) {
191
+ this.x = Scalar.clamp(this.x, min, max);
192
+ this.y = Scalar.clamp(this.y, min, max);
193
+ return this;
180
194
  }
181
195
  /** mutator */
182
196
  negate() {
@@ -247,8 +261,10 @@ export class Vec2 {
247
261
  }
248
262
  /** mutator */
249
263
  divide_(x, y) {
250
- this.x /= x;
251
- this.y /= y;
264
+ if (x !== 0)
265
+ this.x /= x;
266
+ if (y !== 0)
267
+ this.y /= y;
252
268
  return this;
253
269
  }
254
270
  /** mutator */