@emasoft/svg-matrix 1.0.30 → 1.0.31
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/bin/svg-matrix.js +310 -61
- package/bin/svglinter.cjs +102 -3
- package/bin/svgm.js +236 -27
- package/package.json +1 -1
- package/src/animation-optimization.js +137 -17
- package/src/animation-references.js +123 -6
- package/src/arc-length.js +213 -4
- package/src/bezier-analysis.js +217 -21
- package/src/bezier-intersections.js +275 -12
- package/src/browser-verify.js +237 -4
- package/src/clip-path-resolver.js +168 -0
- package/src/convert-path-data.js +479 -28
- package/src/css-specificity.js +73 -10
- package/src/douglas-peucker.js +219 -2
- package/src/flatten-pipeline.js +284 -26
- package/src/geometry-to-path.js +250 -25
- package/src/gjk-collision.js +236 -33
- package/src/index.js +261 -3
- package/src/inkscape-support.js +86 -28
- package/src/logger.js +48 -3
- package/src/marker-resolver.js +278 -74
- package/src/mask-resolver.js +265 -66
- package/src/matrix.js +44 -5
- package/src/mesh-gradient.js +352 -102
- package/src/off-canvas-detection.js +382 -13
- package/src/path-analysis.js +192 -18
- package/src/path-data-plugins.js +309 -5
- package/src/path-optimization.js +129 -5
- package/src/path-simplification.js +188 -32
- package/src/pattern-resolver.js +454 -106
- package/src/polygon-clip.js +324 -1
- package/src/svg-boolean-ops.js +226 -9
- package/src/svg-collections.js +7 -5
- package/src/svg-flatten.js +386 -62
- package/src/svg-parser.js +179 -8
- package/src/svg-rendering-context.js +235 -6
- package/src/svg-toolbox.js +45 -8
- package/src/svg2-polyfills.js +40 -10
- package/src/transform-decomposition.js +258 -32
- package/src/transform-optimization.js +259 -13
- package/src/transforms2d.js +82 -9
- package/src/transforms3d.js +62 -10
- package/src/use-symbol-resolver.js +286 -42
- package/src/vector.js +64 -8
- package/src/verification.js +392 -1
package/src/matrix.js
CHANGED
|
@@ -6,8 +6,13 @@ import { Vector } from "./vector.js";
|
|
|
6
6
|
* Accepts numbers, strings, or Decimal instances.
|
|
7
7
|
* @param {number|string|Decimal} x - The value to convert
|
|
8
8
|
* @returns {Decimal} The Decimal representation
|
|
9
|
+
* @throws {Error} If x is null or undefined
|
|
9
10
|
*/
|
|
10
|
-
const D = (x) =>
|
|
11
|
+
const D = (x) => {
|
|
12
|
+
// Validate that x is not null or undefined
|
|
13
|
+
if (x == null) throw new Error("Cannot convert null or undefined to Decimal");
|
|
14
|
+
return x instanceof Decimal ? x : new Decimal(x);
|
|
15
|
+
};
|
|
11
16
|
|
|
12
17
|
/**
|
|
13
18
|
* Matrix - Decimal-backed matrix class for arbitrary-precision matrix operations.
|
|
@@ -34,9 +39,14 @@ export class Matrix {
|
|
|
34
39
|
* @throws {Error} If data is not a non-empty 2D array with consistent row lengths
|
|
35
40
|
*/
|
|
36
41
|
constructor(data) {
|
|
42
|
+
// Validate data is a non-empty array
|
|
37
43
|
if (!Array.isArray(data) || data.length === 0)
|
|
38
44
|
throw new Error("Matrix requires non-empty 2D array");
|
|
45
|
+
// Validate first row exists and is non-empty
|
|
46
|
+
if (!Array.isArray(data[0]) || data[0].length === 0)
|
|
47
|
+
throw new Error("Matrix rows must be non-empty arrays");
|
|
39
48
|
const cols = data[0].length;
|
|
49
|
+
// Validate all rows have the same length
|
|
40
50
|
for (const row of data) {
|
|
41
51
|
if (!Array.isArray(row) || row.length !== cols)
|
|
42
52
|
throw new Error("All rows must have same length");
|
|
@@ -60,8 +70,14 @@ export class Matrix {
|
|
|
60
70
|
* @param {number} r - Number of rows
|
|
61
71
|
* @param {number} c - Number of columns
|
|
62
72
|
* @returns {Matrix} New r×c zero matrix
|
|
73
|
+
* @throws {Error} If r or c are not positive integers
|
|
63
74
|
*/
|
|
64
75
|
static zeros(r, c) {
|
|
76
|
+
// Validate r and c are positive integers
|
|
77
|
+
if (!Number.isInteger(r) || r <= 0)
|
|
78
|
+
throw new Error("rows must be a positive integer");
|
|
79
|
+
if (!Number.isInteger(c) || c <= 0)
|
|
80
|
+
throw new Error("cols must be a positive integer");
|
|
65
81
|
const out = Array.from({ length: r }, () =>
|
|
66
82
|
Array.from({ length: c }, () => new Decimal(0)),
|
|
67
83
|
);
|
|
@@ -72,8 +88,12 @@ export class Matrix {
|
|
|
72
88
|
* Create an identity matrix.
|
|
73
89
|
* @param {number} n - Size of the square identity matrix
|
|
74
90
|
* @returns {Matrix} New n×n identity matrix
|
|
91
|
+
* @throws {Error} If n is not a positive integer
|
|
75
92
|
*/
|
|
76
93
|
static identity(n) {
|
|
94
|
+
// Validate n is a positive integer
|
|
95
|
+
if (!Number.isInteger(n) || n <= 0)
|
|
96
|
+
throw new Error("size must be a positive integer");
|
|
77
97
|
const out = Array.from({ length: n }, (_, i) =>
|
|
78
98
|
Array.from({ length: n }, (_, j) =>
|
|
79
99
|
(i === j ? new Decimal(1) : new Decimal(0)),
|
|
@@ -259,11 +279,15 @@ export class Matrix {
|
|
|
259
279
|
* @param {Matrix} other - Matrix to compare with
|
|
260
280
|
* @param {number|string|Decimal} [tolerance=0] - Maximum allowed difference per element
|
|
261
281
|
* @returns {boolean} True if matrices are equal within tolerance
|
|
282
|
+
* @throws {Error} If tolerance is negative
|
|
262
283
|
*/
|
|
263
284
|
equals(other, tolerance = 0) {
|
|
264
285
|
if (!(other instanceof Matrix)) return false;
|
|
265
286
|
if (this.rows !== other.rows || this.cols !== other.cols) return false;
|
|
266
287
|
const tol = D(tolerance);
|
|
288
|
+
// Validate tolerance is non-negative
|
|
289
|
+
if (tol.isNegative())
|
|
290
|
+
throw new Error("tolerance must be non-negative");
|
|
267
291
|
for (let i = 0; i < this.rows; i++) {
|
|
268
292
|
for (let j = 0; j < this.cols; j++) {
|
|
269
293
|
const diff = this.data[i][j].minus(other.data[i][j]).abs();
|
|
@@ -472,6 +496,9 @@ export class Matrix {
|
|
|
472
496
|
// Back substitution
|
|
473
497
|
const x = Array.from({ length: n }, () => new Decimal(0));
|
|
474
498
|
for (let i = n - 1; i >= 0; i--) {
|
|
499
|
+
// Check for zero diagonal element (should not happen after forward elimination)
|
|
500
|
+
if (aug[i][i].isZero())
|
|
501
|
+
throw new Error("Zero diagonal element in back substitution: system is singular");
|
|
475
502
|
let sum = new Decimal(0);
|
|
476
503
|
for (let j = i + 1; j < n; j++) sum = sum.plus(aug[i][j].mul(x[j]));
|
|
477
504
|
x[i] = aug[i][n].minus(sum).div(aug[i][i]);
|
|
@@ -546,7 +573,7 @@ export class Matrix {
|
|
|
546
573
|
* @param {number} [options.maxIter=120] - Maximum Taylor series iterations
|
|
547
574
|
* @param {string} [options.tolerance='1e-40'] - Convergence tolerance
|
|
548
575
|
* @returns {Matrix} The matrix exponential exp(A)
|
|
549
|
-
* @throws {Error} If matrix is not square
|
|
576
|
+
* @throws {Error} If matrix is not square or options are invalid
|
|
550
577
|
*/
|
|
551
578
|
exp(options = {}) {
|
|
552
579
|
const n = this.rows;
|
|
@@ -554,6 +581,16 @@ export class Matrix {
|
|
|
554
581
|
throw new Error("Matrix exponential requires square matrix");
|
|
555
582
|
const ident = Matrix.identity(n);
|
|
556
583
|
|
|
584
|
+
// Validate and set maxIter
|
|
585
|
+
const maxIter = options.maxIter || 120;
|
|
586
|
+
if (!Number.isInteger(maxIter) || maxIter <= 0)
|
|
587
|
+
throw new Error("maxIter must be a positive integer");
|
|
588
|
+
|
|
589
|
+
// Validate and set tolerance
|
|
590
|
+
const tol = new Decimal(options.tolerance || "1e-40");
|
|
591
|
+
if (tol.isNegative() || tol.isZero())
|
|
592
|
+
throw new Error("tolerance must be positive");
|
|
593
|
+
|
|
557
594
|
// Compute infinity norm
|
|
558
595
|
const normInf = (M) => {
|
|
559
596
|
let max = new Decimal(0);
|
|
@@ -571,14 +608,16 @@ export class Matrix {
|
|
|
571
608
|
let s = 0;
|
|
572
609
|
if (maxNorm.greaterThan(new Decimal(1))) {
|
|
573
610
|
const ratio = maxNorm.div(new Decimal(1));
|
|
574
|
-
|
|
611
|
+
const logVal = ratio.toNumber();
|
|
612
|
+
// Guard against Infinity or NaN from logarithm
|
|
613
|
+
if (!isFinite(logVal))
|
|
614
|
+
throw new Error("Matrix norm too large for exponential computation");
|
|
615
|
+
s = Math.max(0, Math.ceil(Math.log2(logVal)));
|
|
575
616
|
}
|
|
576
617
|
let A = this;
|
|
577
618
|
if (s > 0) A = this.mul(new Decimal(1).div(new Decimal(2).pow(s)));
|
|
578
619
|
|
|
579
620
|
// Taylor series
|
|
580
|
-
const maxIter = options.maxIter || 120;
|
|
581
|
-
const tol = new Decimal(options.tolerance || "1e-40");
|
|
582
621
|
let term = ident.clone();
|
|
583
622
|
let result = ident.clone();
|
|
584
623
|
for (let k = 1; k < maxIter; k++) {
|