@js-draw/math 1.22.0 → 1.23.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.
- package/dist/cjs/Color4.d.ts +24 -1
- package/dist/cjs/Color4.js +33 -1
- package/dist/cjs/Mat33.d.ts +20 -0
- package/dist/cjs/Mat33.js +20 -0
- package/dist/cjs/Vec3.d.ts +12 -3
- package/dist/cjs/Vec3.js +11 -2
- package/dist/cjs/lib.d.ts +3 -0
- package/dist/cjs/lib.js +3 -0
- package/dist/cjs/shapes/BezierJSWrapper.d.ts +2 -0
- package/dist/cjs/shapes/BezierJSWrapper.js +2 -0
- package/dist/cjs/shapes/Path.d.ts +1 -0
- package/dist/cjs/shapes/Path.js +1 -0
- package/dist/cjs/shapes/QuadraticBezier.d.ts +19 -2
- package/dist/cjs/shapes/QuadraticBezier.js +26 -3
- package/dist/cjs/shapes/Rect2.d.ts +13 -0
- package/dist/cjs/shapes/Rect2.js +22 -1
- package/dist/mjs/Color4.d.ts +24 -1
- package/dist/mjs/Color4.mjs +33 -1
- package/dist/mjs/Mat33.d.ts +20 -0
- package/dist/mjs/Mat33.mjs +20 -0
- package/dist/mjs/Vec3.d.ts +12 -3
- package/dist/mjs/Vec3.mjs +11 -2
- package/dist/mjs/lib.d.ts +3 -0
- package/dist/mjs/lib.mjs +3 -0
- package/dist/mjs/shapes/BezierJSWrapper.d.ts +2 -0
- package/dist/mjs/shapes/BezierJSWrapper.mjs +2 -0
- package/dist/mjs/shapes/Path.d.ts +1 -0
- package/dist/mjs/shapes/Path.mjs +1 -0
- package/dist/mjs/shapes/QuadraticBezier.d.ts +19 -2
- package/dist/mjs/shapes/QuadraticBezier.mjs +26 -3
- package/dist/mjs/shapes/Rect2.d.ts +13 -0
- package/dist/mjs/shapes/Rect2.mjs +22 -1
- package/package.json +3 -3
- package/src/Color4.test.ts +5 -0
- package/src/Color4.ts +39 -1
- package/src/Mat33.fromCSSMatrix.test.ts +1 -1
- package/src/Mat33.test.ts +6 -6
- package/src/Mat33.ts +20 -0
- package/src/Vec3.ts +12 -3
- package/src/lib.ts +3 -0
- package/src/shapes/BezierJSWrapper.ts +2 -0
- package/src/shapes/Path.ts +1 -0
- package/src/shapes/QuadraticBezier.ts +22 -2
- package/src/shapes/Rect2.ts +17 -0
package/dist/cjs/Color4.d.ts
CHANGED
@@ -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;
|
package/dist/cjs/Color4.js
CHANGED
@@ -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);
|
package/dist/cjs/Mat33.d.ts
CHANGED
@@ -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;
|
package/dist/cjs/Vec3.d.ts
CHANGED
@@ -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
|
-
*
|
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
|
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
|
-
*
|
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
|
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
|
-
*
|
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
package/dist/cjs/lib.js
CHANGED
@@ -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,
|
package/dist/cjs/shapes/Path.js
CHANGED
@@ -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
|
-
*
|
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
|
-
*
|
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(
|
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
|
package/dist/cjs/shapes/Rect2.js
CHANGED
@@ -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(
|
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 &&
|
package/dist/mjs/Color4.d.ts
CHANGED
@@ -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;
|
package/dist/mjs/Color4.mjs
CHANGED
@@ -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);
|
package/dist/mjs/Mat33.d.ts
CHANGED
@@ -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/mjs/Mat33.mjs
CHANGED
@@ -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;
|
package/dist/mjs/Vec3.d.ts
CHANGED
@@ -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
|
-
*
|
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
|
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
|
-
*
|
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
|
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
|
-
*
|
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
package/dist/mjs/lib.mjs
CHANGED
@@ -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,
|
package/dist/mjs/shapes/Path.mjs
CHANGED
@@ -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
|
-
*
|
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
|
-
*
|
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(
|
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(
|
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.
|
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.
|
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": "
|
47
|
+
"gitHead": "e0bb3336d5f3a94533c823906778d39a4880f4cf"
|
48
48
|
}
|
package/src/Color4.test.ts
CHANGED
@@ -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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
-
*
|
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
|
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
|
-
*
|
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
@@ -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
|
}
|
package/src/shapes/Path.ts
CHANGED
@@ -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
|
-
*
|
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();
|
package/src/shapes/Rect2.ts
CHANGED
@@ -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 &&
|