@js-draw/math 1.22.0 → 1.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) 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 +23 -1
  5. package/dist/cjs/Vec3.d.ts +14 -5
  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/rounding/cleanUpNumber.js +1 -1
  10. package/dist/cjs/shapes/BezierJSWrapper.d.ts +9 -1
  11. package/dist/cjs/shapes/BezierJSWrapper.js +2 -0
  12. package/dist/cjs/shapes/Path.d.ts +1 -0
  13. package/dist/cjs/shapes/Path.js +1 -0
  14. package/dist/cjs/shapes/QuadraticBezier.d.ts +19 -2
  15. package/dist/cjs/shapes/QuadraticBezier.js +26 -3
  16. package/dist/cjs/shapes/Rect2.d.ts +13 -0
  17. package/dist/cjs/shapes/Rect2.js +22 -1
  18. package/dist/mjs/Color4.d.ts +24 -1
  19. package/dist/mjs/Color4.mjs +33 -1
  20. package/dist/mjs/Mat33.d.ts +20 -0
  21. package/dist/mjs/Mat33.mjs +23 -1
  22. package/dist/mjs/Vec3.d.ts +14 -5
  23. package/dist/mjs/Vec3.mjs +11 -2
  24. package/dist/mjs/lib.d.ts +3 -0
  25. package/dist/mjs/lib.mjs +3 -0
  26. package/dist/mjs/rounding/cleanUpNumber.mjs +1 -1
  27. package/dist/mjs/shapes/BezierJSWrapper.d.ts +9 -1
  28. package/dist/mjs/shapes/BezierJSWrapper.mjs +2 -0
  29. package/dist/mjs/shapes/Path.d.ts +1 -0
  30. package/dist/mjs/shapes/Path.mjs +1 -0
  31. package/dist/mjs/shapes/QuadraticBezier.d.ts +19 -2
  32. package/dist/mjs/shapes/QuadraticBezier.mjs +26 -3
  33. package/dist/mjs/shapes/Rect2.d.ts +13 -0
  34. package/dist/mjs/shapes/Rect2.mjs +22 -1
  35. package/dist-test/test_imports/test-require.cjs +1 -0
  36. package/package.json +3 -3
  37. package/src/Color4.test.ts +5 -0
  38. package/src/Color4.ts +39 -1
  39. package/src/Mat33.fromCSSMatrix.test.ts +4 -1
  40. package/src/Mat33.test.ts +6 -6
  41. package/src/Mat33.ts +23 -1
  42. package/src/Vec3.ts +14 -5
  43. package/src/lib.ts +3 -0
  44. package/src/rounding/cleanUpNumber.test.ts +2 -0
  45. package/src/rounding/cleanUpNumber.ts +1 -1
  46. package/src/shapes/BezierJSWrapper.ts +11 -4
  47. package/src/shapes/Path.ts +1 -0
  48. package/src/shapes/QuadraticBezier.ts +22 -2
  49. 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;
@@ -410,6 +430,8 @@ class Mat33 {
410
430
  if (cssString === '' || cssString === 'none') {
411
431
  return Mat33.identity;
412
432
  }
433
+ // Normalize spacing
434
+ cssString = cssString.trim().replace(/\s+/g, ' ');
413
435
  const parseArguments = (argumentString) => {
414
436
  const parsed = argumentString.split(/[, \t\n]+/g).map((argString) => {
415
437
  // Handle trailing spaces/commands
@@ -486,7 +508,7 @@ class Mat33 {
486
508
  };
487
509
  // A command (\w+)
488
510
  // followed by a set of arguments ([ \t\n0-9eE.,\-%]+)
489
- const partRegex = /\s*(\w+)\s*\(([^)]*)\)/gi;
511
+ const partRegex = /(\w+)\s?\(([^)]*)\)/gi;
490
512
  let match;
491
513
  let matrix = null;
492
514
  while ((match = partRegex.exec(cssString)) !== null) {
@@ -68,8 +68,8 @@ export interface Vec3 {
68
68
  *
69
69
  * This is equivalent to `Math.atan2(vec.y, vec.x)`.
70
70
  *
71
- * As such, observing that `Math.atan2(-0, -1)` $\approx -\pi$ and `Math.atan2(0, -1)`$\approx \pi$
72
- * the resultant angle is in the range $[-\pi, pi]$.
71
+ * As such, observing that `Math.atan2(-0, -1)` $\approx -\pi$ and `Math.atan2(0, -1)` $\approx \pi$
72
+ * the resultant angle is in the range $[-\pi, \pi]$.
73
73
  *
74
74
  * **Example**:
75
75
  * ```ts,runnable,console
@@ -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
  *
@@ -14,7 +14,7 @@ const cleanUpNumber = (text) => {
14
14
  const lastChar = text.charAt(text.length - 1);
15
15
  if (lastChar === '0' || lastChar === '.') {
16
16
  // Remove trailing zeroes
17
- text = text.replace(/([.]\d*[^0]+)0+$/, '$1');
17
+ text = text.replace(/([.]\d*[^0])0+$/, '$1');
18
18
  text = text.replace(/[.]0+$/, '.');
19
19
  // Remove trailing period
20
20
  text = text.replace(/[.]$/, '');
@@ -3,6 +3,12 @@ import { Point2, Vec2 } from '../Vec2';
3
3
  import LineSegment2 from './LineSegment2';
4
4
  import Rect2 from './Rect2';
5
5
  import Parameterized2DShape from './Parameterized2DShape';
6
+ interface CorrectedBezierType extends Bezier {
7
+ dderivative(t: number): {
8
+ x: number;
9
+ y: number;
10
+ };
11
+ }
6
12
  /**
7
13
  * A lazy-initializing wrapper around Bezier-js.
8
14
  *
@@ -17,7 +23,7 @@ export declare abstract class BezierJSWrapper extends Parameterized2DShape {
17
23
  protected constructor(bezierJsBezier?: Bezier);
18
24
  /** Returns the start, control points, and end point of this Bézier. */
19
25
  abstract getPoints(): readonly Point2[];
20
- protected getBezier(): Bezier;
26
+ protected getBezier(): CorrectedBezierType;
21
27
  signedDistance(point: Point2): number;
22
28
  /**
23
29
  * @returns the (more) exact distance from `point` to this.
@@ -29,8 +35,10 @@ export declare abstract class BezierJSWrapper extends Parameterized2DShape {
29
35
  * @returns the curve evaluated at `t`.
30
36
  */
31
37
  at(t: number): Point2;
38
+ /** @returns the curve's directional derivative at `t`. */
32
39
  derivativeAt(t: number): Point2;
33
40
  secondDerivativeAt(t: number): Point2;
41
+ /** @returns the [normal vector](https://en.wikipedia.org/wiki/Normal_(geometry)) to this curve at `t`. */
34
42
  normal(t: number): Vec2;
35
43
  normalAt(t: number): Vec2;
36
44
  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;
@@ -404,6 +424,8 @@ export class Mat33 {
404
424
  if (cssString === '' || cssString === 'none') {
405
425
  return Mat33.identity;
406
426
  }
427
+ // Normalize spacing
428
+ cssString = cssString.trim().replace(/\s+/g, ' ');
407
429
  const parseArguments = (argumentString) => {
408
430
  const parsed = argumentString.split(/[, \t\n]+/g).map((argString) => {
409
431
  // Handle trailing spaces/commands
@@ -480,7 +502,7 @@ export class Mat33 {
480
502
  };
481
503
  // A command (\w+)
482
504
  // followed by a set of arguments ([ \t\n0-9eE.,\-%]+)
483
- const partRegex = /\s*(\w+)\s*\(([^)]*)\)/gi;
505
+ const partRegex = /(\w+)\s?\(([^)]*)\)/gi;
484
506
  let match;
485
507
  let matrix = null;
486
508
  while ((match = partRegex.exec(cssString)) !== null) {