@js-draw/math 1.22.0 → 1.23.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. package/dist/cjs/Color4.d.ts +24 -1
  2. package/dist/cjs/Color4.js +33 -1
  3. package/dist/cjs/Mat33.d.ts +20 -0
  4. package/dist/cjs/Mat33.js +20 -0
  5. package/dist/cjs/Vec3.d.ts +12 -3
  6. package/dist/cjs/Vec3.js +11 -2
  7. package/dist/cjs/lib.d.ts +3 -0
  8. package/dist/cjs/lib.js +3 -0
  9. package/dist/cjs/shapes/BezierJSWrapper.d.ts +2 -0
  10. package/dist/cjs/shapes/BezierJSWrapper.js +2 -0
  11. package/dist/cjs/shapes/Path.d.ts +1 -0
  12. package/dist/cjs/shapes/Path.js +1 -0
  13. package/dist/cjs/shapes/QuadraticBezier.d.ts +19 -2
  14. package/dist/cjs/shapes/QuadraticBezier.js +26 -3
  15. package/dist/cjs/shapes/Rect2.d.ts +13 -0
  16. package/dist/cjs/shapes/Rect2.js +22 -1
  17. package/dist/mjs/Color4.d.ts +24 -1
  18. package/dist/mjs/Color4.mjs +33 -1
  19. package/dist/mjs/Mat33.d.ts +20 -0
  20. package/dist/mjs/Mat33.mjs +20 -0
  21. package/dist/mjs/Vec3.d.ts +12 -3
  22. package/dist/mjs/Vec3.mjs +11 -2
  23. package/dist/mjs/lib.d.ts +3 -0
  24. package/dist/mjs/lib.mjs +3 -0
  25. package/dist/mjs/shapes/BezierJSWrapper.d.ts +2 -0
  26. package/dist/mjs/shapes/BezierJSWrapper.mjs +2 -0
  27. package/dist/mjs/shapes/Path.d.ts +1 -0
  28. package/dist/mjs/shapes/Path.mjs +1 -0
  29. package/dist/mjs/shapes/QuadraticBezier.d.ts +19 -2
  30. package/dist/mjs/shapes/QuadraticBezier.mjs +26 -3
  31. package/dist/mjs/shapes/Rect2.d.ts +13 -0
  32. package/dist/mjs/shapes/Rect2.mjs +22 -1
  33. package/package.json +3 -3
  34. package/src/Color4.test.ts +5 -0
  35. package/src/Color4.ts +39 -1
  36. package/src/Mat33.fromCSSMatrix.test.ts +1 -1
  37. package/src/Mat33.test.ts +6 -6
  38. package/src/Mat33.ts +20 -0
  39. package/src/Vec3.ts +12 -3
  40. package/src/lib.ts +3 -0
  41. package/src/shapes/BezierJSWrapper.ts +2 -0
  42. package/src/shapes/Path.ts +1 -0
  43. package/src/shapes/QuadraticBezier.ts +22 -2
  44. package/src/shapes/Rect2.ts +17 -0
@@ -28,9 +28,32 @@ export declare class Color4 {
28
28
  * Each component should be in the range [0, 1].
29
29
  */
30
30
  static ofRGB(red: number, green: number, blue: number): Color4;
31
+ /**
32
+ * Creates a color from red, green, blue, and transparency components. Each component should
33
+ * be in the range $[0, 1]$.
34
+ */
31
35
  static ofRGBA(red: number, green: number, blue: number, alpha: number): Color4;
36
+ /**
37
+ * Creates a color from an RGB (or RGBA) array.
38
+ *
39
+ * This is similar to {@link ofRGB} and {@link ofRGBA}, but, by default, takes values
40
+ * that range from 0 to 255.
41
+ *
42
+ * If the array values instead range from 0-1, pass `maxValue` as `1`.
43
+ */
44
+ static fromRGBArray(array: Uint8Array | Uint8ClampedArray | number[], maxValue?: number): Color4;
45
+ /**
46
+ * Creates a `Color4` from a three or four-component hexadecimal
47
+ * [color string](https://en.wikipedia.org/wiki/Web_colors#Hex_triplet).
48
+ *
49
+ * Example:
50
+ * ```ts,runnable,console
51
+ * import { Color4 } from '@js-draw/math';
52
+ * console.log(Color4.fromHex('#ff0'));
53
+ * ```
54
+ */
32
55
  static fromHex(hexString: string): Color4;
33
- /** Like fromHex, but can handle additional colors if an `HTMLCanvasElement` is available. */
56
+ /** Like {@link fromHex}, but can handle additional colors if an `HTMLCanvasElement` is available. */
34
57
  static fromString(text: string): Color4;
35
58
  /** @returns true if `this` and `other` are approximately equal. */
36
59
  eq(other: Color4 | null | undefined): boolean;
@@ -42,6 +42,10 @@ class Color4 {
42
42
  static ofRGB(red, green, blue) {
43
43
  return Color4.ofRGBA(red, green, blue, 1.0);
44
44
  }
45
+ /**
46
+ * Creates a color from red, green, blue, and transparency components. Each component should
47
+ * be in the range $[0, 1]$.
48
+ */
45
49
  static ofRGBA(red, green, blue, alpha) {
46
50
  red = Math.max(0, Math.min(red, 1));
47
51
  green = Math.max(0, Math.min(green, 1));
@@ -49,6 +53,34 @@ class Color4 {
49
53
  alpha = Math.max(0, Math.min(alpha, 1));
50
54
  return new Color4(red, green, blue, alpha);
51
55
  }
56
+ /**
57
+ * Creates a color from an RGB (or RGBA) array.
58
+ *
59
+ * This is similar to {@link ofRGB} and {@link ofRGBA}, but, by default, takes values
60
+ * that range from 0 to 255.
61
+ *
62
+ * If the array values instead range from 0-1, pass `maxValue` as `1`.
63
+ */
64
+ static fromRGBArray(array, maxValue = 255) {
65
+ const red = array[0];
66
+ const green = array[1] ?? red;
67
+ const blue = array[2] ?? red;
68
+ let alpha = 255;
69
+ if (3 < array.length) {
70
+ alpha = array[3];
71
+ }
72
+ return Color4.ofRGBA(red / maxValue, green / maxValue, blue / maxValue, alpha / maxValue);
73
+ }
74
+ /**
75
+ * Creates a `Color4` from a three or four-component hexadecimal
76
+ * [color string](https://en.wikipedia.org/wiki/Web_colors#Hex_triplet).
77
+ *
78
+ * Example:
79
+ * ```ts,runnable,console
80
+ * import { Color4 } from '@js-draw/math';
81
+ * console.log(Color4.fromHex('#ff0'));
82
+ * ```
83
+ */
52
84
  static fromHex(hexString) {
53
85
  // Remove starting '#' (if present)
54
86
  hexString = (hexString.match(/^[#]?(.*)$/) ?? [])[1];
@@ -77,7 +109,7 @@ class Color4 {
77
109
  }
78
110
  return Color4.ofRGBA(components[0], components[1], components[2], components[3]);
79
111
  }
80
- /** Like fromHex, but can handle additional colors if an `HTMLCanvasElement` is available. */
112
+ /** Like {@link fromHex}, but can handle additional colors if an `HTMLCanvasElement` is available. */
81
113
  static fromString(text) {
82
114
  if (text.startsWith('#')) {
83
115
  return Color4.fromHex(text);
@@ -206,6 +206,26 @@ export declare class Mat33 {
206
206
  * $$
207
207
  */
208
208
  static translation(amount: Vec2): Mat33;
209
+ /**
210
+ * Creates a matrix for rotating `Vec2`s about `center` by some number of `radians`.
211
+ *
212
+ * For this function, {@link Vec2}s are considered to be points in 2D space.
213
+ *
214
+ * For example,
215
+ * ```ts,runnable,console
216
+ * import { Mat33, Vec2 } from '@js-draw/math';
217
+ *
218
+ * const halfCircle = Math.PI; // PI radians = 180 degrees = 1/2 circle
219
+ * const center = Vec2.of(1, 1); // The point (1,1)
220
+ * const rotationMatrix = Mat33.zRotation(halfCircle, center);
221
+ *
222
+ * console.log(
223
+ * 'Rotating (0,0) 180deg about', center, 'results in',
224
+ * // Rotates (0,0)
225
+ * rotationMatrix.transformVec2(Vec2.zero),
226
+ * );
227
+ * ```
228
+ */
209
229
  static zRotation(radians: number, center?: Point2): Mat33;
210
230
  static scaling2D(amount: number | Vec2, center?: Point2): Mat33;
211
231
  /**
package/dist/cjs/Mat33.js CHANGED
@@ -362,6 +362,26 @@ class Mat33 {
362
362
  // ...
363
363
  return new Mat33(1, 0, amount.x, 0, 1, amount.y, 0, 0, 1);
364
364
  }
365
+ /**
366
+ * Creates a matrix for rotating `Vec2`s about `center` by some number of `radians`.
367
+ *
368
+ * For this function, {@link Vec2}s are considered to be points in 2D space.
369
+ *
370
+ * For example,
371
+ * ```ts,runnable,console
372
+ * import { Mat33, Vec2 } from '@js-draw/math';
373
+ *
374
+ * const halfCircle = Math.PI; // PI radians = 180 degrees = 1/2 circle
375
+ * const center = Vec2.of(1, 1); // The point (1,1)
376
+ * const rotationMatrix = Mat33.zRotation(halfCircle, center);
377
+ *
378
+ * console.log(
379
+ * 'Rotating (0,0) 180deg about', center, 'results in',
380
+ * // Rotates (0,0)
381
+ * rotationMatrix.transformVec2(Vec2.zero),
382
+ * );
383
+ * ```
384
+ */
365
385
  static zRotation(radians, center = Vec2_1.Vec2.zero) {
366
386
  if (radians === 0) {
367
387
  return Mat33.identity;
@@ -150,7 +150,7 @@ export interface Vec3 {
150
150
  map(fn: (component: number, index: number) => number): Vec3;
151
151
  asArray(): [number, number, number];
152
152
  /**
153
- * [fuzz] The maximum difference between two components for this and [other]
153
+ * @param tolerance The maximum difference between two components for this and [other]
154
154
  * to be considered equal.
155
155
  *
156
156
  * @example
@@ -200,12 +200,16 @@ declare class Vec2Impl implements Vec3 {
200
200
  toString(): string;
201
201
  }
202
202
  /**
203
- * A `Vec2` is a `Vec3` optimized for working in a plane. As such, they have an
203
+ * A `Vec2` is a {@link Vec3} optimized for working in a plane. `Vec2`s have an
204
204
  * always-zero `z` component.
205
205
  *
206
206
  * ```ts,runnable,console
207
207
  * import { Vec2 } from '@js-draw/math';
208
- * console.log(Vec2.of(1, 2));
208
+ *
209
+ * const v = Vec2.of(1, 2);
210
+ * console.log('a Vec2:', v);
211
+ * console.log('x component:', v.x);
212
+ * console.log('z component:', v.z);
209
213
  * ```
210
214
  */
211
215
  export declare namespace Vec2 {
@@ -240,6 +244,7 @@ export declare namespace Vec2 {
240
244
  /** The zero vector: A vector with x=0, y=0. */
241
245
  const zero: Vec2Impl;
242
246
  }
247
+ /** Contains static methods for constructing a {@link Vec3}. */
243
248
  export declare namespace Vec3 {
244
249
  /**
245
250
  * Construct a vector from three components.
@@ -248,11 +253,15 @@ export declare namespace Vec3 {
248
253
  * ```ts,runnable,console
249
254
  * import { Vec3 } from '@js-draw/math';
250
255
  * const v1 = Vec3.of(1, 2, 3);
256
+ * console.log(v1.plus(Vec3.of(0, 100, 0)));
251
257
  * ```
252
258
  */
253
259
  const of: (x: number, y: number, z: number) => Vec3;
260
+ /** A unit vector in the x direction (`[1, 0, 0]`). */
254
261
  const unitX: Vec2Impl;
262
+ /** A unit vector in the y direction (`[0, 1, 0]`). */
255
263
  const unitY: Vec2Impl;
264
+ /** The zero vector (`[0, 0, 0]`). */
256
265
  const zero: Vec2Impl;
257
266
  /** A vector of length 1 in the z direction. */
258
267
  const unitZ: Vec3;
package/dist/cjs/Vec3.js CHANGED
@@ -227,12 +227,16 @@ class Vec2Impl {
227
227
  }
228
228
  }
229
229
  /**
230
- * A `Vec2` is a `Vec3` optimized for working in a plane. As such, they have an
230
+ * A `Vec2` is a {@link Vec3} optimized for working in a plane. `Vec2`s have an
231
231
  * always-zero `z` component.
232
232
  *
233
233
  * ```ts,runnable,console
234
234
  * import { Vec2 } from '@js-draw/math';
235
- * console.log(Vec2.of(1, 2));
235
+ *
236
+ * const v = Vec2.of(1, 2);
237
+ * console.log('a Vec2:', v);
238
+ * console.log('x component:', v.x);
239
+ * console.log('z component:', v.z);
236
240
  * ```
237
241
  */
238
242
  var Vec2;
@@ -269,6 +273,7 @@ var Vec2;
269
273
  /** The zero vector: A vector with x=0, y=0. */
270
274
  Vec2.zero = Vec2.of(0, 0);
271
275
  })(Vec2 || (exports.Vec2 = Vec2 = {}));
276
+ /** Contains static methods for constructing a {@link Vec3}. */
272
277
  var Vec3;
273
278
  (function (Vec3) {
274
279
  /**
@@ -278,6 +283,7 @@ var Vec3;
278
283
  * ```ts,runnable,console
279
284
  * import { Vec3 } from '@js-draw/math';
280
285
  * const v1 = Vec3.of(1, 2, 3);
286
+ * console.log(v1.plus(Vec3.of(0, 100, 0)));
281
287
  * ```
282
288
  */
283
289
  Vec3.of = (x, y, z) => {
@@ -288,8 +294,11 @@ var Vec3;
288
294
  return new Vec3Impl(x, y, z);
289
295
  }
290
296
  };
297
+ /** A unit vector in the x direction (`[1, 0, 0]`). */
291
298
  Vec3.unitX = Vec2.unitX;
299
+ /** A unit vector in the y direction (`[0, 1, 0]`). */
292
300
  Vec3.unitY = Vec2.unitY;
301
+ /** The zero vector (`[0, 0, 0]`). */
293
302
  Vec3.zero = Vec2.zero;
294
303
  /** A vector of length 1 in the z direction. */
295
304
  Vec3.unitZ = Vec3.of(0, 0, 1);
package/dist/cjs/lib.d.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
  *
package/dist/cjs/lib.js CHANGED
@@ -1,5 +1,8 @@
1
1
  "use strict";
2
2
  /**
3
+ * This package contains general math utilities used by `js-draw`.
4
+ * These include 2D and 3D vectors, 2D paths, and 3x3 matrices.
5
+ *
3
6
  * ```ts,runnable,console
4
7
  * import { Vec2, Mat33, Rect2 } from '@js-draw/math';
5
8
  *
@@ -29,8 +29,10 @@ export declare abstract class BezierJSWrapper extends Parameterized2DShape {
29
29
  * @returns the curve evaluated at `t`.
30
30
  */
31
31
  at(t: number): Point2;
32
+ /** @returns the curve's directional derivative at `t`. */
32
33
  derivativeAt(t: number): Point2;
33
34
  secondDerivativeAt(t: number): Point2;
35
+ /** @returns the [normal vector](https://en.wikipedia.org/wiki/Normal_(geometry)) to this curve at `t`. */
34
36
  normal(t: number): Vec2;
35
37
  normalAt(t: number): Vec2;
36
38
  tangentAt(t: number): Vec2;
@@ -63,12 +63,14 @@ class BezierJSWrapper extends Parameterized2DShape_1.default {
63
63
  at(t) {
64
64
  return Vec2_1.Vec2.ofXY(this.getBezier().get(t));
65
65
  }
66
+ /** @returns the curve's directional derivative at `t`. */
66
67
  derivativeAt(t) {
67
68
  return Vec2_1.Vec2.ofXY(this.getBezier().derivative(t));
68
69
  }
69
70
  secondDerivativeAt(t) {
70
71
  return Vec2_1.Vec2.ofXY(this.getBezier().dderivative(t));
71
72
  }
73
+ /** @returns the [normal vector](https://en.wikipedia.org/wiki/Normal_(geometry)) to this curve at `t`. */
72
74
  normal(t) {
73
75
  return Vec2_1.Vec2.ofXY(this.getBezier().normal(t));
74
76
  }
@@ -3,6 +3,7 @@ import Mat33 from '../Mat33';
3
3
  import Rect2 from './Rect2';
4
4
  import { Point2 } from '../Vec2';
5
5
  import Parameterized2DShape from './Parameterized2DShape';
6
+ /** Identifiers for different path commands. These commands can make up a {@link Path}. */
6
7
  export declare enum PathCommandType {
7
8
  LineTo = 0,
8
9
  MoveTo = 1,
@@ -13,6 +13,7 @@ const PointShape2D_1 = __importDefault(require("./PointShape2D"));
13
13
  const toRoundedString_1 = __importDefault(require("../rounding/toRoundedString"));
14
14
  const toStringOfSamePrecision_1 = __importDefault(require("../rounding/toStringOfSamePrecision"));
15
15
  const convexHull2Of_1 = __importDefault(require("../utils/convexHull2Of"));
16
+ /** Identifiers for different path commands. These commands can make up a {@link Path}. */
16
17
  var PathCommandType;
17
18
  (function (PathCommandType) {
18
19
  PathCommandType[PathCommandType["LineTo"] = 0] = "LineTo";
@@ -2,9 +2,26 @@ import { Point2, Vec2 } from '../Vec2';
2
2
  import BezierJSWrapper from './BezierJSWrapper';
3
3
  import Rect2 from './Rect2';
4
4
  /**
5
- * Represents a 2D Bézier curve.
5
+ * Represents a 2D [Bézier curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve).
6
6
  *
7
- * **Note**: Many Bézier operations use `bezier-js`'s.
7
+ * Example:
8
+ * ```ts,runnable,console
9
+ * import { QuadraticBezier, Vec2 } from '@js-draw/math';
10
+ *
11
+ * const startPoint = Vec2.of(4, 3);
12
+ * const controlPoint = Vec2.of(1, 1);
13
+ * const endPoint = Vec2.of(1, 3);
14
+ *
15
+ * const curve = new QuadraticBezier(
16
+ * startPoint,
17
+ * controlPoint,
18
+ * endPoint,
19
+ * );
20
+ *
21
+ * console.log('Curve:', curve);
22
+ * ```
23
+ *
24
+ * **Note**: Some Bézier operations internally use the `bezier-js` library.
8
25
  */
9
26
  export declare class QuadraticBezier extends BezierJSWrapper {
10
27
  readonly p0: Point2;
@@ -9,12 +9,35 @@ const solveQuadratic_1 = __importDefault(require("../polynomial/solveQuadratic")
9
9
  const BezierJSWrapper_1 = __importDefault(require("./BezierJSWrapper"));
10
10
  const Rect2_1 = __importDefault(require("./Rect2"));
11
11
  /**
12
- * Represents a 2D Bézier curve.
12
+ * Represents a 2D [Bézier curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve).
13
13
  *
14
- * **Note**: Many Bézier operations use `bezier-js`'s.
14
+ * Example:
15
+ * ```ts,runnable,console
16
+ * import { QuadraticBezier, Vec2 } from '@js-draw/math';
17
+ *
18
+ * const startPoint = Vec2.of(4, 3);
19
+ * const controlPoint = Vec2.of(1, 1);
20
+ * const endPoint = Vec2.of(1, 3);
21
+ *
22
+ * const curve = new QuadraticBezier(
23
+ * startPoint,
24
+ * controlPoint,
25
+ * endPoint,
26
+ * );
27
+ *
28
+ * console.log('Curve:', curve);
29
+ * ```
30
+ *
31
+ * **Note**: Some Bézier operations internally use the `bezier-js` library.
15
32
  */
16
33
  class QuadraticBezier extends BezierJSWrapper_1.default {
17
- constructor(p0, p1, p2) {
34
+ constructor(
35
+ // Start point
36
+ p0,
37
+ // Control point
38
+ p1,
39
+ // End point
40
+ p2) {
18
41
  super();
19
42
  this.p0 = p0;
20
43
  this.p1 = p1;
@@ -15,6 +15,18 @@ export interface RectTemplate {
15
15
  /**
16
16
  * Represents a rectangle in 2D space, parallel to the XY axes.
17
17
  *
18
+ * **Example**:
19
+ * ```ts,runnable,console
20
+ * import { Rect2, Vec2 } from '@js-draw/math';
21
+ *
22
+ * const rect = Rect2.fromCorners(
23
+ * Vec2.of(0, 0),
24
+ * Vec2.of(10, 10),
25
+ * );
26
+ * console.log('area', rect.area);
27
+ * console.log('topLeft', rect.topLeft);
28
+ * ```
29
+ *
18
30
  * `invariant: w ≥ 0, h ≥ 0, immutable`
19
31
  */
20
32
  export declare class Rect2 extends Abstract2DShape {
@@ -29,6 +41,7 @@ export declare class Rect2 extends Abstract2DShape {
29
41
  translatedBy(vec: Vec2): Rect2;
30
42
  resizedTo(size: Vec2): Rect2;
31
43
  containsPoint(other: Point2): boolean;
44
+ /** @returns true iff `other` is completely within this `Rect2`. */
32
45
  containsRect(other: Rect2): boolean;
33
46
  /**
34
47
  * @returns true iff this and `other` overlap
@@ -10,10 +10,30 @@ const Abstract2DShape_1 = __importDefault(require("./Abstract2DShape"));
10
10
  /**
11
11
  * Represents a rectangle in 2D space, parallel to the XY axes.
12
12
  *
13
+ * **Example**:
14
+ * ```ts,runnable,console
15
+ * import { Rect2, Vec2 } from '@js-draw/math';
16
+ *
17
+ * const rect = Rect2.fromCorners(
18
+ * Vec2.of(0, 0),
19
+ * Vec2.of(10, 10),
20
+ * );
21
+ * console.log('area', rect.area);
22
+ * console.log('topLeft', rect.topLeft);
23
+ * ```
24
+ *
13
25
  * `invariant: w ≥ 0, h ≥ 0, immutable`
14
26
  */
15
27
  class Rect2 extends Abstract2DShape_1.default {
16
- constructor(x, y, w, h) {
28
+ constructor(
29
+ // Top left x coordinate
30
+ x,
31
+ // Top left y coordinate
32
+ y,
33
+ // Width
34
+ w,
35
+ // Height
36
+ h) {
17
37
  super();
18
38
  this.x = x;
19
39
  this.y = y;
@@ -45,6 +65,7 @@ class Rect2 extends Abstract2DShape_1.default {
45
65
  this.x + this.w >= other.x &&
46
66
  this.y + this.h >= other.y);
47
67
  }
68
+ /** @returns true iff `other` is completely within this `Rect2`. */
48
69
  containsRect(other) {
49
70
  return (this.x <= other.x &&
50
71
  this.y <= other.y &&
@@ -28,9 +28,32 @@ export declare class Color4 {
28
28
  * Each component should be in the range [0, 1].
29
29
  */
30
30
  static ofRGB(red: number, green: number, blue: number): Color4;
31
+ /**
32
+ * Creates a color from red, green, blue, and transparency components. Each component should
33
+ * be in the range $[0, 1]$.
34
+ */
31
35
  static ofRGBA(red: number, green: number, blue: number, alpha: number): Color4;
36
+ /**
37
+ * Creates a color from an RGB (or RGBA) array.
38
+ *
39
+ * This is similar to {@link ofRGB} and {@link ofRGBA}, but, by default, takes values
40
+ * that range from 0 to 255.
41
+ *
42
+ * If the array values instead range from 0-1, pass `maxValue` as `1`.
43
+ */
44
+ static fromRGBArray(array: Uint8Array | Uint8ClampedArray | number[], maxValue?: number): Color4;
45
+ /**
46
+ * Creates a `Color4` from a three or four-component hexadecimal
47
+ * [color string](https://en.wikipedia.org/wiki/Web_colors#Hex_triplet).
48
+ *
49
+ * Example:
50
+ * ```ts,runnable,console
51
+ * import { Color4 } from '@js-draw/math';
52
+ * console.log(Color4.fromHex('#ff0'));
53
+ * ```
54
+ */
32
55
  static fromHex(hexString: string): Color4;
33
- /** Like fromHex, but can handle additional colors if an `HTMLCanvasElement` is available. */
56
+ /** Like {@link fromHex}, but can handle additional colors if an `HTMLCanvasElement` is available. */
34
57
  static fromString(text: string): Color4;
35
58
  /** @returns true if `this` and `other` are approximately equal. */
36
59
  eq(other: Color4 | null | undefined): boolean;
@@ -36,6 +36,10 @@ export class Color4 {
36
36
  static ofRGB(red, green, blue) {
37
37
  return Color4.ofRGBA(red, green, blue, 1.0);
38
38
  }
39
+ /**
40
+ * Creates a color from red, green, blue, and transparency components. Each component should
41
+ * be in the range $[0, 1]$.
42
+ */
39
43
  static ofRGBA(red, green, blue, alpha) {
40
44
  red = Math.max(0, Math.min(red, 1));
41
45
  green = Math.max(0, Math.min(green, 1));
@@ -43,6 +47,34 @@ export class Color4 {
43
47
  alpha = Math.max(0, Math.min(alpha, 1));
44
48
  return new Color4(red, green, blue, alpha);
45
49
  }
50
+ /**
51
+ * Creates a color from an RGB (or RGBA) array.
52
+ *
53
+ * This is similar to {@link ofRGB} and {@link ofRGBA}, but, by default, takes values
54
+ * that range from 0 to 255.
55
+ *
56
+ * If the array values instead range from 0-1, pass `maxValue` as `1`.
57
+ */
58
+ static fromRGBArray(array, maxValue = 255) {
59
+ const red = array[0];
60
+ const green = array[1] ?? red;
61
+ const blue = array[2] ?? red;
62
+ let alpha = 255;
63
+ if (3 < array.length) {
64
+ alpha = array[3];
65
+ }
66
+ return Color4.ofRGBA(red / maxValue, green / maxValue, blue / maxValue, alpha / maxValue);
67
+ }
68
+ /**
69
+ * Creates a `Color4` from a three or four-component hexadecimal
70
+ * [color string](https://en.wikipedia.org/wiki/Web_colors#Hex_triplet).
71
+ *
72
+ * Example:
73
+ * ```ts,runnable,console
74
+ * import { Color4 } from '@js-draw/math';
75
+ * console.log(Color4.fromHex('#ff0'));
76
+ * ```
77
+ */
46
78
  static fromHex(hexString) {
47
79
  // Remove starting '#' (if present)
48
80
  hexString = (hexString.match(/^[#]?(.*)$/) ?? [])[1];
@@ -71,7 +103,7 @@ export class Color4 {
71
103
  }
72
104
  return Color4.ofRGBA(components[0], components[1], components[2], components[3]);
73
105
  }
74
- /** Like fromHex, but can handle additional colors if an `HTMLCanvasElement` is available. */
106
+ /** Like {@link fromHex}, but can handle additional colors if an `HTMLCanvasElement` is available. */
75
107
  static fromString(text) {
76
108
  if (text.startsWith('#')) {
77
109
  return Color4.fromHex(text);
@@ -206,6 +206,26 @@ export declare class Mat33 {
206
206
  * $$
207
207
  */
208
208
  static translation(amount: Vec2): Mat33;
209
+ /**
210
+ * Creates a matrix for rotating `Vec2`s about `center` by some number of `radians`.
211
+ *
212
+ * For this function, {@link Vec2}s are considered to be points in 2D space.
213
+ *
214
+ * For example,
215
+ * ```ts,runnable,console
216
+ * import { Mat33, Vec2 } from '@js-draw/math';
217
+ *
218
+ * const halfCircle = Math.PI; // PI radians = 180 degrees = 1/2 circle
219
+ * const center = Vec2.of(1, 1); // The point (1,1)
220
+ * const rotationMatrix = Mat33.zRotation(halfCircle, center);
221
+ *
222
+ * console.log(
223
+ * 'Rotating (0,0) 180deg about', center, 'results in',
224
+ * // Rotates (0,0)
225
+ * rotationMatrix.transformVec2(Vec2.zero),
226
+ * );
227
+ * ```
228
+ */
209
229
  static zRotation(radians: number, center?: Point2): Mat33;
210
230
  static scaling2D(amount: number | Vec2, center?: Point2): Mat33;
211
231
  /**
@@ -356,6 +356,26 @@ export class Mat33 {
356
356
  // ...
357
357
  return new Mat33(1, 0, amount.x, 0, 1, amount.y, 0, 0, 1);
358
358
  }
359
+ /**
360
+ * Creates a matrix for rotating `Vec2`s about `center` by some number of `radians`.
361
+ *
362
+ * For this function, {@link Vec2}s are considered to be points in 2D space.
363
+ *
364
+ * For example,
365
+ * ```ts,runnable,console
366
+ * import { Mat33, Vec2 } from '@js-draw/math';
367
+ *
368
+ * const halfCircle = Math.PI; // PI radians = 180 degrees = 1/2 circle
369
+ * const center = Vec2.of(1, 1); // The point (1,1)
370
+ * const rotationMatrix = Mat33.zRotation(halfCircle, center);
371
+ *
372
+ * console.log(
373
+ * 'Rotating (0,0) 180deg about', center, 'results in',
374
+ * // Rotates (0,0)
375
+ * rotationMatrix.transformVec2(Vec2.zero),
376
+ * );
377
+ * ```
378
+ */
359
379
  static zRotation(radians, center = Vec2.zero) {
360
380
  if (radians === 0) {
361
381
  return Mat33.identity;
@@ -150,7 +150,7 @@ export interface Vec3 {
150
150
  map(fn: (component: number, index: number) => number): Vec3;
151
151
  asArray(): [number, number, number];
152
152
  /**
153
- * [fuzz] The maximum difference between two components for this and [other]
153
+ * @param tolerance The maximum difference between two components for this and [other]
154
154
  * to be considered equal.
155
155
  *
156
156
  * @example
@@ -200,12 +200,16 @@ declare class Vec2Impl implements Vec3 {
200
200
  toString(): string;
201
201
  }
202
202
  /**
203
- * A `Vec2` is a `Vec3` optimized for working in a plane. As such, they have an
203
+ * A `Vec2` is a {@link Vec3} optimized for working in a plane. `Vec2`s have an
204
204
  * always-zero `z` component.
205
205
  *
206
206
  * ```ts,runnable,console
207
207
  * import { Vec2 } from '@js-draw/math';
208
- * console.log(Vec2.of(1, 2));
208
+ *
209
+ * const v = Vec2.of(1, 2);
210
+ * console.log('a Vec2:', v);
211
+ * console.log('x component:', v.x);
212
+ * console.log('z component:', v.z);
209
213
  * ```
210
214
  */
211
215
  export declare namespace Vec2 {
@@ -240,6 +244,7 @@ export declare namespace Vec2 {
240
244
  /** The zero vector: A vector with x=0, y=0. */
241
245
  const zero: Vec2Impl;
242
246
  }
247
+ /** Contains static methods for constructing a {@link Vec3}. */
243
248
  export declare namespace Vec3 {
244
249
  /**
245
250
  * Construct a vector from three components.
@@ -248,11 +253,15 @@ export declare namespace Vec3 {
248
253
  * ```ts,runnable,console
249
254
  * import { Vec3 } from '@js-draw/math';
250
255
  * const v1 = Vec3.of(1, 2, 3);
256
+ * console.log(v1.plus(Vec3.of(0, 100, 0)));
251
257
  * ```
252
258
  */
253
259
  const of: (x: number, y: number, z: number) => Vec3;
260
+ /** A unit vector in the x direction (`[1, 0, 0]`). */
254
261
  const unitX: Vec2Impl;
262
+ /** A unit vector in the y direction (`[0, 1, 0]`). */
255
263
  const unitY: Vec2Impl;
264
+ /** The zero vector (`[0, 0, 0]`). */
256
265
  const zero: Vec2Impl;
257
266
  /** A vector of length 1 in the z direction. */
258
267
  const unitZ: Vec3;
package/dist/mjs/Vec3.mjs CHANGED
@@ -224,12 +224,16 @@ class Vec2Impl {
224
224
  }
225
225
  }
226
226
  /**
227
- * A `Vec2` is a `Vec3` optimized for working in a plane. As such, they have an
227
+ * A `Vec2` is a {@link Vec3} optimized for working in a plane. `Vec2`s have an
228
228
  * always-zero `z` component.
229
229
  *
230
230
  * ```ts,runnable,console
231
231
  * import { Vec2 } from '@js-draw/math';
232
- * console.log(Vec2.of(1, 2));
232
+ *
233
+ * const v = Vec2.of(1, 2);
234
+ * console.log('a Vec2:', v);
235
+ * console.log('x component:', v.x);
236
+ * console.log('z component:', v.z);
233
237
  * ```
234
238
  */
235
239
  export var Vec2;
@@ -266,6 +270,7 @@ export var Vec2;
266
270
  /** The zero vector: A vector with x=0, y=0. */
267
271
  Vec2.zero = Vec2.of(0, 0);
268
272
  })(Vec2 || (Vec2 = {}));
273
+ /** Contains static methods for constructing a {@link Vec3}. */
269
274
  export var Vec3;
270
275
  (function (Vec3) {
271
276
  /**
@@ -275,6 +280,7 @@ export var Vec3;
275
280
  * ```ts,runnable,console
276
281
  * import { Vec3 } from '@js-draw/math';
277
282
  * const v1 = Vec3.of(1, 2, 3);
283
+ * console.log(v1.plus(Vec3.of(0, 100, 0)));
278
284
  * ```
279
285
  */
280
286
  Vec3.of = (x, y, z) => {
@@ -285,8 +291,11 @@ export var Vec3;
285
291
  return new Vec3Impl(x, y, z);
286
292
  }
287
293
  };
294
+ /** A unit vector in the x direction (`[1, 0, 0]`). */
288
295
  Vec3.unitX = Vec2.unitX;
296
+ /** A unit vector in the y direction (`[0, 1, 0]`). */
289
297
  Vec3.unitY = Vec2.unitY;
298
+ /** The zero vector (`[0, 0, 0]`). */
290
299
  Vec3.zero = Vec2.zero;
291
300
  /** A vector of length 1 in the z direction. */
292
301
  Vec3.unitZ = Vec3.of(0, 0, 1);
package/dist/mjs/lib.d.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
  *
package/dist/mjs/lib.mjs 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
  *
@@ -29,8 +29,10 @@ export declare abstract class BezierJSWrapper extends Parameterized2DShape {
29
29
  * @returns the curve evaluated at `t`.
30
30
  */
31
31
  at(t: number): Point2;
32
+ /** @returns the curve's directional derivative at `t`. */
32
33
  derivativeAt(t: number): Point2;
33
34
  secondDerivativeAt(t: number): Point2;
35
+ /** @returns the [normal vector](https://en.wikipedia.org/wiki/Normal_(geometry)) to this curve at `t`. */
34
36
  normal(t: number): Vec2;
35
37
  normalAt(t: number): Vec2;
36
38
  tangentAt(t: number): Vec2;
@@ -57,12 +57,14 @@ export class BezierJSWrapper extends Parameterized2DShape {
57
57
  at(t) {
58
58
  return Vec2.ofXY(this.getBezier().get(t));
59
59
  }
60
+ /** @returns the curve's directional derivative at `t`. */
60
61
  derivativeAt(t) {
61
62
  return Vec2.ofXY(this.getBezier().derivative(t));
62
63
  }
63
64
  secondDerivativeAt(t) {
64
65
  return Vec2.ofXY(this.getBezier().dderivative(t));
65
66
  }
67
+ /** @returns the [normal vector](https://en.wikipedia.org/wiki/Normal_(geometry)) to this curve at `t`. */
66
68
  normal(t) {
67
69
  return Vec2.ofXY(this.getBezier().normal(t));
68
70
  }
@@ -3,6 +3,7 @@ import Mat33 from '../Mat33';
3
3
  import Rect2 from './Rect2';
4
4
  import { Point2 } from '../Vec2';
5
5
  import Parameterized2DShape from './Parameterized2DShape';
6
+ /** Identifiers for different path commands. These commands can make up a {@link Path}. */
6
7
  export declare enum PathCommandType {
7
8
  LineTo = 0,
8
9
  MoveTo = 1,
@@ -7,6 +7,7 @@ import PointShape2D from './PointShape2D.mjs';
7
7
  import toRoundedString from '../rounding/toRoundedString.mjs';
8
8
  import toStringOfSamePrecision from '../rounding/toStringOfSamePrecision.mjs';
9
9
  import convexHull2Of from '../utils/convexHull2Of.mjs';
10
+ /** Identifiers for different path commands. These commands can make up a {@link Path}. */
10
11
  export var PathCommandType;
11
12
  (function (PathCommandType) {
12
13
  PathCommandType[PathCommandType["LineTo"] = 0] = "LineTo";
@@ -2,9 +2,26 @@ import { Point2, Vec2 } from '../Vec2';
2
2
  import BezierJSWrapper from './BezierJSWrapper';
3
3
  import Rect2 from './Rect2';
4
4
  /**
5
- * Represents a 2D Bézier curve.
5
+ * Represents a 2D [Bézier curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve).
6
6
  *
7
- * **Note**: Many Bézier operations use `bezier-js`'s.
7
+ * Example:
8
+ * ```ts,runnable,console
9
+ * import { QuadraticBezier, Vec2 } from '@js-draw/math';
10
+ *
11
+ * const startPoint = Vec2.of(4, 3);
12
+ * const controlPoint = Vec2.of(1, 1);
13
+ * const endPoint = Vec2.of(1, 3);
14
+ *
15
+ * const curve = new QuadraticBezier(
16
+ * startPoint,
17
+ * controlPoint,
18
+ * endPoint,
19
+ * );
20
+ *
21
+ * console.log('Curve:', curve);
22
+ * ```
23
+ *
24
+ * **Note**: Some Bézier operations internally use the `bezier-js` library.
8
25
  */
9
26
  export declare class QuadraticBezier extends BezierJSWrapper {
10
27
  readonly p0: Point2;
@@ -3,12 +3,35 @@ import solveQuadratic from '../polynomial/solveQuadratic.mjs';
3
3
  import BezierJSWrapper from './BezierJSWrapper.mjs';
4
4
  import Rect2 from './Rect2.mjs';
5
5
  /**
6
- * Represents a 2D Bézier curve.
6
+ * Represents a 2D [Bézier curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve).
7
7
  *
8
- * **Note**: Many Bézier operations use `bezier-js`'s.
8
+ * Example:
9
+ * ```ts,runnable,console
10
+ * import { QuadraticBezier, Vec2 } from '@js-draw/math';
11
+ *
12
+ * const startPoint = Vec2.of(4, 3);
13
+ * const controlPoint = Vec2.of(1, 1);
14
+ * const endPoint = Vec2.of(1, 3);
15
+ *
16
+ * const curve = new QuadraticBezier(
17
+ * startPoint,
18
+ * controlPoint,
19
+ * endPoint,
20
+ * );
21
+ *
22
+ * console.log('Curve:', curve);
23
+ * ```
24
+ *
25
+ * **Note**: Some Bézier operations internally use the `bezier-js` library.
9
26
  */
10
27
  export class QuadraticBezier extends BezierJSWrapper {
11
- constructor(p0, p1, p2) {
28
+ constructor(
29
+ // Start point
30
+ p0,
31
+ // Control point
32
+ p1,
33
+ // End point
34
+ p2) {
12
35
  super();
13
36
  this.p0 = p0;
14
37
  this.p1 = p1;
@@ -15,6 +15,18 @@ export interface RectTemplate {
15
15
  /**
16
16
  * Represents a rectangle in 2D space, parallel to the XY axes.
17
17
  *
18
+ * **Example**:
19
+ * ```ts,runnable,console
20
+ * import { Rect2, Vec2 } from '@js-draw/math';
21
+ *
22
+ * const rect = Rect2.fromCorners(
23
+ * Vec2.of(0, 0),
24
+ * Vec2.of(10, 10),
25
+ * );
26
+ * console.log('area', rect.area);
27
+ * console.log('topLeft', rect.topLeft);
28
+ * ```
29
+ *
18
30
  * `invariant: w ≥ 0, h ≥ 0, immutable`
19
31
  */
20
32
  export declare class Rect2 extends Abstract2DShape {
@@ -29,6 +41,7 @@ export declare class Rect2 extends Abstract2DShape {
29
41
  translatedBy(vec: Vec2): Rect2;
30
42
  resizedTo(size: Vec2): Rect2;
31
43
  containsPoint(other: Point2): boolean;
44
+ /** @returns true iff `other` is completely within this `Rect2`. */
32
45
  containsRect(other: Rect2): boolean;
33
46
  /**
34
47
  * @returns true iff this and `other` overlap
@@ -4,10 +4,30 @@ import Abstract2DShape from './Abstract2DShape.mjs';
4
4
  /**
5
5
  * Represents a rectangle in 2D space, parallel to the XY axes.
6
6
  *
7
+ * **Example**:
8
+ * ```ts,runnable,console
9
+ * import { Rect2, Vec2 } from '@js-draw/math';
10
+ *
11
+ * const rect = Rect2.fromCorners(
12
+ * Vec2.of(0, 0),
13
+ * Vec2.of(10, 10),
14
+ * );
15
+ * console.log('area', rect.area);
16
+ * console.log('topLeft', rect.topLeft);
17
+ * ```
18
+ *
7
19
  * `invariant: w ≥ 0, h ≥ 0, immutable`
8
20
  */
9
21
  export class Rect2 extends Abstract2DShape {
10
- constructor(x, y, w, h) {
22
+ constructor(
23
+ // Top left x coordinate
24
+ x,
25
+ // Top left y coordinate
26
+ y,
27
+ // Width
28
+ w,
29
+ // Height
30
+ h) {
11
31
  super();
12
32
  this.x = x;
13
33
  this.y = y;
@@ -39,6 +59,7 @@ export class Rect2 extends Abstract2DShape {
39
59
  this.x + this.w >= other.x &&
40
60
  this.y + this.h >= other.y);
41
61
  }
62
+ /** @returns true iff `other` is completely within this `Rect2`. */
42
63
  containsRect(other) {
43
64
  return (this.x <= other.x &&
44
65
  this.y <= other.y &&
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@js-draw/math",
3
- "version": "1.22.0",
3
+ "version": "1.23.1",
4
4
  "description": "A math library for js-draw. ",
5
5
  "types": "./dist/mjs/lib.d.ts",
6
6
  "main": "./dist/cjs/lib.js",
@@ -27,7 +27,7 @@
27
27
  "bezier-js": "6.1.3"
28
28
  },
29
29
  "devDependencies": {
30
- "@js-draw/build-tool": "^1.22.0",
30
+ "@js-draw/build-tool": "^1.23.1",
31
31
  "@types/bezier-js": "4.1.0",
32
32
  "@types/jest": "29.5.5",
33
33
  "@types/jsdom": "21.1.3"
@@ -44,5 +44,5 @@
44
44
  "svg",
45
45
  "math"
46
46
  ],
47
- "gitHead": "c922cf6e44d078133100e01383ba1bacdebe01bd"
47
+ "gitHead": "e0bb3336d5f3a94533c823906778d39a4880f4cf"
48
48
  }
@@ -86,4 +86,9 @@ describe('Color4', () => {
86
86
  expect(Color4.contrastRatio(colorA, colorB)).toBeCloseTo(expectedContrast, 1);
87
87
  }
88
88
  });
89
+
90
+ it('should support creating colors from an RGBA array', () => {
91
+ expect(Color4.fromRGBArray([255, 0, 0])).objEq(Color4.ofRGB(1, 0, 0));
92
+ expect(Color4.fromRGBArray([255, 0, 0, 128])).objEq(Color4.ofRGBA(1, 0, 0, 0.5));
93
+ });
89
94
  });
package/src/Color4.ts CHANGED
@@ -37,6 +37,10 @@ export class Color4 {
37
37
  return Color4.ofRGBA(red, green, blue, 1.0);
38
38
  }
39
39
 
40
+ /**
41
+ * Creates a color from red, green, blue, and transparency components. Each component should
42
+ * be in the range $[0, 1]$.
43
+ */
40
44
  public static ofRGBA(red: number, green: number, blue: number, alpha: number): Color4 {
41
45
  red = Math.max(0, Math.min(red, 1));
42
46
  green = Math.max(0, Math.min(green, 1));
@@ -46,6 +50,40 @@ export class Color4 {
46
50
  return new Color4(red, green, blue, alpha);
47
51
  }
48
52
 
53
+ /**
54
+ * Creates a color from an RGB (or RGBA) array.
55
+ *
56
+ * This is similar to {@link ofRGB} and {@link ofRGBA}, but, by default, takes values
57
+ * that range from 0 to 255.
58
+ *
59
+ * If the array values instead range from 0-1, pass `maxValue` as `1`.
60
+ */
61
+ public static fromRGBArray(
62
+ array: Uint8Array | Uint8ClampedArray | number[],
63
+ maxValue: number = 255,
64
+ ) {
65
+ const red = array[0];
66
+ const green = array[1] ?? red;
67
+ const blue = array[2] ?? red;
68
+
69
+ let alpha = 255;
70
+ if (3 < array.length) {
71
+ alpha = array[3];
72
+ }
73
+
74
+ return Color4.ofRGBA(red / maxValue, green / maxValue, blue / maxValue, alpha / maxValue);
75
+ }
76
+
77
+ /**
78
+ * Creates a `Color4` from a three or four-component hexadecimal
79
+ * [color string](https://en.wikipedia.org/wiki/Web_colors#Hex_triplet).
80
+ *
81
+ * Example:
82
+ * ```ts,runnable,console
83
+ * import { Color4 } from '@js-draw/math';
84
+ * console.log(Color4.fromHex('#ff0'));
85
+ * ```
86
+ */
49
87
  public static fromHex(hexString: string): Color4 {
50
88
  // Remove starting '#' (if present)
51
89
  hexString = (hexString.match(/^[#]?(.*)$/) ?? [])[1];
@@ -82,7 +120,7 @@ export class Color4 {
82
120
  return Color4.ofRGBA(components[0], components[1], components[2], components[3]);
83
121
  }
84
122
 
85
- /** Like fromHex, but can handle additional colors if an `HTMLCanvasElement` is available. */
123
+ /** Like {@link fromHex}, but can handle additional colors if an `HTMLCanvasElement` is available. */
86
124
  public static fromString(text: string): Color4 {
87
125
  if (text.startsWith('#')) {
88
126
  return Color4.fromHex(text);
@@ -2,7 +2,7 @@ import Mat33 from './Mat33';
2
2
  import { Vec2 } from './Vec2';
3
3
 
4
4
  describe('Mat33.fromCSSMatrix', () => {
5
- it('should convert CSS matrix(...) strings to matricies', () => {
5
+ it('should convert CSS matrix(...) strings to matrices', () => {
6
6
  // From MDN:
7
7
  // ⎡ a c e ⎤
8
8
  // ⎢ b d f ⎥ = matrix(a,b,c,d,e,f)
package/src/Mat33.test.ts CHANGED
@@ -39,7 +39,7 @@ describe('Mat33 tests', () => {
39
39
  expect(M.inverse().rightMul(M)).objEq(Mat33.identity, fuzz);
40
40
  });
41
41
 
42
- it('90 degree z-rotation matricies should rotate 90 degrees counter clockwise', () => {
42
+ it('90 degree z-rotation matrices should rotate 90 degrees counter clockwise', () => {
43
43
  const fuzz = 0.001;
44
44
 
45
45
  const M = Mat33.zRotation(Math.PI / 2);
@@ -48,7 +48,7 @@ describe('Mat33 tests', () => {
48
48
  expect(M.transformVec2(rotated)).objEq(Vec2.unitX.times(-1), fuzz);
49
49
  });
50
50
 
51
- it('z-rotation matricies should preserve the given origin', () => {
51
+ it('z-rotation matrices should preserve the given origin', () => {
52
52
  const testPairs: Array<[number, Vec2]> = [
53
53
  [Math.PI / 2, Vec2.zero],
54
54
  [-Math.PI / 2, Vec2.zero],
@@ -60,7 +60,7 @@ describe('Mat33 tests', () => {
60
60
  }
61
61
  });
62
62
 
63
- it('translation matricies should translate Vec2s', () => {
63
+ it('translation matrices should translate Vec2s', () => {
64
64
  const fuzz = 0.01;
65
65
 
66
66
  const M = Mat33.translation(Vec2.of(1, -4));
@@ -68,7 +68,7 @@ describe('Mat33 tests', () => {
68
68
  expect(M.transformVec2(Vec2.of(-1, 3))).objEq(Vec2.of(0, -1), fuzz);
69
69
  });
70
70
 
71
- it('scaling matricies should scale about the provided center', () => {
71
+ it('scaling matrices should scale about the provided center', () => {
72
72
  const fuzz = 0.01;
73
73
 
74
74
  const center = Vec2.of(1, -4);
@@ -77,14 +77,14 @@ describe('Mat33 tests', () => {
77
77
  expect(M.transformVec2(Vec2.of(0, 0))).objEq(Vec2.of(-1, 4), fuzz);
78
78
  });
79
79
 
80
- it('calling inverse on singular matricies should result in the identity matrix', () => {
80
+ it('calling inverse on singular matrices should result in the identity matrix', () => {
81
81
  const fuzz = 0.001;
82
82
  const singularMat = Mat33.ofRows(Vec3.of(0, 0, 1), Vec3.of(0, 1, 0), Vec3.of(0, 1, 1));
83
83
  expect(singularMat.invertable()).toBe(false);
84
84
  expect(singularMat.inverse()).objEq(Mat33.identity, fuzz);
85
85
  });
86
86
 
87
- it('z-rotation matricies should be invertable', () => {
87
+ it('z-rotation matrices should be invertable', () => {
88
88
  const fuzz = 0.01;
89
89
  const M = Mat33.zRotation(-0.2617993877991494, Vec2.of(481, 329.5));
90
90
  expect(M.inverse().transformVec2(M.transformVec2(Vec2.unitX))).objEq(Vec2.unitX, fuzz);
package/src/Mat33.ts CHANGED
@@ -440,6 +440,26 @@ export class Mat33 {
440
440
  return new Mat33(1, 0, amount.x, 0, 1, amount.y, 0, 0, 1);
441
441
  }
442
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
+ */
443
463
  public static zRotation(radians: number, center: Point2 = Vec2.zero): Mat33 {
444
464
  if (radians === 0) {
445
465
  return Mat33.identity;
package/src/Vec3.ts CHANGED
@@ -168,7 +168,7 @@ export interface Vec3 {
168
168
  asArray(): [number, number, number];
169
169
 
170
170
  /**
171
- * [fuzz] The maximum difference between two components for this and [other]
171
+ * @param tolerance The maximum difference between two components for this and [other]
172
172
  * to be considered equal.
173
173
  *
174
174
  * @example
@@ -481,12 +481,16 @@ class Vec2Impl implements Vec3 {
481
481
  }
482
482
 
483
483
  /**
484
- * 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
485
485
  * always-zero `z` component.
486
486
  *
487
487
  * ```ts,runnable,console
488
488
  * import { Vec2 } from '@js-draw/math';
489
- * 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);
490
494
  * ```
491
495
  */
492
496
  export namespace Vec2 {
@@ -527,6 +531,7 @@ export namespace Vec2 {
527
531
  export const zero = Vec2.of(0, 0);
528
532
  }
529
533
 
534
+ /** Contains static methods for constructing a {@link Vec3}. */
530
535
  export namespace Vec3 {
531
536
  /**
532
537
  * Construct a vector from three components.
@@ -535,6 +540,7 @@ export namespace Vec3 {
535
540
  * ```ts,runnable,console
536
541
  * import { Vec3 } from '@js-draw/math';
537
542
  * const v1 = Vec3.of(1, 2, 3);
543
+ * console.log(v1.plus(Vec3.of(0, 100, 0)));
538
544
  * ```
539
545
  */
540
546
  export const of = (x: number, y: number, z: number): Vec3 => {
@@ -545,8 +551,11 @@ export namespace Vec3 {
545
551
  }
546
552
  };
547
553
 
554
+ /** A unit vector in the x direction (`[1, 0, 0]`). */
548
555
  export const unitX = Vec2.unitX;
556
+ /** A unit vector in the y direction (`[0, 1, 0]`). */
549
557
  export const unitY = Vec2.unitY;
558
+ /** The zero vector (`[0, 0, 0]`). */
550
559
  export const zero = Vec2.zero;
551
560
 
552
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
  *
@@ -56,6 +56,7 @@ export abstract class BezierJSWrapper extends Parameterized2DShape {
56
56
  return Vec2.ofXY(this.getBezier().get(t));
57
57
  }
58
58
 
59
+ /** @returns the curve's directional derivative at `t`. */
59
60
  public derivativeAt(t: number): Point2 {
60
61
  return Vec2.ofXY(this.getBezier().derivative(t));
61
62
  }
@@ -64,6 +65,7 @@ export abstract class BezierJSWrapper extends Parameterized2DShape {
64
65
  return Vec2.ofXY((this.getBezier() as any).dderivative(t));
65
66
  }
66
67
 
68
+ /** @returns the [normal vector](https://en.wikipedia.org/wiki/Normal_(geometry)) to this curve at `t`. */
67
69
  public normal(t: number): Vec2 {
68
70
  return Vec2.ofXY(this.getBezier().normal(t));
69
71
  }
@@ -11,6 +11,7 @@ import Parameterized2DShape from './Parameterized2DShape';
11
11
  import BezierJSWrapper from './BezierJSWrapper';
12
12
  import convexHull2Of from '../utils/convexHull2Of';
13
13
 
14
+ /** Identifiers for different path commands. These commands can make up a {@link Path}. */
14
15
  export enum PathCommandType {
15
16
  LineTo,
16
17
  MoveTo,
@@ -4,14 +4,34 @@ import BezierJSWrapper from './BezierJSWrapper';
4
4
  import Rect2 from './Rect2';
5
5
 
6
6
  /**
7
- * Represents a 2D Bézier curve.
7
+ * Represents a 2D [Bézier curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve).
8
8
  *
9
- * **Note**: Many Bézier operations use `bezier-js`'s.
9
+ * Example:
10
+ * ```ts,runnable,console
11
+ * import { QuadraticBezier, Vec2 } from '@js-draw/math';
12
+ *
13
+ * const startPoint = Vec2.of(4, 3);
14
+ * const controlPoint = Vec2.of(1, 1);
15
+ * const endPoint = Vec2.of(1, 3);
16
+ *
17
+ * const curve = new QuadraticBezier(
18
+ * startPoint,
19
+ * controlPoint,
20
+ * endPoint,
21
+ * );
22
+ *
23
+ * console.log('Curve:', curve);
24
+ * ```
25
+ *
26
+ * **Note**: Some Bézier operations internally use the `bezier-js` library.
10
27
  */
11
28
  export class QuadraticBezier extends BezierJSWrapper {
12
29
  public constructor(
30
+ // Start point
13
31
  public readonly p0: Point2,
32
+ // Control point
14
33
  public readonly p1: Point2,
34
+ // End point
15
35
  public readonly p2: Point2,
16
36
  ) {
17
37
  super();
@@ -17,6 +17,18 @@ export interface RectTemplate {
17
17
  /**
18
18
  * Represents a rectangle in 2D space, parallel to the XY axes.
19
19
  *
20
+ * **Example**:
21
+ * ```ts,runnable,console
22
+ * import { Rect2, Vec2 } from '@js-draw/math';
23
+ *
24
+ * const rect = Rect2.fromCorners(
25
+ * Vec2.of(0, 0),
26
+ * Vec2.of(10, 10),
27
+ * );
28
+ * console.log('area', rect.area);
29
+ * console.log('topLeft', rect.topLeft);
30
+ * ```
31
+ *
20
32
  * `invariant: w ≥ 0, h ≥ 0, immutable`
21
33
  */
22
34
  export class Rect2 extends Abstract2DShape {
@@ -28,9 +40,13 @@ export class Rect2 extends Abstract2DShape {
28
40
  public readonly area: number;
29
41
 
30
42
  public constructor(
43
+ // Top left x coordinate
31
44
  public readonly x: number,
45
+ // Top left y coordinate
32
46
  public readonly y: number,
47
+ // Width
33
48
  public readonly w: number,
49
+ // Height
34
50
  public readonly h: number,
35
51
  ) {
36
52
  super();
@@ -69,6 +85,7 @@ export class Rect2 extends Abstract2DShape {
69
85
  );
70
86
  }
71
87
 
88
+ /** @returns true iff `other` is completely within this `Rect2`. */
72
89
  public containsRect(other: Rect2): boolean {
73
90
  return (
74
91
  this.x <= other.x &&