@js-draw/math 1.21.3 → 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/build-config.json +1 -1
- package/dist/cjs/Color4.d.ts +24 -1
- package/dist/cjs/Color4.js +35 -3
- package/dist/cjs/Mat33.d.ts +21 -11
- package/dist/cjs/Mat33.js +28 -24
- package/dist/cjs/Vec3.d.ts +12 -3
- package/dist/cjs/Vec3.js +20 -9
- 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 +22 -13
- package/dist/cjs/shapes/LineSegment2.js +13 -17
- package/dist/cjs/shapes/Parameterized2DShape.js +1 -1
- package/dist/cjs/shapes/Path.d.ts +1 -0
- package/dist/cjs/shapes/Path.js +50 -47
- 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 +35 -16
- package/dist/cjs/shapes/Triangle.js +4 -5
- package/dist/cjs/utils/convexHull2Of.js +3 -3
- package/dist/mjs/Color4.d.ts +24 -1
- package/dist/mjs/Color4.mjs +35 -3
- package/dist/mjs/Mat33.d.ts +21 -11
- package/dist/mjs/Mat33.mjs +28 -24
- package/dist/mjs/Vec3.d.ts +12 -3
- package/dist/mjs/Vec3.mjs +20 -9
- 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 +22 -13
- package/dist/mjs/shapes/LineSegment2.mjs +13 -17
- package/dist/mjs/shapes/Parameterized2DShape.mjs +1 -1
- package/dist/mjs/shapes/Path.d.ts +1 -0
- package/dist/mjs/shapes/Path.mjs +50 -47
- 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 +35 -16
- package/dist/mjs/shapes/Triangle.mjs +4 -5
- package/dist/mjs/utils/convexHull2Of.mjs +3 -3
- package/dist-test/test_imports/test-require.cjs +1 -1
- package/package.json +3 -3
- package/src/Color4.test.ts +21 -21
- package/src/Color4.ts +61 -18
- package/src/Mat33.fromCSSMatrix.test.ts +32 -46
- package/src/Mat33.test.ts +64 -102
- package/src/Mat33.ts +81 -104
- package/src/Vec2.test.ts +3 -3
- package/src/Vec3.test.ts +2 -3
- package/src/Vec3.ts +46 -61
- package/src/lib.ts +3 -2
- package/src/polynomial/solveQuadratic.test.ts +39 -13
- package/src/polynomial/solveQuadratic.ts +5 -6
- package/src/rounding/cleanUpNumber.test.ts +1 -1
- package/src/rounding/constants.ts +1 -3
- package/src/rounding/getLenAfterDecimal.ts +1 -2
- package/src/rounding/lib.ts +1 -2
- package/src/rounding/toRoundedString.test.ts +1 -1
- package/src/rounding/toStringOfSamePrecision.test.ts +1 -2
- package/src/rounding/toStringOfSamePrecision.ts +1 -1
- package/src/shapes/BezierJSWrapper.ts +56 -37
- package/src/shapes/CubicBezier.ts +3 -3
- package/src/shapes/LineSegment2.test.ts +24 -17
- package/src/shapes/LineSegment2.ts +26 -29
- package/src/shapes/Parameterized2DShape.ts +5 -4
- package/src/shapes/Path.fromString.test.ts +5 -5
- package/src/shapes/Path.test.ts +122 -120
- package/src/shapes/Path.toString.test.ts +7 -7
- package/src/shapes/Path.ts +379 -352
- package/src/shapes/PointShape2D.ts +3 -3
- package/src/shapes/QuadraticBezier.test.ts +27 -21
- package/src/shapes/QuadraticBezier.ts +26 -11
- package/src/shapes/Rect2.test.ts +44 -75
- package/src/shapes/Rect2.ts +47 -35
- package/src/shapes/Triangle.test.ts +31 -29
- package/src/shapes/Triangle.ts +17 -18
- package/src/utils/convexHull2Of.test.ts +54 -15
- package/src/utils/convexHull2Of.ts +9 -7
- package/tsconfig.json +1 -3
- package/typedoc.json +2 -2
package/dist/mjs/Mat33.mjs
CHANGED
@@ -70,11 +70,7 @@ export class Mat33 {
|
|
70
70
|
this.c2 = c2;
|
71
71
|
this.c3 = c3;
|
72
72
|
this.cachedInverse = undefined;
|
73
|
-
this.rows = [
|
74
|
-
Vec3.of(a1, a2, a3),
|
75
|
-
Vec3.of(b1, b2, b3),
|
76
|
-
Vec3.of(c1, c2, c3),
|
77
|
-
];
|
73
|
+
this.rows = [Vec3.of(a1, a2, a3), Vec3.of(b1, b2, b3), Vec3.of(c1, c2, c3)];
|
78
74
|
}
|
79
75
|
/**
|
80
76
|
* Creates a matrix from the given rows:
|
@@ -106,16 +102,8 @@ export class Mat33 {
|
|
106
102
|
if (this.cachedInverse !== undefined) {
|
107
103
|
return this.cachedInverse;
|
108
104
|
}
|
109
|
-
const toIdentity = [
|
110
|
-
|
111
|
-
this.rows[1],
|
112
|
-
this.rows[2],
|
113
|
-
];
|
114
|
-
const toResult = [
|
115
|
-
Vec3.unitX,
|
116
|
-
Vec3.unitY,
|
117
|
-
Vec3.unitZ,
|
118
|
-
];
|
105
|
+
const toIdentity = [this.rows[0], this.rows[1], this.rows[2]];
|
106
|
+
const toResult = [Vec3.unitX, Vec3.unitY, Vec3.unitZ];
|
119
107
|
// Convert toIdentity to the identity matrix and
|
120
108
|
// toResult to the inverse through elementary row operations
|
121
109
|
for (let cursor = 0; cursor < 3; cursor++) {
|
@@ -311,11 +299,7 @@ export class Mat33 {
|
|
311
299
|
* ```
|
312
300
|
*/
|
313
301
|
toArray() {
|
314
|
-
return [
|
315
|
-
this.a1, this.a2, this.a3,
|
316
|
-
this.b1, this.b2, this.b3,
|
317
|
-
this.c1, this.c2, this.c3,
|
318
|
-
];
|
302
|
+
return [this.a1, this.a2, this.a3, this.b1, this.b2, this.b3, this.c1, this.c2, this.c3];
|
319
303
|
}
|
320
304
|
/**
|
321
305
|
* Returns a new `Mat33` where each entry is the output of the function
|
@@ -372,6 +356,26 @@ export class Mat33 {
|
|
372
356
|
// ...
|
373
357
|
return new Mat33(1, 0, amount.x, 0, 1, amount.y, 0, 0, 1);
|
374
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
|
+
*/
|
375
379
|
static zRotation(radians, center = Vec2.zero) {
|
376
380
|
if (radians === 0) {
|
377
381
|
return Mat33.identity;
|
@@ -421,7 +425,7 @@ export class Mat33 {
|
|
421
425
|
return Mat33.identity;
|
422
426
|
}
|
423
427
|
const parseArguments = (argumentString) => {
|
424
|
-
const parsed = argumentString.split(/[, \t\n]+/g).map(argString => {
|
428
|
+
const parsed = argumentString.split(/[, \t\n]+/g).map((argString) => {
|
425
429
|
// Handle trailing spaces/commands
|
426
430
|
if (argString.trim() === '') {
|
427
431
|
return null;
|
@@ -432,7 +436,7 @@ export class Mat33 {
|
|
432
436
|
argString = argString.substring(0, argString.length - 1);
|
433
437
|
}
|
434
438
|
// Remove trailing px units.
|
435
|
-
argString = argString.replace(/px$/
|
439
|
+
argString = argString.replace(/px$/gi, '');
|
436
440
|
const numberExp = /^[-]?\d*(?:\.\d*)?(?:[eE][-+]?\d+)?$/i;
|
437
441
|
if (!numberExp.exec(argString)) {
|
438
442
|
throw new Error(`All arguments to transform functions must be numeric (state: ${JSON.stringify({
|
@@ -446,7 +450,7 @@ export class Mat33 {
|
|
446
450
|
}
|
447
451
|
return argNumber;
|
448
452
|
});
|
449
|
-
return parsed.filter(n => n !== null);
|
453
|
+
return parsed.filter((n) => n !== null);
|
450
454
|
};
|
451
455
|
const keywordToAction = {
|
452
456
|
matrix: (matrixData) => {
|
@@ -496,7 +500,7 @@ export class Mat33 {
|
|
496
500
|
};
|
497
501
|
// A command (\w+)
|
498
502
|
// followed by a set of arguments ([ \t\n0-9eE.,\-%]+)
|
499
|
-
const partRegex = /\s*(\w+)\s*\(([^)]*)\)/
|
503
|
+
const partRegex = /\s*(\w+)\s*\(([^)]*)\)/gi;
|
500
504
|
let match;
|
501
505
|
let matrix = null;
|
502
506
|
while ((match = partRegex.exec(cssString)) !== null) {
|
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
@@ -103,9 +103,9 @@ class Vec3Impl {
|
|
103
103
|
return [this.x, this.y, this.z];
|
104
104
|
}
|
105
105
|
eq(other, fuzz = defaultEqlTolerance) {
|
106
|
-
return (Math.abs(other.x - this.x) <= fuzz
|
107
|
-
|
108
|
-
|
106
|
+
return (Math.abs(other.x - this.x) <= fuzz &&
|
107
|
+
Math.abs(other.y - this.y) <= fuzz &&
|
108
|
+
Math.abs(other.z - this.z) <= fuzz);
|
109
109
|
}
|
110
110
|
toString() {
|
111
111
|
return `Vec(${this.x}, ${this.y}, ${this.z})`;
|
@@ -116,7 +116,9 @@ class Vec2Impl {
|
|
116
116
|
this.x = x;
|
117
117
|
this.y = y;
|
118
118
|
}
|
119
|
-
get z() {
|
119
|
+
get z() {
|
120
|
+
return 0;
|
121
|
+
}
|
120
122
|
get xy() {
|
121
123
|
// Useful for APIs that behave differently if .z is present.
|
122
124
|
return {
|
@@ -213,21 +215,25 @@ class Vec2Impl {
|
|
213
215
|
return [this.x, this.y, 0];
|
214
216
|
}
|
215
217
|
eq(other, fuzz = defaultEqlTolerance) {
|
216
|
-
return (Math.abs(other.x - this.x) <= fuzz
|
217
|
-
|
218
|
-
|
218
|
+
return (Math.abs(other.x - this.x) <= fuzz &&
|
219
|
+
Math.abs(other.y - this.y) <= fuzz &&
|
220
|
+
Math.abs(other.z) <= fuzz);
|
219
221
|
}
|
220
222
|
toString() {
|
221
223
|
return `Vec(${this.x}, ${this.y})`;
|
222
224
|
}
|
223
225
|
}
|
224
226
|
/**
|
225
|
-
* A `Vec2` is a
|
227
|
+
* A `Vec2` is a {@link Vec3} optimized for working in a plane. `Vec2`s have an
|
226
228
|
* always-zero `z` component.
|
227
229
|
*
|
228
230
|
* ```ts,runnable,console
|
229
231
|
* import { Vec2 } from '@js-draw/math';
|
230
|
-
*
|
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);
|
231
237
|
* ```
|
232
238
|
*/
|
233
239
|
export var Vec2;
|
@@ -264,6 +270,7 @@ export var Vec2;
|
|
264
270
|
/** The zero vector: A vector with x=0, y=0. */
|
265
271
|
Vec2.zero = Vec2.of(0, 0);
|
266
272
|
})(Vec2 || (Vec2 = {}));
|
273
|
+
/** Contains static methods for constructing a {@link Vec3}. */
|
267
274
|
export var Vec3;
|
268
275
|
(function (Vec3) {
|
269
276
|
/**
|
@@ -273,6 +280,7 @@ export var Vec3;
|
|
273
280
|
* ```ts,runnable,console
|
274
281
|
* import { Vec3 } from '@js-draw/math';
|
275
282
|
* const v1 = Vec3.of(1, 2, 3);
|
283
|
+
* console.log(v1.plus(Vec3.of(0, 100, 0)));
|
276
284
|
* ```
|
277
285
|
*/
|
278
286
|
Vec3.of = (x, y, z) => {
|
@@ -283,8 +291,11 @@ export var Vec3;
|
|
283
291
|
return new Vec3Impl(x, y, z);
|
284
292
|
}
|
285
293
|
};
|
294
|
+
/** A unit vector in the x direction (`[1, 0, 0]`). */
|
286
295
|
Vec3.unitX = Vec2.unitX;
|
296
|
+
/** A unit vector in the y direction (`[0, 1, 0]`). */
|
287
297
|
Vec3.unitY = Vec2.unitY;
|
298
|
+
/** The zero vector (`[0, 0, 0]`). */
|
288
299
|
Vec3.zero = Vec2.zero;
|
289
300
|
/** A vector of length 1 in the z direction. */
|
290
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;
|
@@ -34,7 +34,7 @@ export class BezierJSWrapper extends Parameterized2DShape {
|
|
34
34
|
}
|
35
35
|
getBezier() {
|
36
36
|
if (!__classPrivateFieldGet(this, _BezierJSWrapper_bezierJs, "f")) {
|
37
|
-
__classPrivateFieldSet(this, _BezierJSWrapper_bezierJs, new Bezier(this.getPoints().map(p => p.xy)), "f");
|
37
|
+
__classPrivateFieldSet(this, _BezierJSWrapper_bezierJs, new Bezier(this.getPoints().map((p) => p.xy)), "f");
|
38
38
|
}
|
39
39
|
return __classPrivateFieldGet(this, _BezierJSWrapper_bezierJs, "f");
|
40
40
|
}
|
@@ -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
|
}
|
@@ -88,10 +90,12 @@ export class BezierJSWrapper extends Parameterized2DShape {
|
|
88
90
|
const asLine = LineSegment2.ofSmallestContainingPoints(this.getPoints());
|
89
91
|
if (asLine) {
|
90
92
|
const intersection = asLine.intersectsLineSegment(line);
|
91
|
-
return intersection.map(p => this.nearestPointTo(p).parameterValue);
|
93
|
+
return intersection.map((p) => this.nearestPointTo(p).parameterValue);
|
92
94
|
}
|
93
95
|
const bezier = this.getBezier();
|
94
|
-
return bezier
|
96
|
+
return bezier
|
97
|
+
.intersects(line)
|
98
|
+
.map((t) => {
|
95
99
|
// We're using the .intersects(line) function, which is documented
|
96
100
|
// to always return numbers. However, to satisfy the type checker (and
|
97
101
|
// possibly improperly-defined types),
|
@@ -100,12 +104,12 @@ export class BezierJSWrapper extends Parameterized2DShape {
|
|
100
104
|
}
|
101
105
|
const point = Vec2.ofXY(this.at(t));
|
102
106
|
// Ensure that the intersection is on the line segment
|
103
|
-
if (point.distanceTo(line.p1) > line.length
|
104
|
-
|| point.distanceTo(line.p2) > line.length) {
|
107
|
+
if (point.distanceTo(line.p1) > line.length || point.distanceTo(line.p2) > line.length) {
|
105
108
|
return null;
|
106
109
|
}
|
107
110
|
return t;
|
108
|
-
})
|
111
|
+
})
|
112
|
+
.filter((entry) => entry !== null);
|
109
113
|
}
|
110
114
|
splitAt(t) {
|
111
115
|
if (t <= 0 || t >= 1) {
|
@@ -114,8 +118,8 @@ export class BezierJSWrapper extends Parameterized2DShape {
|
|
114
118
|
const bezier = this.getBezier();
|
115
119
|
const split = bezier.split(t);
|
116
120
|
return [
|
117
|
-
new BezierJSWrapperImpl(split.left.points.map(point => Vec2.ofXY(point)), split.left),
|
118
|
-
new BezierJSWrapperImpl(split.right.points.map(point => Vec2.ofXY(point)), split.right),
|
121
|
+
new BezierJSWrapperImpl(split.left.points.map((point) => Vec2.ofXY(point)), split.left),
|
122
|
+
new BezierJSWrapperImpl(split.right.points.map((point) => Vec2.ofXY(point)), split.right),
|
119
123
|
];
|
120
124
|
}
|
121
125
|
nearestPointTo(point) {
|
@@ -159,16 +163,19 @@ export class BezierJSWrapper extends Parameterized2DShape {
|
|
159
163
|
const b = this.at(t);
|
160
164
|
const bPrime = this.derivativeAt(t);
|
161
165
|
const bPrimePrime = this.secondDerivativeAt(t);
|
162
|
-
return (2 * bPrime.x * bPrime.x +
|
163
|
-
|
166
|
+
return (2 * bPrime.x * bPrime.x +
|
167
|
+
2 * b.x * bPrimePrime.x -
|
168
|
+
2 * point.x * bPrimePrime.x +
|
169
|
+
2 * bPrime.y * bPrime.y +
|
170
|
+
2 * b.y * bPrimePrime.y -
|
171
|
+
2 * point.y * bPrimePrime.y);
|
164
172
|
};
|
165
173
|
// Because we're zeroing f'(t), we also need to be able to compute it:
|
166
174
|
const derivativeAt = (t) => {
|
167
175
|
// f'(t) = 2Bₓ(t)Bₓ'(t) - 2pₓBₓ'(t) + 2Bᵧ(t)Bᵧ'(t) - 2pᵧBᵧ'(t)
|
168
176
|
const b = this.at(t);
|
169
177
|
const bPrime = this.derivativeAt(t);
|
170
|
-
return (2 * b.x * bPrime.x - 2 * point.x * bPrime.x
|
171
|
-
+ 2 * b.y * bPrime.y - 2 * point.y * bPrime.y);
|
178
|
+
return (2 * b.x * bPrime.x - 2 * point.x * bPrime.x + 2 * b.y * bPrime.y - 2 * point.y * bPrime.y);
|
172
179
|
};
|
173
180
|
const iterate = () => {
|
174
181
|
const slope = secondDerivativeAt(t);
|
@@ -219,7 +226,9 @@ export class BezierJSWrapper extends Parameterized2DShape {
|
|
219
226
|
return result;
|
220
227
|
}
|
221
228
|
toString() {
|
222
|
-
return `Bézier(${this.getPoints()
|
229
|
+
return `Bézier(${this.getPoints()
|
230
|
+
.map((point) => point.toString())
|
231
|
+
.join(', ')})`;
|
223
232
|
}
|
224
233
|
}
|
225
234
|
_BezierJSWrapper_bezierJs = new WeakMap();
|
@@ -40,7 +40,7 @@ export class LineSegment2 extends Parameterized2DShape {
|
|
40
40
|
static ofSmallestContainingPoints(points) {
|
41
41
|
if (points.length <= 1)
|
42
42
|
return null;
|
43
|
-
const sorted = [...points].sort((a, b) => a.x !== b.x ? a.x - b.x : a.y - b.y);
|
43
|
+
const sorted = [...points].sort((a, b) => (a.x !== b.x ? a.x - b.x : a.y - b.y));
|
44
44
|
const line = new LineSegment2(sorted[0], sorted[sorted.length - 1]);
|
45
45
|
for (const point of sorted) {
|
46
46
|
if (!line.containsPoint(point)) {
|
@@ -90,10 +90,7 @@ export class LineSegment2 extends Parameterized2DShape {
|
|
90
90
|
if (t <= 0 || t >= 1) {
|
91
91
|
return [this];
|
92
92
|
}
|
93
|
-
return [
|
94
|
-
new LineSegment2(this.point1, this.at(t)),
|
95
|
-
new LineSegment2(this.at(t), this.point2),
|
96
|
-
];
|
93
|
+
return [new LineSegment2(this.point1, this.at(t)), new LineSegment2(this.at(t), this.point2)];
|
97
94
|
}
|
98
95
|
/**
|
99
96
|
* Returns the intersection of this with another line segment.
|
@@ -143,18 +140,17 @@ export class LineSegment2 extends Parameterized2DShape {
|
|
143
140
|
return null;
|
144
141
|
}
|
145
142
|
const xIntersect = this.point1.x;
|
146
|
-
const yIntersect = (this.point1.x - other.point1.x) * other.direction.y / other.direction.x + other.point1.y;
|
143
|
+
const yIntersect = ((this.point1.x - other.point1.x) * other.direction.y) / other.direction.x + other.point1.y;
|
147
144
|
resultPoint = Vec2.of(xIntersect, yIntersect);
|
148
145
|
resultT = (yIntersect - this.point1.y) / this.direction.y;
|
149
146
|
}
|
150
147
|
else {
|
151
148
|
// From above,
|
152
149
|
// x = ((o₁ᵧ - o₂ᵧ)(d₁ₓd₂ₓ) + (d₂ᵧd₁ₓ)(o₂ₓ) - (d₁ᵧd₂ₓ)(o₁ₓ))/(d₂ᵧd₁ₓ - d₁ᵧd₂ₓ)
|
153
|
-
const numerator = (
|
154
|
-
|
155
|
-
|
156
|
-
const denominator =
|
157
|
-
- this.direction.y * other.direction.x);
|
150
|
+
const numerator = (this.point1.y - other.point1.y) * this.direction.x * other.direction.x +
|
151
|
+
this.direction.x * other.direction.y * other.point1.x -
|
152
|
+
this.direction.y * other.direction.x * this.point1.x;
|
153
|
+
const denominator = other.direction.y * this.direction.x - this.direction.y * other.direction.x;
|
158
154
|
// Avoid dividing by zero. It means there is no intersection
|
159
155
|
if (denominator === 0) {
|
160
156
|
return null;
|
@@ -170,10 +166,10 @@ export class LineSegment2 extends Parameterized2DShape {
|
|
170
166
|
const resultToP2 = resultPoint.distanceTo(this.point2);
|
171
167
|
const resultToP3 = resultPoint.distanceTo(other.point1);
|
172
168
|
const resultToP4 = resultPoint.distanceTo(other.point2);
|
173
|
-
if (resultToP1 > this.length
|
174
|
-
|
175
|
-
|
176
|
-
|
169
|
+
if (resultToP1 > this.length ||
|
170
|
+
resultToP2 > this.length ||
|
171
|
+
resultToP3 > other.length ||
|
172
|
+
resultToP4 > other.length) {
|
177
173
|
return null;
|
178
174
|
}
|
179
175
|
return {
|
@@ -258,8 +254,8 @@ export class LineSegment2 extends Parameterized2DShape {
|
|
258
254
|
}
|
259
255
|
const tolerance = options?.tolerance;
|
260
256
|
const ignoreDirection = options?.ignoreDirection ?? true;
|
261
|
-
return ((other.p1.eq(this.p1, tolerance) && other.p2.eq(this.p2, tolerance))
|
262
|
-
|
257
|
+
return ((other.p1.eq(this.p1, tolerance) && other.p2.eq(this.p2, tolerance)) ||
|
258
|
+
(ignoreDirection && other.p1.eq(this.p2, tolerance) && other.p2.eq(this.p1, tolerance)));
|
263
259
|
}
|
264
260
|
}
|
265
261
|
export default LineSegment2;
|
@@ -7,7 +7,7 @@ import Abstract2DShape from './Abstract2DShape.mjs';
|
|
7
7
|
*/
|
8
8
|
export class Parameterized2DShape extends Abstract2DShape {
|
9
9
|
intersectsLineSegment(line) {
|
10
|
-
return this.argIntersectsLineSegment(line).map(t => this.at(t));
|
10
|
+
return this.argIntersectsLineSegment(line).map((t) => this.at(t));
|
11
11
|
}
|
12
12
|
}
|
13
13
|
export default Parameterized2DShape;
|
@@ -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,
|