@js-draw/math 1.21.3 → 1.23.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. package/build-config.json +1 -1
  2. package/dist/cjs/Color4.d.ts +24 -1
  3. package/dist/cjs/Color4.js +35 -3
  4. package/dist/cjs/Mat33.d.ts +21 -11
  5. package/dist/cjs/Mat33.js +28 -24
  6. package/dist/cjs/Vec3.d.ts +12 -3
  7. package/dist/cjs/Vec3.js +20 -9
  8. package/dist/cjs/lib.d.ts +3 -0
  9. package/dist/cjs/lib.js +3 -0
  10. package/dist/cjs/shapes/BezierJSWrapper.d.ts +2 -0
  11. package/dist/cjs/shapes/BezierJSWrapper.js +22 -13
  12. package/dist/cjs/shapes/LineSegment2.js +13 -17
  13. package/dist/cjs/shapes/Parameterized2DShape.js +1 -1
  14. package/dist/cjs/shapes/Path.d.ts +1 -0
  15. package/dist/cjs/shapes/Path.js +50 -47
  16. package/dist/cjs/shapes/QuadraticBezier.d.ts +19 -2
  17. package/dist/cjs/shapes/QuadraticBezier.js +26 -3
  18. package/dist/cjs/shapes/Rect2.d.ts +13 -0
  19. package/dist/cjs/shapes/Rect2.js +35 -16
  20. package/dist/cjs/shapes/Triangle.js +4 -5
  21. package/dist/cjs/utils/convexHull2Of.js +3 -3
  22. package/dist/mjs/Color4.d.ts +24 -1
  23. package/dist/mjs/Color4.mjs +35 -3
  24. package/dist/mjs/Mat33.d.ts +21 -11
  25. package/dist/mjs/Mat33.mjs +28 -24
  26. package/dist/mjs/Vec3.d.ts +12 -3
  27. package/dist/mjs/Vec3.mjs +20 -9
  28. package/dist/mjs/lib.d.ts +3 -0
  29. package/dist/mjs/lib.mjs +3 -0
  30. package/dist/mjs/shapes/BezierJSWrapper.d.ts +2 -0
  31. package/dist/mjs/shapes/BezierJSWrapper.mjs +22 -13
  32. package/dist/mjs/shapes/LineSegment2.mjs +13 -17
  33. package/dist/mjs/shapes/Parameterized2DShape.mjs +1 -1
  34. package/dist/mjs/shapes/Path.d.ts +1 -0
  35. package/dist/mjs/shapes/Path.mjs +50 -47
  36. package/dist/mjs/shapes/QuadraticBezier.d.ts +19 -2
  37. package/dist/mjs/shapes/QuadraticBezier.mjs +26 -3
  38. package/dist/mjs/shapes/Rect2.d.ts +13 -0
  39. package/dist/mjs/shapes/Rect2.mjs +35 -16
  40. package/dist/mjs/shapes/Triangle.mjs +4 -5
  41. package/dist/mjs/utils/convexHull2Of.mjs +3 -3
  42. package/dist-test/test_imports/test-require.cjs +1 -1
  43. package/package.json +3 -3
  44. package/src/Color4.test.ts +21 -21
  45. package/src/Color4.ts +61 -18
  46. package/src/Mat33.fromCSSMatrix.test.ts +32 -46
  47. package/src/Mat33.test.ts +64 -102
  48. package/src/Mat33.ts +81 -104
  49. package/src/Vec2.test.ts +3 -3
  50. package/src/Vec3.test.ts +2 -3
  51. package/src/Vec3.ts +46 -61
  52. package/src/lib.ts +3 -2
  53. package/src/polynomial/solveQuadratic.test.ts +39 -13
  54. package/src/polynomial/solveQuadratic.ts +5 -6
  55. package/src/rounding/cleanUpNumber.test.ts +1 -1
  56. package/src/rounding/constants.ts +1 -3
  57. package/src/rounding/getLenAfterDecimal.ts +1 -2
  58. package/src/rounding/lib.ts +1 -2
  59. package/src/rounding/toRoundedString.test.ts +1 -1
  60. package/src/rounding/toStringOfSamePrecision.test.ts +1 -2
  61. package/src/rounding/toStringOfSamePrecision.ts +1 -1
  62. package/src/shapes/BezierJSWrapper.ts +56 -37
  63. package/src/shapes/CubicBezier.ts +3 -3
  64. package/src/shapes/LineSegment2.test.ts +24 -17
  65. package/src/shapes/LineSegment2.ts +26 -29
  66. package/src/shapes/Parameterized2DShape.ts +5 -4
  67. package/src/shapes/Path.fromString.test.ts +5 -5
  68. package/src/shapes/Path.test.ts +122 -120
  69. package/src/shapes/Path.toString.test.ts +7 -7
  70. package/src/shapes/Path.ts +379 -352
  71. package/src/shapes/PointShape2D.ts +3 -3
  72. package/src/shapes/QuadraticBezier.test.ts +27 -21
  73. package/src/shapes/QuadraticBezier.ts +26 -11
  74. package/src/shapes/Rect2.test.ts +44 -75
  75. package/src/shapes/Rect2.ts +47 -35
  76. package/src/shapes/Triangle.test.ts +31 -29
  77. package/src/shapes/Triangle.ts +17 -18
  78. package/src/utils/convexHull2Of.test.ts +54 -15
  79. package/src/utils/convexHull2Of.ts +9 -7
  80. package/tsconfig.json +1 -3
  81. package/typedoc.json +2 -2
package/src/Mat33.ts CHANGED
@@ -4,11 +4,7 @@ import Vec3 from './Vec3';
4
4
  /**
5
5
  * See {@link Mat33.toArray}.
6
6
  */
7
- export type Mat33Array = [
8
- number, number, number,
9
- number, number, number,
10
- number, number, number,
11
- ];
7
+ export type Mat33Array = [number, number, number, number, number, number, number, number, number];
12
8
 
13
9
  /**
14
10
  * Represents a three dimensional linear transformation or
@@ -82,13 +78,9 @@ export class Mat33 {
82
78
 
83
79
  public readonly c1: number,
84
80
  public readonly c2: number,
85
- public readonly c3: number
81
+ public readonly c3: number,
86
82
  ) {
87
- this.rows = [
88
- Vec3.of(a1, a2, a3),
89
- Vec3.of(b1, b2, b3),
90
- Vec3.of(c1, c2, c3),
91
- ];
83
+ this.rows = [Vec3.of(a1, a2, a3), Vec3.of(b1, b2, b3), Vec3.of(c1, c2, c3)];
92
84
  }
93
85
 
94
86
  /**
@@ -102,19 +94,11 @@ export class Mat33 {
102
94
  * $$
103
95
  */
104
96
  public static ofRows(r1: Vec3, r2: Vec3, r3: Vec3): Mat33 {
105
- return new Mat33(
106
- r1.x, r1.y, r1.z,
107
- r2.x, r2.y, r2.z,
108
- r3.x, r3.y, r3.z
109
- );
97
+ return new Mat33(r1.x, r1.y, r1.z, r2.x, r2.y, r2.z, r3.x, r3.y, r3.z);
110
98
  }
111
99
 
112
100
  /** The 3x3 [identity matrix](https://en.wikipedia.org/wiki/Identity_matrix). */
113
- public static identity = new Mat33(
114
- 1, 0, 0,
115
- 0, 1, 0,
116
- 0, 0, 1
117
- );
101
+ public static identity = new Mat33(1, 0, 0, 0, 1, 0, 0, 0, 1);
118
102
 
119
103
  /**
120
104
  * Either returns the inverse of this, or, if this matrix is singular/uninvertable,
@@ -131,23 +115,15 @@ export class Mat33 {
131
115
  return this.computeInverse() !== null;
132
116
  }
133
117
 
134
- private cachedInverse: Mat33|undefined|null = undefined;
135
- private computeInverse(): Mat33|null {
118
+ private cachedInverse: Mat33 | undefined | null = undefined;
119
+ private computeInverse(): Mat33 | null {
136
120
  if (this.cachedInverse !== undefined) {
137
121
  return this.cachedInverse;
138
122
  }
139
123
 
140
- const toIdentity = [
141
- this.rows[0],
142
- this.rows[1],
143
- this.rows[2],
144
- ];
124
+ const toIdentity = [this.rows[0], this.rows[1], this.rows[2]];
145
125
 
146
- const toResult = [
147
- Vec3.unitX,
148
- Vec3.unitY,
149
- Vec3.unitZ,
150
- ];
126
+ const toResult = [Vec3.unitX, Vec3.unitY, Vec3.unitZ];
151
127
 
152
128
  // Convert toIdentity to the identity matrix and
153
129
  // toResult to the inverse through elementary row operations
@@ -199,29 +175,27 @@ export class Mat33 {
199
175
  for (let i = 1; i <= 2; i++) {
200
176
  const otherRowIdx = (cursor + i) % 3;
201
177
  scale = -toIdentity[otherRowIdx].at(cursor);
202
- toIdentity[otherRowIdx] = toIdentity[otherRowIdx].plus(
203
- cursorToIdentityRow.times(scale)
204
- );
205
- toResult[otherRowIdx] = toResult[otherRowIdx].plus(
206
- cursorToResultRow.times(scale)
207
- );
178
+ toIdentity[otherRowIdx] = toIdentity[otherRowIdx].plus(cursorToIdentityRow.times(scale));
179
+ toResult[otherRowIdx] = toResult[otherRowIdx].plus(cursorToResultRow.times(scale));
208
180
  }
209
181
  }
210
182
 
211
- const inverse = Mat33.ofRows(
212
- toResult[0],
213
- toResult[1],
214
- toResult[2]
215
- );
183
+ const inverse = Mat33.ofRows(toResult[0], toResult[1], toResult[2]);
216
184
  this.cachedInverse = inverse;
217
185
  return inverse;
218
186
  }
219
187
 
220
188
  public transposed(): Mat33 {
221
189
  return new Mat33(
222
- this.a1, this.b1, this.c1,
223
- this.a2, this.b2, this.c2,
224
- this.a3, this.b3, this.c3
190
+ this.a1,
191
+ this.b1,
192
+ this.c1,
193
+ this.a2,
194
+ this.b2,
195
+ this.c2,
196
+ this.a3,
197
+ this.b3,
198
+ this.c3,
225
199
  );
226
200
  }
227
201
 
@@ -256,9 +230,15 @@ export class Mat33 {
256
230
  };
257
231
 
258
232
  return new Mat33(
259
- at(0, 0), at(0, 1), at(0, 2),
260
- at(1, 0), at(1, 1), at(1, 2),
261
- at(2, 0), at(2, 1), at(2, 2)
233
+ at(0, 0),
234
+ at(0, 1),
235
+ at(0, 2),
236
+ at(1, 0),
237
+ at(1, 1),
238
+ at(1, 2),
239
+ at(2, 0),
240
+ at(2, 1),
241
+ at(2, 2),
262
242
  );
263
243
  }
264
244
 
@@ -288,11 +268,7 @@ export class Mat33 {
288
268
  * This is the standard way of transforming vectors in ℝ³.
289
269
  */
290
270
  public transformVec3(other: Vec3): Vec3 {
291
- return Vec3.of(
292
- this.rows[0].dot(other),
293
- this.rows[1].dot(other),
294
- this.rows[2].dot(other)
295
- );
271
+ return Vec3.of(this.rows[0].dot(other), this.rows[1].dot(other), this.rows[2].dot(other));
296
272
  }
297
273
 
298
274
  /** @returns true iff this is the identity matrix. */
@@ -326,7 +302,7 @@ export class Mat33 {
326
302
  */
327
303
  public toString(): string {
328
304
  let result = '';
329
- const maxColumnLens = [ 0, 0, 0 ];
305
+ const maxColumnLens = [0, 0, 0];
330
306
 
331
307
  // Determine the longest item in each column so we can pad the others to that
332
308
  // length.
@@ -390,11 +366,7 @@ export class Mat33 {
390
366
  * ```
391
367
  */
392
368
  public toArray(): Mat33Array {
393
- return [
394
- this.a1, this.a2, this.a3,
395
- this.b1, this.b2, this.b3,
396
- this.c1, this.c2, this.c3,
397
- ];
369
+ return [this.a1, this.a2, this.a3, this.b1, this.b2, this.b3, this.c1, this.c2, this.c3];
398
370
  }
399
371
 
400
372
  /**
@@ -413,11 +385,17 @@ export class Mat33 {
413
385
  * // ⎣ 6, 7, 8 ⎦
414
386
  * ```
415
387
  */
416
- public mapEntries(mapping: (component: number, rowcol: [number, number])=>number): Mat33 {
388
+ public mapEntries(mapping: (component: number, rowcol: [number, number]) => number): Mat33 {
417
389
  return new Mat33(
418
- mapping(this.a1, [0, 0]), mapping(this.a2, [0, 1]), mapping(this.a3, [0, 2]),
419
- mapping(this.b1, [1, 0]), mapping(this.b2, [1, 1]), mapping(this.b3, [1, 2]),
420
- mapping(this.c1, [2, 0]), mapping(this.c2, [2, 1]), mapping(this.c3, [2, 2]),
390
+ mapping(this.a1, [0, 0]),
391
+ mapping(this.a2, [0, 1]),
392
+ mapping(this.a3, [0, 2]),
393
+ mapping(this.b1, [1, 0]),
394
+ mapping(this.b2, [1, 1]),
395
+ mapping(this.b3, [1, 2]),
396
+ mapping(this.c1, [2, 0]),
397
+ mapping(this.c2, [2, 1]),
398
+ mapping(this.c3, [2, 2]),
421
399
  );
422
400
  }
423
401
 
@@ -428,11 +406,7 @@ export class Mat33 {
428
406
 
429
407
  /** Returns the `idx`-th column (`idx` is 0-indexed). */
430
408
  public getColumn(idx: number) {
431
- return Vec3.of(
432
- this.rows[0].at(idx),
433
- this.rows[1].at(idx),
434
- this.rows[2].at(idx),
435
- );
409
+ return Vec3.of(this.rows[0].at(idx), this.rows[1].at(idx), this.rows[2].at(idx));
436
410
  }
437
411
 
438
412
  /** Returns the magnitude of the entry with the largest entry */
@@ -463,13 +437,29 @@ export class Mat33 {
463
437
  // Vec2s z = 1. As such,
464
438
  // outVec2.x = inVec2.x * 1 + inVec2.y * 0 + 1 * amount.x
465
439
  // ...
466
- return new Mat33(
467
- 1, 0, amount.x,
468
- 0, 1, amount.y,
469
- 0, 0, 1
470
- );
440
+ return new Mat33(1, 0, amount.x, 0, 1, amount.y, 0, 0, 1);
471
441
  }
472
442
 
443
+ /**
444
+ * Creates a matrix for rotating `Vec2`s about `center` by some number of `radians`.
445
+ *
446
+ * For this function, {@link Vec2}s are considered to be points in 2D space.
447
+ *
448
+ * For example,
449
+ * ```ts,runnable,console
450
+ * import { Mat33, Vec2 } from '@js-draw/math';
451
+ *
452
+ * const halfCircle = Math.PI; // PI radians = 180 degrees = 1/2 circle
453
+ * const center = Vec2.of(1, 1); // The point (1,1)
454
+ * const rotationMatrix = Mat33.zRotation(halfCircle, center);
455
+ *
456
+ * console.log(
457
+ * 'Rotating (0,0) 180deg about', center, 'results in',
458
+ * // Rotates (0,0)
459
+ * rotationMatrix.transformVec2(Vec2.zero),
460
+ * );
461
+ * ```
462
+ */
473
463
  public static zRotation(radians: number, center: Point2 = Vec2.zero): Mat33 {
474
464
  if (radians === 0) {
475
465
  return Mat33.identity;
@@ -481,15 +471,11 @@ export class Mat33 {
481
471
  // Translate everything so that rotation is about the origin
482
472
  let result = Mat33.translation(center);
483
473
 
484
- result = result.rightMul(new Mat33(
485
- cos, -sin, 0,
486
- sin, cos, 0,
487
- 0, 0, 1
488
- ));
474
+ result = result.rightMul(new Mat33(cos, -sin, 0, sin, cos, 0, 0, 0, 1));
489
475
  return result.rightMul(Mat33.translation(center.times(-1)));
490
476
  }
491
477
 
492
- public static scaling2D(amount: number|Vec2, center: Point2 = Vec2.zero): Mat33 {
478
+ public static scaling2D(amount: number | Vec2, center: Point2 = Vec2.zero): Mat33 {
493
479
  let result = Mat33.translation(center);
494
480
  let xAmount, yAmount;
495
481
 
@@ -501,11 +487,7 @@ export class Mat33 {
501
487
  yAmount = amount.y;
502
488
  }
503
489
 
504
- result = result.rightMul(new Mat33(
505
- xAmount, 0, 0,
506
- 0, yAmount, 0,
507
- 0, 0, 1
508
- ));
490
+ result = result.rightMul(new Mat33(xAmount, 0, 0, 0, yAmount, 0, 0, 0, 1));
509
491
 
510
492
  // Translate such that [center] goes to (0, 0)
511
493
  return result.rightMul(Mat33.translation(center.times(-1)));
@@ -536,7 +518,7 @@ export class Mat33 {
536
518
  }
537
519
 
538
520
  const parseArguments = (argumentString: string): number[] => {
539
- const parsed = argumentString.split(/[, \t\n]+/g).map(argString => {
521
+ const parsed = argumentString.split(/[, \t\n]+/g).map((argString) => {
540
522
  // Handle trailing spaces/commands
541
523
  if (argString.trim() === '') {
542
524
  return null;
@@ -549,18 +531,16 @@ export class Mat33 {
549
531
  }
550
532
 
551
533
  // Remove trailing px units.
552
- argString = argString.replace(/px$/ig, '');
534
+ argString = argString.replace(/px$/gi, '');
553
535
 
554
536
  const numberExp = /^[-]?\d*(?:\.\d*)?(?:[eE][-+]?\d+)?$/i;
555
537
 
556
538
  if (!numberExp.exec(argString)) {
557
539
  throw new Error(
558
- `All arguments to transform functions must be numeric (state: ${
559
- JSON.stringify({
560
- currentArgument: argString,
561
- allArguments: argumentString,
562
- })
563
- })`
540
+ `All arguments to transform functions must be numeric (state: ${JSON.stringify({
541
+ currentArgument: argString,
542
+ allArguments: argumentString,
543
+ })})`,
564
544
  );
565
545
  }
566
546
 
@@ -572,10 +552,9 @@ export class Mat33 {
572
552
 
573
553
  return argNumber;
574
554
  });
575
- return parsed.filter(n => n !== null);
555
+ return parsed.filter((n) => n !== null);
576
556
  };
577
557
 
578
-
579
558
  const keywordToAction = {
580
559
  matrix: (matrixData: number[]) => {
581
560
  if (matrixData.length !== 6) {
@@ -589,11 +568,7 @@ export class Mat33 {
589
568
  const e = matrixData[4];
590
569
  const f = matrixData[5];
591
570
 
592
- const transform = new Mat33(
593
- a, c, e,
594
- b, d, f,
595
- 0, 0, 1
596
- );
571
+ const transform = new Mat33(a, c, e, b, d, f, 0, 0, 1);
597
572
  return transform;
598
573
  },
599
574
 
@@ -623,7 +598,9 @@ export class Mat33 {
623
598
  translateX = translateArgs[0];
624
599
  translateY = translateArgs[1];
625
600
  } else {
626
- throw new Error(`The translate() function requires either 1 or 2 arguments. Given ${translateArgs}`);
601
+ throw new Error(
602
+ `The translate() function requires either 1 or 2 arguments. Given ${translateArgs}`,
603
+ );
627
604
  }
628
605
 
629
606
  return Mat33.translation(Vec2.of(translateX, translateY));
@@ -632,9 +609,9 @@ export class Mat33 {
632
609
 
633
610
  // A command (\w+)
634
611
  // followed by a set of arguments ([ \t\n0-9eE.,\-%]+)
635
- const partRegex = /\s*(\w+)\s*\(([^)]*)\)/ig;
612
+ const partRegex = /\s*(\w+)\s*\(([^)]*)\)/gi;
636
613
  let match;
637
- let matrix: Mat33|null = null;
614
+ let matrix: Mat33 | null = null;
638
615
 
639
616
  while ((match = partRegex.exec(cssString)) !== null) {
640
617
  const action = match[1].toLowerCase();
package/src/Vec2.test.ts CHANGED
@@ -17,11 +17,11 @@ describe('Vec2', () => {
17
17
  });
18
18
 
19
19
  it('More complicated expressions', () => {
20
- expect((Vec2.of(1, 2).plus(Vec2.of(3, 4))).times(2)).objEq(Vec2.of(8, 12));
20
+ expect(Vec2.of(1, 2).plus(Vec2.of(3, 4)).times(2)).objEq(Vec2.of(8, 12));
21
21
  });
22
22
 
23
23
  it('Angle', () => {
24
- expect(Vec2.of(-1, 1).angle()).toBeCloseTo(3 * Math.PI / 4);
24
+ expect(Vec2.of(-1, 1).angle()).toBeCloseTo((3 * Math.PI) / 4);
25
25
  });
26
26
 
27
27
  it('Perpindicular', () => {
@@ -29,4 +29,4 @@ describe('Vec2', () => {
29
29
  expect(Vec2.unitX.cross(Vec3.unitZ)).objEq(Vec2.unitY.times(-1), tolerance);
30
30
  expect(Vec2.unitX.orthog()).objEq(Vec2.unitY, tolerance);
31
31
  });
32
- });
32
+ });
package/src/Vec3.test.ts CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  import Vec3 from './Vec3';
3
2
 
4
3
  describe('Vec3', () => {
@@ -60,7 +59,7 @@ describe('Vec3', () => {
60
59
  { from: Vec3.of(-1, -10, 0), to: Vec3.of(1, 2, 0), expected: 148 },
61
60
  ])(
62
61
  '.squareDistanceTo and .distanceTo should return correct square and euclidean distances (%j)',
63
- ({ from , to, expected }) => {
62
+ ({ from, to, expected }) => {
64
63
  expect(from.squareDistanceTo(to)).toBe(expected);
65
64
  expect(to.squareDistanceTo(from)).toBe(expected);
66
65
  expect(to.distanceTo(from)).toBeCloseTo(Math.sqrt(expected));
@@ -83,4 +82,4 @@ describe('Vec3', () => {
83
82
  expect(a.eq(b, tolerance)).toBe(eq);
84
83
  expect(b.eq(a, tolerance)).toBe(eq);
85
84
  });
86
- });
85
+ });
package/src/Vec3.ts CHANGED
@@ -1,5 +1,3 @@
1
-
2
-
3
1
  /**
4
2
  * A vector with three components, $\begin{pmatrix} x \\ y \\ z \end{pmatrix}$.
5
3
  * Can also be used to represent a two-component vector.
@@ -28,7 +26,7 @@ export interface Vec3 {
28
26
  * Returns the x, y components of this.
29
27
  * May be implemented as a getter method.
30
28
  */
31
- readonly xy: { x: number, y: number };
29
+ readonly xy: { x: number; y: number };
32
30
 
33
31
  /** Returns the vector's `idx`th component. For example, `Vec3.of(1, 2, 3).at(1) → 2`. */
34
32
  at(i: number): number;
@@ -124,7 +122,7 @@ export interface Vec3 {
124
122
  * Vec3.of(1, 2, 3).scale(Vec3.of(2, 4, 6)); // → Vec3(2, 8, 18)
125
123
  * ```
126
124
  */
127
- scale(other: Vec3|number): Vec3;
125
+ scale(other: Vec3 | number): Vec3;
128
126
 
129
127
  /**
130
128
  * Returns a vector orthogonal to this. If this is a Vec2, returns `this` rotated
@@ -154,9 +152,7 @@ export interface Vec3 {
154
152
  * console.log(zipped.toString()); // → Vec(0.5, 2, 2.9)
155
153
  * ```
156
154
  */
157
- zip(
158
- other: Vec3, zip: (componentInThis: number, componentInOther: number)=> number
159
- ): Vec3;
155
+ zip(other: Vec3, zip: (componentInThis: number, componentInOther: number) => number): Vec3;
160
156
 
161
157
  /**
162
158
  * Returns a vector with each component acted on by `fn`.
@@ -167,13 +163,12 @@ export interface Vec3 {
167
163
  * console.log(Vec3.of(1, 2, 3).map(val => val + 1)); // → Vec(2, 3, 4)
168
164
  * ```
169
165
  */
170
- map(fn: (component: number, index: number)=> number): Vec3;
171
-
172
- asArray(): [ number, number, number ];
166
+ map(fn: (component: number, index: number) => number): Vec3;
173
167
 
168
+ asArray(): [number, number, number];
174
169
 
175
170
  /**
176
- * [fuzz] The maximum difference between two components for this and [other]
171
+ * @param tolerance The maximum difference between two components for this and [other]
177
172
  * to be considered equal.
178
173
  *
179
174
  * @example
@@ -196,9 +191,8 @@ class Vec3Impl implements Vec3 {
196
191
  public constructor(
197
192
  public readonly x: number,
198
193
  public readonly y: number,
199
- public readonly z: number
200
- ) {
201
- }
194
+ public readonly z: number,
195
+ ) {}
202
196
 
203
197
  public get xy(): { x: number; y: number } {
204
198
  // Useful for APIs that behave differently if .z is present.
@@ -288,16 +282,12 @@ class Vec3Impl implements Vec3 {
288
282
  );
289
283
  }
290
284
 
291
- public scale(other: Vec3|number): Vec3 {
285
+ public scale(other: Vec3 | number): Vec3 {
292
286
  if (typeof other === 'number') {
293
287
  return this.times(other);
294
288
  }
295
289
 
296
- return Vec3.of(
297
- this.x * other.x,
298
- this.y * other.y,
299
- this.z * other.z,
300
- );
290
+ return Vec3.of(this.x * other.x, this.y * other.y, this.z * other.z);
301
291
  }
302
292
 
303
293
  public orthog(): Vec3 {
@@ -318,28 +308,25 @@ class Vec3Impl implements Vec3 {
318
308
  }
319
309
 
320
310
  public zip(
321
- other: Vec3, zip: (componentInThis: number, componentInOther: number)=> number
311
+ other: Vec3,
312
+ zip: (componentInThis: number, componentInOther: number) => number,
322
313
  ): Vec3 {
323
- return Vec3.of(
324
- zip(other.x, this.x),
325
- zip(other.y, this.y),
326
- zip(other.z, this.z)
327
- );
314
+ return Vec3.of(zip(other.x, this.x), zip(other.y, this.y), zip(other.z, this.z));
328
315
  }
329
316
 
330
- public map(fn: (component: number, index: number)=> number): Vec3 {
317
+ public map(fn: (component: number, index: number) => number): Vec3 {
331
318
  return Vec3.of(fn(this.x, 0), fn(this.y, 1), fn(this.z, 2));
332
319
  }
333
320
 
334
- public asArray(): [ number, number, number ] {
321
+ public asArray(): [number, number, number] {
335
322
  return [this.x, this.y, this.z];
336
323
  }
337
324
 
338
325
  public eq(other: Vec3, fuzz: number = defaultEqlTolerance): boolean {
339
326
  return (
340
- Math.abs(other.x - this.x) <= fuzz
341
- && Math.abs(other.y - this.y) <= fuzz
342
- && Math.abs(other.z - this.z) <= fuzz
327
+ Math.abs(other.x - this.x) <= fuzz &&
328
+ Math.abs(other.y - this.y) <= fuzz &&
329
+ Math.abs(other.z - this.z) <= fuzz
343
330
  );
344
331
  }
345
332
 
@@ -352,10 +339,11 @@ class Vec2Impl implements Vec3 {
352
339
  public constructor(
353
340
  public readonly x: number,
354
341
  public readonly y: number,
355
- ) {
356
- }
342
+ ) {}
357
343
 
358
- public get z() { return 0; }
344
+ public get z() {
345
+ return 0;
346
+ }
359
347
 
360
348
  public get xy(): { x: number; y: number } {
361
349
  // Useful for APIs that behave differently if .z is present.
@@ -436,22 +424,15 @@ class Vec2Impl implements Vec3 {
436
424
  // | i j k |
437
425
  // | x1 y1 z1| = (i)(y1z2 - y2z1) - (j)(x1z2 - x2z1) + (k)(x1y2 - x2y1)
438
426
  // | x2 y2 z2|
439
- return Vec3.of(
440
- this.y * other.z,
441
- -this.x * other.z,
442
- this.x * other.y - other.x * this.y,
443
- );
427
+ return Vec3.of(this.y * other.z, -this.x * other.z, this.x * other.y - other.x * this.y);
444
428
  }
445
429
 
446
- public scale(other: Vec3|number): Vec3 {
430
+ public scale(other: Vec3 | number): Vec3 {
447
431
  if (typeof other === 'number') {
448
432
  return this.times(other);
449
433
  }
450
434
 
451
- return Vec2.of(
452
- this.x * other.x,
453
- this.y * other.y,
454
- );
435
+ return Vec2.of(this.x * other.x, this.y * other.y);
455
436
  }
456
437
 
457
438
  public orthog(): Vec3 {
@@ -472,30 +453,25 @@ class Vec2Impl implements Vec3 {
472
453
  }
473
454
 
474
455
  public zip(
475
- other: Vec3, zip: (componentInThis: number, componentInOther: number)=> number
456
+ other: Vec3,
457
+ zip: (componentInThis: number, componentInOther: number) => number,
476
458
  ): Vec3 {
477
- return Vec3.of(
478
- zip(other.x, this.x),
479
- zip(other.y, this.y),
480
- zip(other.z, 0),
481
- );
459
+ return Vec3.of(zip(other.x, this.x), zip(other.y, this.y), zip(other.z, 0));
482
460
  }
483
461
 
484
- public map(fn: (component: number, index: number)=> number): Vec3 {
485
- return Vec3.of(
486
- fn(this.x, 0), fn(this.y, 1), fn(0, 2)
487
- );
462
+ public map(fn: (component: number, index: number) => number): Vec3 {
463
+ return Vec3.of(fn(this.x, 0), fn(this.y, 1), fn(0, 2));
488
464
  }
489
465
 
490
- public asArray(): [ number, number, number ] {
466
+ public asArray(): [number, number, number] {
491
467
  return [this.x, this.y, 0];
492
468
  }
493
469
 
494
470
  public eq(other: Vec3, fuzz: number = defaultEqlTolerance): boolean {
495
471
  return (
496
- Math.abs(other.x - this.x) <= fuzz
497
- && Math.abs(other.y - this.y) <= fuzz
498
- && Math.abs(other.z) <= fuzz
472
+ Math.abs(other.x - this.x) <= fuzz &&
473
+ Math.abs(other.y - this.y) <= fuzz &&
474
+ Math.abs(other.z) <= fuzz
499
475
  );
500
476
  }
501
477
 
@@ -505,12 +481,16 @@ class Vec2Impl implements Vec3 {
505
481
  }
506
482
 
507
483
  /**
508
- * A `Vec2` is a `Vec3` optimized for working in a plane. As such, they have an
484
+ * A `Vec2` is a {@link Vec3} optimized for working in a plane. `Vec2`s have an
509
485
  * always-zero `z` component.
510
486
  *
511
487
  * ```ts,runnable,console
512
488
  * import { Vec2 } from '@js-draw/math';
513
- * console.log(Vec2.of(1, 2));
489
+ *
490
+ * const v = Vec2.of(1, 2);
491
+ * console.log('a Vec2:', v);
492
+ * console.log('x component:', v.x);
493
+ * console.log('z component:', v.z);
514
494
  * ```
515
495
  */
516
496
  export namespace Vec2 {
@@ -537,7 +517,7 @@ export namespace Vec2 {
537
517
  * const v2 = Vec2.ofXY({ x: -123.4, y: 1 });
538
518
  * ```
539
519
  */
540
- export const ofXY = ({x, y}: {x: number, y: number}) => {
520
+ export const ofXY = ({ x, y }: { x: number; y: number }) => {
541
521
  return Vec2.of(x, y);
542
522
  };
543
523
 
@@ -551,6 +531,7 @@ export namespace Vec2 {
551
531
  export const zero = Vec2.of(0, 0);
552
532
  }
553
533
 
534
+ /** Contains static methods for constructing a {@link Vec3}. */
554
535
  export namespace Vec3 {
555
536
  /**
556
537
  * Construct a vector from three components.
@@ -559,6 +540,7 @@ export namespace Vec3 {
559
540
  * ```ts,runnable,console
560
541
  * import { Vec3 } from '@js-draw/math';
561
542
  * const v1 = Vec3.of(1, 2, 3);
543
+ * console.log(v1.plus(Vec3.of(0, 100, 0)));
562
544
  * ```
563
545
  */
564
546
  export const of = (x: number, y: number, z: number): Vec3 => {
@@ -569,8 +551,11 @@ export namespace Vec3 {
569
551
  }
570
552
  };
571
553
 
554
+ /** A unit vector in the x direction (`[1, 0, 0]`). */
572
555
  export const unitX = Vec2.unitX;
556
+ /** A unit vector in the y direction (`[0, 1, 0]`). */
573
557
  export const unitY = Vec2.unitY;
558
+ /** The zero vector (`[0, 0, 0]`). */
574
559
  export const zero = Vec2.zero;
575
560
 
576
561
  /** A vector of length 1 in the z direction. */
package/src/lib.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  /**
2
+ * This package contains general math utilities used by `js-draw`.
3
+ * These include 2D and 3D vectors, 2D paths, and 3x3 matrices.
4
+ *
2
5
  * ```ts,runnable,console
3
6
  * import { Vec2, Mat33, Rect2 } from '@js-draw/math';
4
7
  *
@@ -20,7 +23,6 @@
20
23
  export { LineSegment2 } from './shapes/LineSegment2';
21
24
  export {
22
25
  Path,
23
-
24
26
  IntersectionResult as PathIntersectionResult,
25
27
  CurveIndexRecord as PathCurveIndex,
26
28
  stepCurveIndexBy as stepPathIndexBy,
@@ -43,6 +45,5 @@ export { Vec3 } from './Vec3';
43
45
  export { Color4 } from './Color4';
44
46
  export * from './rounding/lib';
45
47
 
46
-
47
48
  // Note: All above exports cannot use `export { default as ... } from "..."` because this
48
49
  // breaks TypeDoc -- TypeDoc otherwise labels any imports of these classes as `default`.