@js-draw/math 1.18.0 → 1.21.1

Sign up to get free protection for your applications and to get access to all the features.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Henry Heino
3
+ Copyright (c) 2023-2024 Henry Heino
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,5 +1,8 @@
1
1
  import { Point2, Vec2 } from './Vec2';
2
2
  import Vec3 from './Vec3';
3
+ /**
4
+ * See {@link Mat33.toArray}.
5
+ */
3
6
  export type Mat33Array = [
4
7
  number,
5
8
  number,
@@ -15,6 +18,46 @@ export type Mat33Array = [
15
18
  * Represents a three dimensional linear transformation or
16
19
  * a two-dimensional affine transformation. (An affine transformation scales/rotates/shears
17
20
  * **and** translates while a linear transformation just scales/rotates/shears).
21
+ *
22
+ * In addition to other matrices, {@link Mat33}s can be used to transform {@link Vec3}s and {@link Vec2}s.
23
+ *
24
+ * For example, to move the point $(1, 1)$ by 5 units to the left and 6 units up,
25
+ * ```ts,runnable,console
26
+ * import {Mat33, Vec2} from '@js-draw/math';
27
+ *
28
+ * const moveLeftAndUp = Mat33.translation(Vec2.of(5, 6));
29
+ * console.log(moveLeftAndUp);
30
+ * ```
31
+ *
32
+ * This `moveLeftAndUp` matrix could then translate (move) a {@link Vec2} using
33
+ * {@link Mat33.transformVec2}:
34
+ *
35
+ * ```ts,runnable,console
36
+ * ---use-previous---
37
+ * ---visible---
38
+ * console.log(moveLeftAndUp.transformVec2(Vec2.of(1, 1)));
39
+ * console.log(moveLeftAndUp.transformVec2(Vec2.of(-1, 2)));
40
+ * ```
41
+ *
42
+ * It's also possible to create transformation matrices that scale and rotate.
43
+ * A single transform matrix can be created from multiple using matrix multiplication
44
+ * (see {@link Mat33.rightMul}):
45
+ *
46
+ * ```ts,runnable,console
47
+ * ---use-previous---
48
+ * ---visible---
49
+ * // Create a matrix by right multiplying.
50
+ * const scaleThenRotate =
51
+ * // The resultant matrix first scales by a factor of two
52
+ * Mat33.scaling2D(2).rightMul(
53
+ * // ...then rotates by pi/2 radians = 90 degrees.
54
+ * Mat33.zRotation(Math.PI / 2)
55
+ * );
56
+ * console.log(scaleThenRotate);
57
+ *
58
+ * // Use scaleThenRotate to scale then rotate a vector.
59
+ * console.log(scaleThenRotate.transformVec2(Vec2.unitX));
60
+ * ```
18
61
  */
19
62
  export declare class Mat33 {
20
63
  readonly a1: number;
@@ -36,6 +79,9 @@ export declare class Mat33 {
36
79
  * c1 & c2 & c3
37
80
  * \end{bmatrix}
38
81
  * $$
82
+ *
83
+ * Static constructor methods are also available.
84
+ * See {@link Mat33.scaling2D}, {@link Mat33.zRotation}, {@link Mat33.translation}, and {@link Mat33.fromCSSMatrix}.
39
85
  */
40
86
  constructor(a1: number, a2: number, a3: number, b1: number, b2: number, b3: number, c1: number, c2: number, c3: number);
41
87
  /**
@@ -49,6 +95,7 @@ export declare class Mat33 {
49
95
  * $$
50
96
  */
51
97
  static ofRows(r1: Vec3, r2: Vec3, r3: Vec3): Mat33;
98
+ /** The 3x3 [identity matrix](https://en.wikipedia.org/wiki/Identity_matrix). */
52
99
  static identity: Mat33;
53
100
  /**
54
101
  * Either returns the inverse of this, or, if this matrix is singular/uninvertable,
@@ -62,6 +109,29 @@ export declare class Mat33 {
62
109
  private cachedInverse;
63
110
  private computeInverse;
64
111
  transposed(): Mat33;
112
+ /**
113
+ * [Right-multiplies](https://en.wikipedia.org/wiki/Matrix_multiplication) this by `other`.
114
+ *
115
+ * See also {@link transformVec3} and {@link transformVec2}.
116
+ *
117
+ * Example:
118
+ * ```ts,runnable,console
119
+ * import {Mat33, Vec2} from '@js-draw/math';
120
+ * console.log(Mat33.identity.rightMul(Mat33.identity));
121
+ *
122
+ * // Create a matrix by right multiplying.
123
+ * const scaleThenRotate =
124
+ * // The resultant matrix first scales by a factor of two
125
+ * Mat33.scaling2D(2).rightMul(
126
+ * // ...then rotates by pi/4 radians = 45 degrees.
127
+ * Mat33.zRotation(Math.PI / 4)
128
+ * );
129
+ * console.log(scaleThenRotate);
130
+ *
131
+ * // Use scaleThenRotate to scale then rotate a vector.
132
+ * console.log(scaleThenRotate.transformVec2(Vec2.unitX));
133
+ * ```
134
+ */
65
135
  rightMul(other: Mat33): Mat33;
66
136
  /**
67
137
  * Applies this as an **affine** transformation to the given vector.
@@ -79,6 +149,15 @@ export declare class Mat33 {
79
149
  isIdentity(): boolean;
80
150
  /** Returns true iff this = other ± fuzz */
81
151
  eq(other: Mat33, fuzz?: number): boolean;
152
+ /**
153
+ * Creates a human-readable representation of the matrix.
154
+ *
155
+ * Example:
156
+ * ```ts,runnable,console
157
+ * import { Mat33 } from '@js-draw/math';
158
+ * console.log(Mat33.identity.toString());
159
+ * ```
160
+ */
82
161
  toString(): string;
83
162
  /**
84
163
  * ```
@@ -86,6 +165,18 @@ export declare class Mat33 {
86
165
  * result[1] = element at row zero, column 1
87
166
  * ...
88
167
  * ```
168
+ *
169
+ * Example:
170
+ * ```ts,runnable,console
171
+ * import { Mat33 } from '@js-draw/math';
172
+ * console.log(
173
+ * new Mat33(
174
+ * 1, 2, 3,
175
+ * 4, 5, 6,
176
+ * 7, 8, 9,
177
+ * )
178
+ * );
179
+ * ```
89
180
  */
90
181
  toArray(): Mat33Array;
91
182
  /**
package/dist/cjs/Mat33.js CHANGED
@@ -10,6 +10,46 @@ const Vec3_1 = __importDefault(require("./Vec3"));
10
10
  * Represents a three dimensional linear transformation or
11
11
  * a two-dimensional affine transformation. (An affine transformation scales/rotates/shears
12
12
  * **and** translates while a linear transformation just scales/rotates/shears).
13
+ *
14
+ * In addition to other matrices, {@link Mat33}s can be used to transform {@link Vec3}s and {@link Vec2}s.
15
+ *
16
+ * For example, to move the point $(1, 1)$ by 5 units to the left and 6 units up,
17
+ * ```ts,runnable,console
18
+ * import {Mat33, Vec2} from '@js-draw/math';
19
+ *
20
+ * const moveLeftAndUp = Mat33.translation(Vec2.of(5, 6));
21
+ * console.log(moveLeftAndUp);
22
+ * ```
23
+ *
24
+ * This `moveLeftAndUp` matrix could then translate (move) a {@link Vec2} using
25
+ * {@link Mat33.transformVec2}:
26
+ *
27
+ * ```ts,runnable,console
28
+ * ---use-previous---
29
+ * ---visible---
30
+ * console.log(moveLeftAndUp.transformVec2(Vec2.of(1, 1)));
31
+ * console.log(moveLeftAndUp.transformVec2(Vec2.of(-1, 2)));
32
+ * ```
33
+ *
34
+ * It's also possible to create transformation matrices that scale and rotate.
35
+ * A single transform matrix can be created from multiple using matrix multiplication
36
+ * (see {@link Mat33.rightMul}):
37
+ *
38
+ * ```ts,runnable,console
39
+ * ---use-previous---
40
+ * ---visible---
41
+ * // Create a matrix by right multiplying.
42
+ * const scaleThenRotate =
43
+ * // The resultant matrix first scales by a factor of two
44
+ * Mat33.scaling2D(2).rightMul(
45
+ * // ...then rotates by pi/2 radians = 90 degrees.
46
+ * Mat33.zRotation(Math.PI / 2)
47
+ * );
48
+ * console.log(scaleThenRotate);
49
+ *
50
+ * // Use scaleThenRotate to scale then rotate a vector.
51
+ * console.log(scaleThenRotate.transformVec2(Vec2.unitX));
52
+ * ```
13
53
  */
14
54
  class Mat33 {
15
55
  /**
@@ -21,6 +61,9 @@ class Mat33 {
21
61
  * c1 & c2 & c3
22
62
  * \end{bmatrix}
23
63
  * $$
64
+ *
65
+ * Static constructor methods are also available.
66
+ * See {@link Mat33.scaling2D}, {@link Mat33.zRotation}, {@link Mat33.translation}, and {@link Mat33.fromCSSMatrix}.
24
67
  */
25
68
  constructor(a1, a2, a3, b1, b2, b3, c1, c2, c3) {
26
69
  this.a1 = a1;
@@ -131,6 +174,29 @@ class Mat33 {
131
174
  transposed() {
132
175
  return new Mat33(this.a1, this.b1, this.c1, this.a2, this.b2, this.c2, this.a3, this.b3, this.c3);
133
176
  }
177
+ /**
178
+ * [Right-multiplies](https://en.wikipedia.org/wiki/Matrix_multiplication) this by `other`.
179
+ *
180
+ * See also {@link transformVec3} and {@link transformVec2}.
181
+ *
182
+ * Example:
183
+ * ```ts,runnable,console
184
+ * import {Mat33, Vec2} from '@js-draw/math';
185
+ * console.log(Mat33.identity.rightMul(Mat33.identity));
186
+ *
187
+ * // Create a matrix by right multiplying.
188
+ * const scaleThenRotate =
189
+ * // The resultant matrix first scales by a factor of two
190
+ * Mat33.scaling2D(2).rightMul(
191
+ * // ...then rotates by pi/4 radians = 45 degrees.
192
+ * Mat33.zRotation(Math.PI / 4)
193
+ * );
194
+ * console.log(scaleThenRotate);
195
+ *
196
+ * // Use scaleThenRotate to scale then rotate a vector.
197
+ * console.log(scaleThenRotate.transformVec2(Vec2.unitX));
198
+ * ```
199
+ */
134
200
  rightMul(other) {
135
201
  other = other.transposed();
136
202
  const at = (row, col) => {
@@ -180,6 +246,15 @@ class Mat33 {
180
246
  }
181
247
  return true;
182
248
  }
249
+ /**
250
+ * Creates a human-readable representation of the matrix.
251
+ *
252
+ * Example:
253
+ * ```ts,runnable,console
254
+ * import { Mat33 } from '@js-draw/math';
255
+ * console.log(Mat33.identity.toString());
256
+ * ```
257
+ */
183
258
  toString() {
184
259
  let result = '';
185
260
  const maxColumnLens = [0, 0, 0];
@@ -228,6 +303,18 @@ class Mat33 {
228
303
  * result[1] = element at row zero, column 1
229
304
  * ...
230
305
  * ```
306
+ *
307
+ * Example:
308
+ * ```ts,runnable,console
309
+ * import { Mat33 } from '@js-draw/math';
310
+ * console.log(
311
+ * new Mat33(
312
+ * 1, 2, 3,
313
+ * 4, 5, 6,
314
+ * 7, 8, 9,
315
+ * )
316
+ * );
317
+ * ```
231
318
  */
232
319
  toArray() {
233
320
  return [
@@ -436,5 +523,6 @@ class Mat33 {
436
523
  }
437
524
  }
438
525
  exports.Mat33 = Mat33;
526
+ /** The 3x3 [identity matrix](https://en.wikipedia.org/wiki/Identity_matrix). */
439
527
  Mat33.identity = new Mat33(1, 0, 0, 0, 1, 0, 0, 0, 1);
440
528
  exports.default = Mat33;
@@ -1,42 +1,5 @@
1
- import Vec3 from './Vec3';
2
- /**
3
- * Utility functions that facilitate treating `Vec3`s as 2D vectors.
4
- *
5
- * @example
6
- * ```ts,runnable,console
7
- * import { Vec2 } from '@js-draw/math';
8
- * console.log(Vec2.of(1, 2));
9
- * ```
10
- */
11
- export declare namespace Vec2 {
12
- /**
13
- * Creates a `Vec2` from an x and y coordinate.
14
- *
15
- * For example,
16
- * ```ts
17
- * const v = Vec2.of(3, 4); // x=3, y=4.
18
- * ```
19
- */
20
- const of: (x: number, y: number) => Vec2;
21
- /**
22
- * Creates a `Vec2` from an object containing x and y coordinates.
23
- *
24
- * For example,
25
- * ```ts
26
- * const v1 = Vec2.ofXY({ x: 3, y: 4.5 });
27
- * const v2 = Vec2.ofXY({ x: -123.4, y: 1 });
28
- * ```
29
- */
30
- const ofXY: ({ x, y }: {
31
- x: number;
32
- y: number;
33
- }) => Vec2;
34
- /** A vector of length 1 in the X direction (→). */
35
- const unitX: Vec3;
36
- /** A vector of length 1 in the Y direction (↑). */
37
- const unitY: Vec3;
38
- /** The zero vector: A vector with x=0, y=0. */
39
- const zero: Vec3;
40
- }
1
+ import { Vec3, Vec2 } from './Vec3';
41
2
  export type Point2 = Vec3;
42
3
  export type Vec2 = Vec3;
4
+ export { Vec3, Vec2 };
5
+ export default Vec2;
package/dist/cjs/Vec2.js CHANGED
@@ -1,48 +1,10 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.Vec2 = void 0;
7
- const Vec3_1 = __importDefault(require("./Vec3"));
8
- /**
9
- * Utility functions that facilitate treating `Vec3`s as 2D vectors.
10
- *
11
- * @example
12
- * ```ts,runnable,console
13
- * import { Vec2 } from '@js-draw/math';
14
- * console.log(Vec2.of(1, 2));
15
- * ```
16
- */
17
- var Vec2;
18
- (function (Vec2) {
19
- /**
20
- * Creates a `Vec2` from an x and y coordinate.
21
- *
22
- * For example,
23
- * ```ts
24
- * const v = Vec2.of(3, 4); // x=3, y=4.
25
- * ```
26
- */
27
- Vec2.of = (x, y) => {
28
- return Vec3_1.default.of(x, y, 0);
29
- };
30
- /**
31
- * Creates a `Vec2` from an object containing x and y coordinates.
32
- *
33
- * For example,
34
- * ```ts
35
- * const v1 = Vec2.ofXY({ x: 3, y: 4.5 });
36
- * const v2 = Vec2.ofXY({ x: -123.4, y: 1 });
37
- * ```
38
- */
39
- Vec2.ofXY = ({ x, y }) => {
40
- return Vec3_1.default.of(x, y, 0);
41
- };
42
- /** A vector of length 1 in the X direction (→). */
43
- Vec2.unitX = Vec2.of(1, 0);
44
- /** A vector of length 1 in the Y direction (↑). */
45
- Vec2.unitY = Vec2.of(0, 1);
46
- /** The zero vector: A vector with x=0, y=0. */
47
- Vec2.zero = Vec2.of(0, 0);
48
- })(Vec2 || (exports.Vec2 = Vec2 = {}));
3
+ exports.Vec2 = exports.Vec3 = void 0;
4
+ // Internally, we define Vec2 as a namespace within Vec3 --
5
+ // this allows referencing Vec2s from Vec3 constructors without
6
+ // cyclic references.
7
+ const Vec3_1 = require("./Vec3");
8
+ Object.defineProperty(exports, "Vec3", { enumerable: true, get: function () { return Vec3_1.Vec3; } });
9
+ Object.defineProperty(exports, "Vec2", { enumerable: true, get: function () { return Vec3_1.Vec2; } });
10
+ exports.default = Vec3_1.Vec2;
@@ -17,22 +17,23 @@
17
17
  * console.log('As an array:', Vec3.unitZ.asArray());
18
18
  * ```
19
19
  */
20
- export declare class Vec3 {
20
+ export interface Vec3 {
21
21
  readonly x: number;
22
22
  readonly y: number;
23
23
  readonly z: number;
24
- private constructor();
25
- /** Returns the x, y components of this. */
26
- get xy(): {
24
+ /**
25
+ * Returns the x, y components of this.
26
+ * May be implemented as a getter method.
27
+ */
28
+ readonly xy: {
27
29
  x: number;
28
30
  y: number;
29
31
  };
30
- /** Construct a vector from three components. */
31
- static of(x: number, y: number, z: number): Vec3;
32
- /** Returns this' `idx`th component. For example, `Vec3.of(1, 2, 3).at(1) → 2`. */
33
- at(idx: number): number;
34
- /** Alias for this.magnitude. */
32
+ /** Returns the vector's `idx`th component. For example, `Vec3.of(1, 2, 3).at(1) → 2`. */
33
+ at(i: number): number;
34
+ /** Alias for `.magnitude`. */
35
35
  length(): number;
36
+ /** Returns the length of this vector in ℝ^3. */
36
37
  magnitude(): number;
37
38
  magnitudeSquared(): number;
38
39
  /**
@@ -41,7 +42,7 @@ export declare class Vec3 {
41
42
  *
42
43
  * Equivalent to `.minus(p).magnitudeSquared()`.
43
44
  */
44
- squareDistanceTo(p: Vec3): number;
45
+ squareDistanceTo(other: Vec3): number;
45
46
  /**
46
47
  * Interpreting this vector as a point in ℝ³, returns the distance to the point
47
48
  * `p`.
@@ -90,10 +91,17 @@ export declare class Vec3 {
90
91
  normalizedOrZero(): Vec3;
91
92
  /** @returns A copy of `this` multiplied by a scalar. */
92
93
  times(c: number): Vec3;
94
+ /** Performs vector addition. */
93
95
  plus(v: Vec3): Vec3;
94
96
  minus(v: Vec3): Vec3;
95
- dot(other: Vec3): number;
96
- cross(other: Vec3): Vec3;
97
+ /**
98
+ * Computes the scalar product between this and `v`.
99
+ *
100
+ * In particular, `a.dot(b)` is equivalent to `a.x * b.x + a.y * b.y + a.z * b.z`.
101
+ */
102
+ dot(v: Vec3): number;
103
+ /** Computes the cross product between this and `v` */
104
+ cross(v: Vec3): Vec3;
97
105
  /**
98
106
  * If `other` is a `Vec3`, multiplies `this` component-wise by `other`. Otherwise,
99
107
  * if `other is a `number`, returns the result of scalar multiplication.
@@ -154,11 +162,99 @@ export declare class Vec3 {
154
162
  * Vec3.of(1, 2, 3).eq(Vec3.of(4, 5, 6), 2.99); // → false
155
163
  * ```
156
164
  */
165
+ eq(other: Vec3, tolerance?: number): boolean;
166
+ toString(): string;
167
+ }
168
+ declare class Vec2Impl implements Vec3 {
169
+ readonly x: number;
170
+ readonly y: number;
171
+ constructor(x: number, y: number);
172
+ get z(): number;
173
+ get xy(): {
174
+ x: number;
175
+ y: number;
176
+ };
177
+ at(idx: number): number;
178
+ length(): number;
179
+ magnitude(): number;
180
+ magnitudeSquared(): number;
181
+ squareDistanceTo(p: Vec3): number;
182
+ distanceTo(p: Vec3): number;
183
+ maximumEntryMagnitude(): number;
184
+ angle(): number;
185
+ normalized(): Vec3;
186
+ normalizedOrZero(): Vec3;
187
+ times(c: number): Vec3;
188
+ plus(v: Vec3): Vec3;
189
+ minus(v: Vec3): Vec3;
190
+ dot(other: Vec3): number;
191
+ cross(other: Vec3): Vec3;
192
+ scale(other: Vec3 | number): Vec3;
193
+ orthog(): Vec3;
194
+ extend(distance: number, direction: Vec3): Vec3;
195
+ lerp(target: Vec3, fractionTo: number): Vec3;
196
+ zip(other: Vec3, zip: (componentInThis: number, componentInOther: number) => number): Vec3;
197
+ map(fn: (component: number, index: number) => number): Vec3;
198
+ asArray(): [number, number, number];
157
199
  eq(other: Vec3, fuzz?: number): boolean;
158
200
  toString(): string;
159
- static unitX: Vec3;
160
- static unitY: Vec3;
161
- static unitZ: Vec3;
162
- static zero: Vec3;
201
+ }
202
+ /**
203
+ * A `Vec2` is a `Vec3` optimized for working in a plane. As such, they have an
204
+ * always-zero `z` component.
205
+ *
206
+ * ```ts,runnable,console
207
+ * import { Vec2 } from '@js-draw/math';
208
+ * console.log(Vec2.of(1, 2));
209
+ * ```
210
+ */
211
+ export declare namespace Vec2 {
212
+ /**
213
+ * Creates a `Vec2` from an x and y coordinate.
214
+ *
215
+ * @example
216
+ * ```ts,runnable,console
217
+ * import { Vec2 } from '@js-draw/math';
218
+ * const v = Vec2.of(3, 4); // x=3, y=4.
219
+ * ```
220
+ */
221
+ const of: (x: number, y: number) => Vec2Impl;
222
+ /**
223
+ * Creates a `Vec2` from an object containing `x` and `y` coordinates.
224
+ *
225
+ * @example
226
+ * ```ts,runnable,console
227
+ * import { Vec2 } from '@js-draw/math';
228
+ * const v1 = Vec2.ofXY({ x: 3, y: 4.5 });
229
+ * const v2 = Vec2.ofXY({ x: -123.4, y: 1 });
230
+ * ```
231
+ */
232
+ const ofXY: ({ x, y }: {
233
+ x: number;
234
+ y: number;
235
+ }) => Vec2Impl;
236
+ /** A vector of length 1 in the X direction (→). */
237
+ const unitX: Vec2Impl;
238
+ /** A vector of length 1 in the Y direction (↑). */
239
+ const unitY: Vec2Impl;
240
+ /** The zero vector: A vector with x=0, y=0. */
241
+ const zero: Vec2Impl;
242
+ }
243
+ export declare namespace Vec3 {
244
+ /**
245
+ * Construct a vector from three components.
246
+ *
247
+ * @example
248
+ * ```ts,runnable,console
249
+ * import { Vec3 } from '@js-draw/math';
250
+ * const v1 = Vec3.of(1, 2, 3);
251
+ * ```
252
+ */
253
+ const of: (x: number, y: number, z: number) => Vec3;
254
+ const unitX: Vec2Impl;
255
+ const unitY: Vec2Impl;
256
+ const zero: Vec2Impl;
257
+ /** A vector of length 1 in the z direction. */
258
+ const unitZ: Vec3;
163
259
  }
164
260
  export default Vec3;