@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/src/Mat33.ts CHANGED
@@ -1,6 +1,9 @@
1
1
  import { Point2, Vec2 } from './Vec2';
2
2
  import Vec3 from './Vec3';
3
3
 
4
+ /**
5
+ * See {@link Mat33.toArray}.
6
+ */
4
7
  export type Mat33Array = [
5
8
  number, number, number,
6
9
  number, number, number,
@@ -11,6 +14,46 @@ export type Mat33Array = [
11
14
  * Represents a three dimensional linear transformation or
12
15
  * a two-dimensional affine transformation. (An affine transformation scales/rotates/shears
13
16
  * **and** translates while a linear transformation just scales/rotates/shears).
17
+ *
18
+ * In addition to other matrices, {@link Mat33}s can be used to transform {@link Vec3}s and {@link Vec2}s.
19
+ *
20
+ * For example, to move the point $(1, 1)$ by 5 units to the left and 6 units up,
21
+ * ```ts,runnable,console
22
+ * import {Mat33, Vec2} from '@js-draw/math';
23
+ *
24
+ * const moveLeftAndUp = Mat33.translation(Vec2.of(5, 6));
25
+ * console.log(moveLeftAndUp);
26
+ * ```
27
+ *
28
+ * This `moveLeftAndUp` matrix could then translate (move) a {@link Vec2} using
29
+ * {@link Mat33.transformVec2}:
30
+ *
31
+ * ```ts,runnable,console
32
+ * ---use-previous---
33
+ * ---visible---
34
+ * console.log(moveLeftAndUp.transformVec2(Vec2.of(1, 1)));
35
+ * console.log(moveLeftAndUp.transformVec2(Vec2.of(-1, 2)));
36
+ * ```
37
+ *
38
+ * It's also possible to create transformation matrices that scale and rotate.
39
+ * A single transform matrix can be created from multiple using matrix multiplication
40
+ * (see {@link Mat33.rightMul}):
41
+ *
42
+ * ```ts,runnable,console
43
+ * ---use-previous---
44
+ * ---visible---
45
+ * // Create a matrix by right multiplying.
46
+ * const scaleThenRotate =
47
+ * // The resultant matrix first scales by a factor of two
48
+ * Mat33.scaling2D(2).rightMul(
49
+ * // ...then rotates by pi/2 radians = 90 degrees.
50
+ * Mat33.zRotation(Math.PI / 2)
51
+ * );
52
+ * console.log(scaleThenRotate);
53
+ *
54
+ * // Use scaleThenRotate to scale then rotate a vector.
55
+ * console.log(scaleThenRotate.transformVec2(Vec2.unitX));
56
+ * ```
14
57
  */
15
58
  export class Mat33 {
16
59
  private readonly rows: Vec3[];
@@ -24,6 +67,9 @@ export class Mat33 {
24
67
  * c1 & c2 & c3
25
68
  * \end{bmatrix}
26
69
  * $$
70
+ *
71
+ * Static constructor methods are also available.
72
+ * See {@link Mat33.scaling2D}, {@link Mat33.zRotation}, {@link Mat33.translation}, and {@link Mat33.fromCSSMatrix}.
27
73
  */
28
74
  public constructor(
29
75
  public readonly a1: number,
@@ -63,6 +109,7 @@ export class Mat33 {
63
109
  );
64
110
  }
65
111
 
112
+ /** The 3x3 [identity matrix](https://en.wikipedia.org/wiki/Identity_matrix). */
66
113
  public static identity = new Mat33(
67
114
  1, 0, 0,
68
115
  0, 1, 0,
@@ -178,6 +225,29 @@ export class Mat33 {
178
225
  );
179
226
  }
180
227
 
228
+ /**
229
+ * [Right-multiplies](https://en.wikipedia.org/wiki/Matrix_multiplication) this by `other`.
230
+ *
231
+ * See also {@link transformVec3} and {@link transformVec2}.
232
+ *
233
+ * Example:
234
+ * ```ts,runnable,console
235
+ * import {Mat33, Vec2} from '@js-draw/math';
236
+ * console.log(Mat33.identity.rightMul(Mat33.identity));
237
+ *
238
+ * // Create a matrix by right multiplying.
239
+ * const scaleThenRotate =
240
+ * // The resultant matrix first scales by a factor of two
241
+ * Mat33.scaling2D(2).rightMul(
242
+ * // ...then rotates by pi/4 radians = 45 degrees.
243
+ * Mat33.zRotation(Math.PI / 4)
244
+ * );
245
+ * console.log(scaleThenRotate);
246
+ *
247
+ * // Use scaleThenRotate to scale then rotate a vector.
248
+ * console.log(scaleThenRotate.transformVec2(Vec2.unitX));
249
+ * ```
250
+ */
181
251
  public rightMul(other: Mat33): Mat33 {
182
252
  other = other.transposed();
183
253
 
@@ -245,6 +315,15 @@ export class Mat33 {
245
315
  return true;
246
316
  }
247
317
 
318
+ /**
319
+ * Creates a human-readable representation of the matrix.
320
+ *
321
+ * Example:
322
+ * ```ts,runnable,console
323
+ * import { Mat33 } from '@js-draw/math';
324
+ * console.log(Mat33.identity.toString());
325
+ * ```
326
+ */
248
327
  public toString(): string {
249
328
  let result = '';
250
329
  const maxColumnLens = [ 0, 0, 0 ];
@@ -297,6 +376,18 @@ export class Mat33 {
297
376
  * result[1] = element at row zero, column 1
298
377
  * ...
299
378
  * ```
379
+ *
380
+ * Example:
381
+ * ```ts,runnable,console
382
+ * import { Mat33 } from '@js-draw/math';
383
+ * console.log(
384
+ * new Mat33(
385
+ * 1, 2, 3,
386
+ * 4, 5, 6,
387
+ * 7, 8, 9,
388
+ * )
389
+ * );
390
+ * ```
300
391
  */
301
392
  public toArray(): Mat33Array {
302
393
  return [
@@ -481,7 +572,7 @@ export class Mat33 {
481
572
 
482
573
  return argNumber;
483
574
  });
484
- return parsed.filter(n => n !== null) as number[];
575
+ return parsed.filter(n => n !== null);
485
576
  };
486
577
 
487
578
 
package/src/Vec2.test.ts CHANGED
@@ -8,10 +8,12 @@ describe('Vec2', () => {
8
8
 
9
9
  it('Addition', () => {
10
10
  expect(Vec2.of(1, 2).plus(Vec2.of(3, 4))).objEq(Vec2.of(4, 6));
11
+ expect(Vec2.of(1, 2).plus(Vec3.of(3, 4, 1))).objEq(Vec3.of(4, 6, 1));
11
12
  });
12
13
 
13
14
  it('Multiplication', () => {
14
15
  expect(Vec2.of(1, -1).times(22)).objEq(Vec2.of(22, -22));
16
+ expect(Vec2.of(1, -1).scale(Vec3.of(-1, 2, 3))).objEq(Vec2.of(-1, -2));
15
17
  });
16
18
 
17
19
  it('More complicated expressions', () => {
@@ -23,8 +25,8 @@ describe('Vec2', () => {
23
25
  });
24
26
 
25
27
  it('Perpindicular', () => {
26
- const fuzz = 0.001;
27
- expect(Vec2.unitX.cross(Vec3.unitZ)).objEq(Vec2.unitY.times(-1), fuzz);
28
- expect(Vec2.unitX.orthog()).objEq(Vec2.unitY, fuzz);
28
+ const tolerance = 0.001;
29
+ expect(Vec2.unitX.cross(Vec3.unitZ)).objEq(Vec2.unitY.times(-1), tolerance);
30
+ expect(Vec2.unitX.orthog()).objEq(Vec2.unitY, tolerance);
29
31
  });
30
32
  });
package/src/Vec2.ts CHANGED
@@ -1,49 +1,9 @@
1
- import Vec3 from './Vec3';
2
-
3
- /**
4
- * Utility functions that facilitate treating `Vec3`s as 2D vectors.
5
- *
6
- * @example
7
- * ```ts,runnable,console
8
- * import { Vec2 } from '@js-draw/math';
9
- * console.log(Vec2.of(1, 2));
10
- * ```
11
- */
12
- export namespace Vec2 {
13
- /**
14
- * Creates a `Vec2` from an x and y coordinate.
15
- *
16
- * For example,
17
- * ```ts
18
- * const v = Vec2.of(3, 4); // x=3, y=4.
19
- * ```
20
- */
21
- export const of = (x: number, y: number): Vec2 => {
22
- return Vec3.of(x, y, 0);
23
- };
24
-
25
- /**
26
- * Creates a `Vec2` from an object containing x and y coordinates.
27
- *
28
- * For example,
29
- * ```ts
30
- * const v1 = Vec2.ofXY({ x: 3, y: 4.5 });
31
- * const v2 = Vec2.ofXY({ x: -123.4, y: 1 });
32
- * ```
33
- */
34
- export const ofXY = ({x, y}: { x: number, y: number }): Vec2 => {
35
- return Vec3.of(x, y, 0);
36
- };
37
-
38
- /** A vector of length 1 in the X direction (→). */
39
- export const unitX = Vec2.of(1, 0);
40
-
41
- /** A vector of length 1 in the Y direction (↑). */
42
- export const unitY = Vec2.of(0, 1);
43
-
44
- /** The zero vector: A vector with x=0, y=0. */
45
- export const zero = Vec2.of(0, 0);
46
- }
1
+ // Internally, we define Vec2 as a namespace within Vec3 --
2
+ // this allows referencing Vec2s from Vec3 constructors without
3
+ // cyclic references.
4
+ import { Vec3, Vec2 } from './Vec3';
47
5
 
48
6
  export type Point2 = Vec3;
49
- export type Vec2 = Vec3; // eslint-disable-line
7
+ export type Vec2 = Vec3;
8
+ export { Vec3, Vec2 };
9
+ export default Vec2;