@emasoft/svg-matrix 1.1.0 → 1.2.0
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 +7 -6
- package/bin/svgm.js +109 -40
- package/dist/svg-matrix.min.js +7 -7
- package/dist/svg-toolbox.min.js +148 -228
- package/dist/svgm.min.js +152 -232
- package/dist/version.json +5 -5
- package/package.json +1 -1
- package/scripts/postinstall.js +72 -41
- package/scripts/test-postinstall.js +18 -16
- package/scripts/version-sync.js +78 -60
- package/src/animation-optimization.js +190 -98
- package/src/animation-references.js +11 -3
- package/src/arc-length.js +23 -20
- package/src/bezier-analysis.js +9 -13
- package/src/bezier-intersections.js +18 -4
- package/src/browser-verify.js +35 -8
- package/src/clip-path-resolver.js +285 -114
- package/src/convert-path-data.js +20 -8
- package/src/css-specificity.js +33 -9
- package/src/douglas-peucker.js +272 -141
- package/src/geometry-to-path.js +79 -22
- package/src/gjk-collision.js +287 -126
- package/src/index.js +56 -21
- package/src/inkscape-support.js +122 -101
- package/src/logger.js +43 -27
- package/src/marker-resolver.js +201 -121
- package/src/mask-resolver.js +231 -98
- package/src/matrix.js +9 -5
- package/src/mesh-gradient.js +22 -14
- package/src/off-canvas-detection.js +53 -17
- package/src/path-optimization.js +356 -171
- package/src/path-simplification.js +671 -256
- package/src/pattern-resolver.js +1 -3
- package/src/polygon-clip.js +396 -78
- package/src/svg-boolean-ops.js +90 -23
- package/src/svg-collections.js +1546 -667
- package/src/svg-flatten.js +152 -38
- package/src/svg-matrix-lib.js +2 -2
- package/src/svg-parser.js +5 -1
- package/src/svg-rendering-context.js +3 -1
- package/src/svg-toolbox-lib.js +2 -2
- package/src/svg-toolbox.js +99 -457
- package/src/svg-validation-data.js +513 -345
- package/src/svg2-polyfills.js +156 -93
- package/src/svgm-lib.js +8 -4
- package/src/transform-optimization.js +168 -51
- package/src/transforms2d.js +73 -40
- package/src/transforms3d.js +34 -27
- package/src/use-symbol-resolver.js +175 -76
- package/src/vector.js +80 -44
- package/src/vendor/inkscape-hatch-polyfill.js +143 -108
- package/src/vendor/inkscape-hatch-polyfill.min.js +291 -1
- package/src/vendor/inkscape-mesh-polyfill.js +953 -766
- package/src/vendor/inkscape-mesh-polyfill.min.js +896 -1
- package/src/verification.js +3 -4
package/src/pattern-resolver.js
CHANGED
|
@@ -732,9 +732,7 @@ export function resolvePattern(patternData, targetBBox, options = {}) {
|
|
|
732
732
|
);
|
|
733
733
|
|
|
734
734
|
// Parse patternTransform if present
|
|
735
|
-
const patternTransform = parsePatternTransform(
|
|
736
|
-
patternData.patternTransform,
|
|
737
|
-
);
|
|
735
|
+
const patternTransform = parsePatternTransform(patternData.patternTransform);
|
|
738
736
|
|
|
739
737
|
// Get tile positions
|
|
740
738
|
const positions = getTilePositions(tile, targetBBox);
|
package/src/polygon-clip.js
CHANGED
|
@@ -166,10 +166,24 @@ export function point(x, y) {
|
|
|
166
166
|
*/
|
|
167
167
|
export function pointsEqual(p1, p2, tolerance = EPSILON) {
|
|
168
168
|
// Validate parameters - check for null/undefined explicitly since Decimal objects are always truthy
|
|
169
|
-
if (
|
|
169
|
+
if (
|
|
170
|
+
!p1 ||
|
|
171
|
+
typeof p1 !== "object" ||
|
|
172
|
+
p1.x === null ||
|
|
173
|
+
p1.x === undefined ||
|
|
174
|
+
p1.y === null ||
|
|
175
|
+
p1.y === undefined
|
|
176
|
+
) {
|
|
170
177
|
throw new Error("pointsEqual: p1 must be a point with x and y properties");
|
|
171
178
|
}
|
|
172
|
-
if (
|
|
179
|
+
if (
|
|
180
|
+
!p2 ||
|
|
181
|
+
typeof p2 !== "object" ||
|
|
182
|
+
p2.x === null ||
|
|
183
|
+
p2.x === undefined ||
|
|
184
|
+
p2.y === null ||
|
|
185
|
+
p2.y === undefined
|
|
186
|
+
) {
|
|
173
187
|
throw new Error("pointsEqual: p2 must be a point with x and y properties");
|
|
174
188
|
}
|
|
175
189
|
if (!tolerance || typeof tolerance.abs !== "function") {
|
|
@@ -221,13 +235,31 @@ export function pointsEqual(p1, p2, tolerance = EPSILON) {
|
|
|
221
235
|
*/
|
|
222
236
|
export function cross(o, a, b) {
|
|
223
237
|
// Validate parameters - check for null/undefined explicitly since Decimal objects are always truthy
|
|
224
|
-
if (
|
|
238
|
+
if (
|
|
239
|
+
!o ||
|
|
240
|
+
o.x === null ||
|
|
241
|
+
o.x === undefined ||
|
|
242
|
+
o.y === null ||
|
|
243
|
+
o.y === undefined
|
|
244
|
+
) {
|
|
225
245
|
throw new Error("cross: origin point o must have x and y properties");
|
|
226
246
|
}
|
|
227
|
-
if (
|
|
247
|
+
if (
|
|
248
|
+
!a ||
|
|
249
|
+
a.x === null ||
|
|
250
|
+
a.x === undefined ||
|
|
251
|
+
a.y === null ||
|
|
252
|
+
a.y === undefined
|
|
253
|
+
) {
|
|
228
254
|
throw new Error("cross: point a must have x and y properties");
|
|
229
255
|
}
|
|
230
|
-
if (
|
|
256
|
+
if (
|
|
257
|
+
!b ||
|
|
258
|
+
b.x === null ||
|
|
259
|
+
b.x === undefined ||
|
|
260
|
+
b.y === null ||
|
|
261
|
+
b.y === undefined
|
|
262
|
+
) {
|
|
231
263
|
throw new Error("cross: point b must have x and y properties");
|
|
232
264
|
}
|
|
233
265
|
const ax = a.x.minus(o.x);
|
|
@@ -279,13 +311,31 @@ export function cross(o, a, b) {
|
|
|
279
311
|
*/
|
|
280
312
|
export function dot(o, a, b) {
|
|
281
313
|
// Validate parameters - check for null/undefined explicitly since Decimal objects are always truthy
|
|
282
|
-
if (
|
|
314
|
+
if (
|
|
315
|
+
!o ||
|
|
316
|
+
o.x === null ||
|
|
317
|
+
o.x === undefined ||
|
|
318
|
+
o.y === null ||
|
|
319
|
+
o.y === undefined
|
|
320
|
+
) {
|
|
283
321
|
throw new Error("dot: origin point o must have x and y properties");
|
|
284
322
|
}
|
|
285
|
-
if (
|
|
323
|
+
if (
|
|
324
|
+
!a ||
|
|
325
|
+
a.x === null ||
|
|
326
|
+
a.x === undefined ||
|
|
327
|
+
a.y === null ||
|
|
328
|
+
a.y === undefined
|
|
329
|
+
) {
|
|
286
330
|
throw new Error("dot: point a must have x and y properties");
|
|
287
331
|
}
|
|
288
|
-
if (
|
|
332
|
+
if (
|
|
333
|
+
!b ||
|
|
334
|
+
b.x === null ||
|
|
335
|
+
b.x === undefined ||
|
|
336
|
+
b.y === null ||
|
|
337
|
+
b.y === undefined
|
|
338
|
+
) {
|
|
289
339
|
throw new Error("dot: point b must have x and y properties");
|
|
290
340
|
}
|
|
291
341
|
const ax = a.x.minus(o.x);
|
|
@@ -372,17 +422,49 @@ export function sign(val) {
|
|
|
372
422
|
*/
|
|
373
423
|
export function segmentIntersection(a, b, c, d) {
|
|
374
424
|
// Validate all segment endpoints - check for null/undefined explicitly
|
|
375
|
-
if (
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
throw new Error(
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
425
|
+
if (
|
|
426
|
+
!a ||
|
|
427
|
+
a.x === null ||
|
|
428
|
+
a.x === undefined ||
|
|
429
|
+
a.y === null ||
|
|
430
|
+
a.y === undefined
|
|
431
|
+
) {
|
|
432
|
+
throw new Error(
|
|
433
|
+
"segmentIntersection: point a must have x and y properties",
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
if (
|
|
437
|
+
!b ||
|
|
438
|
+
b.x === null ||
|
|
439
|
+
b.x === undefined ||
|
|
440
|
+
b.y === null ||
|
|
441
|
+
b.y === undefined
|
|
442
|
+
) {
|
|
443
|
+
throw new Error(
|
|
444
|
+
"segmentIntersection: point b must have x and y properties",
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
if (
|
|
448
|
+
!c ||
|
|
449
|
+
c.x === null ||
|
|
450
|
+
c.x === undefined ||
|
|
451
|
+
c.y === null ||
|
|
452
|
+
c.y === undefined
|
|
453
|
+
) {
|
|
454
|
+
throw new Error(
|
|
455
|
+
"segmentIntersection: point c must have x and y properties",
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
if (
|
|
459
|
+
!d ||
|
|
460
|
+
d.x === null ||
|
|
461
|
+
d.x === undefined ||
|
|
462
|
+
d.y === null ||
|
|
463
|
+
d.y === undefined
|
|
464
|
+
) {
|
|
465
|
+
throw new Error(
|
|
466
|
+
"segmentIntersection: point d must have x and y properties",
|
|
467
|
+
);
|
|
386
468
|
}
|
|
387
469
|
|
|
388
470
|
// Direction vectors
|
|
@@ -465,17 +547,49 @@ export function segmentIntersection(a, b, c, d) {
|
|
|
465
547
|
*/
|
|
466
548
|
export function lineSegmentIntersection(lineA, lineB, segA, segB) {
|
|
467
549
|
// Validate all points - check for null/undefined explicitly
|
|
468
|
-
if (
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
throw new Error(
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
550
|
+
if (
|
|
551
|
+
!lineA ||
|
|
552
|
+
lineA.x === null ||
|
|
553
|
+
lineA.x === undefined ||
|
|
554
|
+
lineA.y === null ||
|
|
555
|
+
lineA.y === undefined
|
|
556
|
+
) {
|
|
557
|
+
throw new Error(
|
|
558
|
+
"lineSegmentIntersection: lineA must have x and y properties",
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
if (
|
|
562
|
+
!lineB ||
|
|
563
|
+
lineB.x === null ||
|
|
564
|
+
lineB.x === undefined ||
|
|
565
|
+
lineB.y === null ||
|
|
566
|
+
lineB.y === undefined
|
|
567
|
+
) {
|
|
568
|
+
throw new Error(
|
|
569
|
+
"lineSegmentIntersection: lineB must have x and y properties",
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
if (
|
|
573
|
+
!segA ||
|
|
574
|
+
segA.x === null ||
|
|
575
|
+
segA.x === undefined ||
|
|
576
|
+
segA.y === null ||
|
|
577
|
+
segA.y === undefined
|
|
578
|
+
) {
|
|
579
|
+
throw new Error(
|
|
580
|
+
"lineSegmentIntersection: segA must have x and y properties",
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
if (
|
|
584
|
+
!segB ||
|
|
585
|
+
segB.x === null ||
|
|
586
|
+
segB.x === undefined ||
|
|
587
|
+
segB.y === null ||
|
|
588
|
+
segB.y === undefined
|
|
589
|
+
) {
|
|
590
|
+
throw new Error(
|
|
591
|
+
"lineSegmentIntersection: segB must have x and y properties",
|
|
592
|
+
);
|
|
479
593
|
}
|
|
480
594
|
|
|
481
595
|
const dx1 = lineB.x.minus(lineA.x);
|
|
@@ -553,7 +667,13 @@ export function lineSegmentIntersection(lineA, lineB, segA, segB) {
|
|
|
553
667
|
*/
|
|
554
668
|
export function pointInPolygon(pt, polygon) {
|
|
555
669
|
// Validate point parameter - check for null/undefined explicitly
|
|
556
|
-
if (
|
|
670
|
+
if (
|
|
671
|
+
!pt ||
|
|
672
|
+
pt.x === null ||
|
|
673
|
+
pt.x === undefined ||
|
|
674
|
+
pt.y === null ||
|
|
675
|
+
pt.y === undefined
|
|
676
|
+
) {
|
|
557
677
|
throw new Error("pointInPolygon: pt must have x and y properties");
|
|
558
678
|
}
|
|
559
679
|
// Validate polygon is an array
|
|
@@ -567,8 +687,16 @@ export function pointInPolygon(pt, polygon) {
|
|
|
567
687
|
|
|
568
688
|
// Validate polygon elements have x and y properties
|
|
569
689
|
for (let i = 0; i < n; i++) {
|
|
570
|
-
if (
|
|
571
|
-
|
|
690
|
+
if (
|
|
691
|
+
!polygon[i] ||
|
|
692
|
+
polygon[i].x === null ||
|
|
693
|
+
polygon[i].x === undefined ||
|
|
694
|
+
polygon[i].y === null ||
|
|
695
|
+
polygon[i].y === undefined
|
|
696
|
+
) {
|
|
697
|
+
throw new Error(
|
|
698
|
+
`pointInPolygon: polygon[${i}] must have x and y properties`,
|
|
699
|
+
);
|
|
572
700
|
}
|
|
573
701
|
}
|
|
574
702
|
|
|
@@ -640,14 +768,36 @@ export function pointInPolygon(pt, polygon) {
|
|
|
640
768
|
*/
|
|
641
769
|
export function pointOnSegment(pt, a, b) {
|
|
642
770
|
// Validate all points - check for null/undefined explicitly
|
|
643
|
-
if (
|
|
771
|
+
if (
|
|
772
|
+
!pt ||
|
|
773
|
+
pt.x === null ||
|
|
774
|
+
pt.x === undefined ||
|
|
775
|
+
pt.y === null ||
|
|
776
|
+
pt.y === undefined
|
|
777
|
+
) {
|
|
644
778
|
throw new Error("pointOnSegment: pt must have x and y properties");
|
|
645
779
|
}
|
|
646
|
-
if (
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
780
|
+
if (
|
|
781
|
+
!a ||
|
|
782
|
+
a.x === null ||
|
|
783
|
+
a.x === undefined ||
|
|
784
|
+
a.y === null ||
|
|
785
|
+
a.y === undefined
|
|
786
|
+
) {
|
|
787
|
+
throw new Error(
|
|
788
|
+
"pointOnSegment: segment point a must have x and y properties",
|
|
789
|
+
);
|
|
790
|
+
}
|
|
791
|
+
if (
|
|
792
|
+
!b ||
|
|
793
|
+
b.x === null ||
|
|
794
|
+
b.x === undefined ||
|
|
795
|
+
b.y === null ||
|
|
796
|
+
b.y === undefined
|
|
797
|
+
) {
|
|
798
|
+
throw new Error(
|
|
799
|
+
"pointOnSegment: segment point b must have x and y properties",
|
|
800
|
+
);
|
|
651
801
|
}
|
|
652
802
|
|
|
653
803
|
// Check collinearity using cross product
|
|
@@ -734,14 +884,28 @@ export function clipPolygonSH(subject, clip) {
|
|
|
734
884
|
|
|
735
885
|
// Validate all subject points have x and y properties
|
|
736
886
|
for (let i = 0; i < subject.length; i++) {
|
|
737
|
-
if (
|
|
738
|
-
|
|
887
|
+
if (
|
|
888
|
+
!subject[i] ||
|
|
889
|
+
subject[i].x === null ||
|
|
890
|
+
subject[i].x === undefined ||
|
|
891
|
+
subject[i].y === null ||
|
|
892
|
+
subject[i].y === undefined
|
|
893
|
+
) {
|
|
894
|
+
throw new Error(
|
|
895
|
+
`clipPolygonSH: subject[${i}] must have x and y properties`,
|
|
896
|
+
);
|
|
739
897
|
}
|
|
740
898
|
}
|
|
741
899
|
|
|
742
900
|
// Validate all clip points have x and y properties
|
|
743
901
|
for (let i = 0; i < clip.length; i++) {
|
|
744
|
-
if (
|
|
902
|
+
if (
|
|
903
|
+
!clip[i] ||
|
|
904
|
+
clip[i].x === null ||
|
|
905
|
+
clip[i].x === undefined ||
|
|
906
|
+
clip[i].y === null ||
|
|
907
|
+
clip[i].y === undefined
|
|
908
|
+
) {
|
|
745
909
|
throw new Error(`clipPolygonSH: clip[${i}] must have x and y properties`);
|
|
746
910
|
}
|
|
747
911
|
}
|
|
@@ -822,13 +986,31 @@ export function clipPolygonSH(subject, clip) {
|
|
|
822
986
|
*/
|
|
823
987
|
function isInsideEdge(pt, edgeStart, edgeEnd) {
|
|
824
988
|
// Validate inputs (defensive check for internal function) - check for null/undefined explicitly
|
|
825
|
-
if (
|
|
989
|
+
if (
|
|
990
|
+
!pt ||
|
|
991
|
+
pt.x === null ||
|
|
992
|
+
pt.x === undefined ||
|
|
993
|
+
pt.y === null ||
|
|
994
|
+
pt.y === undefined
|
|
995
|
+
) {
|
|
826
996
|
throw new Error("isInsideEdge: pt must have x and y properties");
|
|
827
997
|
}
|
|
828
|
-
if (
|
|
998
|
+
if (
|
|
999
|
+
!edgeStart ||
|
|
1000
|
+
edgeStart.x === null ||
|
|
1001
|
+
edgeStart.x === undefined ||
|
|
1002
|
+
edgeStart.y === null ||
|
|
1003
|
+
edgeStart.y === undefined
|
|
1004
|
+
) {
|
|
829
1005
|
throw new Error("isInsideEdge: edgeStart must have x and y properties");
|
|
830
1006
|
}
|
|
831
|
-
if (
|
|
1007
|
+
if (
|
|
1008
|
+
!edgeEnd ||
|
|
1009
|
+
edgeEnd.x === null ||
|
|
1010
|
+
edgeEnd.x === undefined ||
|
|
1011
|
+
edgeEnd.y === null ||
|
|
1012
|
+
edgeEnd.y === undefined
|
|
1013
|
+
) {
|
|
832
1014
|
throw new Error("isInsideEdge: edgeEnd must have x and y properties");
|
|
833
1015
|
}
|
|
834
1016
|
|
|
@@ -852,16 +1034,40 @@ function isInsideEdge(pt, edgeStart, edgeEnd) {
|
|
|
852
1034
|
*/
|
|
853
1035
|
function lineIntersection(a, b, c, d) {
|
|
854
1036
|
// Validate inputs (defensive check for internal function) - check for null/undefined explicitly
|
|
855
|
-
if (
|
|
1037
|
+
if (
|
|
1038
|
+
!a ||
|
|
1039
|
+
a.x === null ||
|
|
1040
|
+
a.x === undefined ||
|
|
1041
|
+
a.y === null ||
|
|
1042
|
+
a.y === undefined
|
|
1043
|
+
) {
|
|
856
1044
|
throw new Error("lineIntersection: point a must have x and y properties");
|
|
857
1045
|
}
|
|
858
|
-
if (
|
|
1046
|
+
if (
|
|
1047
|
+
!b ||
|
|
1048
|
+
b.x === null ||
|
|
1049
|
+
b.x === undefined ||
|
|
1050
|
+
b.y === null ||
|
|
1051
|
+
b.y === undefined
|
|
1052
|
+
) {
|
|
859
1053
|
throw new Error("lineIntersection: point b must have x and y properties");
|
|
860
1054
|
}
|
|
861
|
-
if (
|
|
1055
|
+
if (
|
|
1056
|
+
!c ||
|
|
1057
|
+
c.x === null ||
|
|
1058
|
+
c.x === undefined ||
|
|
1059
|
+
c.y === null ||
|
|
1060
|
+
c.y === undefined
|
|
1061
|
+
) {
|
|
862
1062
|
throw new Error("lineIntersection: point c must have x and y properties");
|
|
863
1063
|
}
|
|
864
|
-
if (
|
|
1064
|
+
if (
|
|
1065
|
+
!d ||
|
|
1066
|
+
d.x === null ||
|
|
1067
|
+
d.x === undefined ||
|
|
1068
|
+
d.y === null ||
|
|
1069
|
+
d.y === undefined
|
|
1070
|
+
) {
|
|
865
1071
|
throw new Error("lineIntersection: point d must have x and y properties");
|
|
866
1072
|
}
|
|
867
1073
|
|
|
@@ -937,8 +1143,16 @@ export function polygonArea(polygon) {
|
|
|
937
1143
|
|
|
938
1144
|
// Validate all polygon points have x and y properties
|
|
939
1145
|
for (let i = 0; i < n; i++) {
|
|
940
|
-
if (
|
|
941
|
-
|
|
1146
|
+
if (
|
|
1147
|
+
!polygon[i] ||
|
|
1148
|
+
polygon[i].x === null ||
|
|
1149
|
+
polygon[i].x === undefined ||
|
|
1150
|
+
polygon[i].y === null ||
|
|
1151
|
+
polygon[i].y === undefined
|
|
1152
|
+
) {
|
|
1153
|
+
throw new Error(
|
|
1154
|
+
`polygonArea: polygon[${i}] must have x and y properties`,
|
|
1155
|
+
);
|
|
942
1156
|
}
|
|
943
1157
|
}
|
|
944
1158
|
|
|
@@ -1083,8 +1297,16 @@ export function convexHull(points) {
|
|
|
1083
1297
|
if (points.length < 3) {
|
|
1084
1298
|
// Validate and convert points
|
|
1085
1299
|
for (let i = 0; i < points.length; i++) {
|
|
1086
|
-
if (
|
|
1087
|
-
|
|
1300
|
+
if (
|
|
1301
|
+
!points[i] ||
|
|
1302
|
+
points[i].x === null ||
|
|
1303
|
+
points[i].x === undefined ||
|
|
1304
|
+
points[i].y === null ||
|
|
1305
|
+
points[i].y === undefined
|
|
1306
|
+
) {
|
|
1307
|
+
throw new Error(
|
|
1308
|
+
`convexHull: points[${i}] must have x and y properties`,
|
|
1309
|
+
);
|
|
1088
1310
|
}
|
|
1089
1311
|
}
|
|
1090
1312
|
return points.map((p) => point(p.x, p.y));
|
|
@@ -1092,7 +1314,13 @@ export function convexHull(points) {
|
|
|
1092
1314
|
|
|
1093
1315
|
// Validate all points have x and y properties before converting
|
|
1094
1316
|
for (let i = 0; i < points.length; i++) {
|
|
1095
|
-
if (
|
|
1317
|
+
if (
|
|
1318
|
+
!points[i] ||
|
|
1319
|
+
points[i].x === null ||
|
|
1320
|
+
points[i].x === undefined ||
|
|
1321
|
+
points[i].y === null ||
|
|
1322
|
+
points[i].y === undefined
|
|
1323
|
+
) {
|
|
1096
1324
|
throw new Error(`convexHull: points[${i}] must have x and y properties`);
|
|
1097
1325
|
}
|
|
1098
1326
|
}
|
|
@@ -1183,7 +1411,13 @@ export function boundingBox(polygon) {
|
|
|
1183
1411
|
}
|
|
1184
1412
|
|
|
1185
1413
|
// Validate first point has x and y properties
|
|
1186
|
-
if (
|
|
1414
|
+
if (
|
|
1415
|
+
!polygon[0] ||
|
|
1416
|
+
polygon[0].x === null ||
|
|
1417
|
+
polygon[0].x === undefined ||
|
|
1418
|
+
polygon[0].y === null ||
|
|
1419
|
+
polygon[0].y === undefined
|
|
1420
|
+
) {
|
|
1187
1421
|
throw new Error("boundingBox: polygon[0] must have x and y properties");
|
|
1188
1422
|
}
|
|
1189
1423
|
|
|
@@ -1195,8 +1429,16 @@ export function boundingBox(polygon) {
|
|
|
1195
1429
|
for (let i = 0; i < polygon.length; i++) {
|
|
1196
1430
|
const p = polygon[i];
|
|
1197
1431
|
// Validate each point has x and y properties
|
|
1198
|
-
if (
|
|
1199
|
-
|
|
1432
|
+
if (
|
|
1433
|
+
!p ||
|
|
1434
|
+
p.x === null ||
|
|
1435
|
+
p.x === undefined ||
|
|
1436
|
+
p.y === null ||
|
|
1437
|
+
p.y === undefined
|
|
1438
|
+
) {
|
|
1439
|
+
throw new Error(
|
|
1440
|
+
`boundingBox: polygon[${i}] must have x and y properties`,
|
|
1441
|
+
);
|
|
1200
1442
|
}
|
|
1201
1443
|
const x = D(p.x);
|
|
1202
1444
|
const y = D(p.y);
|
|
@@ -1242,13 +1484,33 @@ export function bboxIntersects(bb1, bb2) {
|
|
|
1242
1484
|
if (!bb1 || !bb2) return false;
|
|
1243
1485
|
|
|
1244
1486
|
// Validate bounding boxes have required properties - check for null/undefined explicitly
|
|
1245
|
-
if (
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1487
|
+
if (
|
|
1488
|
+
bb1.minX === null ||
|
|
1489
|
+
bb1.minX === undefined ||
|
|
1490
|
+
bb1.minY === null ||
|
|
1491
|
+
bb1.minY === undefined ||
|
|
1492
|
+
bb1.maxX === null ||
|
|
1493
|
+
bb1.maxX === undefined ||
|
|
1494
|
+
bb1.maxY === null ||
|
|
1495
|
+
bb1.maxY === undefined
|
|
1496
|
+
) {
|
|
1497
|
+
throw new Error(
|
|
1498
|
+
"bboxIntersects: bb1 must have minX, minY, maxX, maxY properties",
|
|
1499
|
+
);
|
|
1500
|
+
}
|
|
1501
|
+
if (
|
|
1502
|
+
bb2.minX === null ||
|
|
1503
|
+
bb2.minX === undefined ||
|
|
1504
|
+
bb2.minY === null ||
|
|
1505
|
+
bb2.minY === undefined ||
|
|
1506
|
+
bb2.maxX === null ||
|
|
1507
|
+
bb2.maxX === undefined ||
|
|
1508
|
+
bb2.maxY === null ||
|
|
1509
|
+
bb2.maxY === undefined
|
|
1510
|
+
) {
|
|
1511
|
+
throw new Error(
|
|
1512
|
+
"bboxIntersects: bb2 must have minX, minY, maxX, maxY properties",
|
|
1513
|
+
);
|
|
1252
1514
|
}
|
|
1253
1515
|
|
|
1254
1516
|
return !(
|
|
@@ -1312,15 +1574,31 @@ export function polygonIntersection(subject, clip) {
|
|
|
1312
1574
|
|
|
1313
1575
|
// Validate all subject points have x and y properties
|
|
1314
1576
|
for (let i = 0; i < subject.length; i++) {
|
|
1315
|
-
if (
|
|
1316
|
-
|
|
1577
|
+
if (
|
|
1578
|
+
!subject[i] ||
|
|
1579
|
+
subject[i].x === null ||
|
|
1580
|
+
subject[i].x === undefined ||
|
|
1581
|
+
subject[i].y === null ||
|
|
1582
|
+
subject[i].y === undefined
|
|
1583
|
+
) {
|
|
1584
|
+
throw new Error(
|
|
1585
|
+
`polygonIntersection: subject[${i}] must have x and y properties`,
|
|
1586
|
+
);
|
|
1317
1587
|
}
|
|
1318
1588
|
}
|
|
1319
1589
|
|
|
1320
1590
|
// Validate all clip points have x and y properties
|
|
1321
1591
|
for (let i = 0; i < clip.length; i++) {
|
|
1322
|
-
if (
|
|
1323
|
-
|
|
1592
|
+
if (
|
|
1593
|
+
!clip[i] ||
|
|
1594
|
+
clip[i].x === null ||
|
|
1595
|
+
clip[i].x === undefined ||
|
|
1596
|
+
clip[i].y === null ||
|
|
1597
|
+
clip[i].y === undefined
|
|
1598
|
+
) {
|
|
1599
|
+
throw new Error(
|
|
1600
|
+
`polygonIntersection: clip[${i}] must have x and y properties`,
|
|
1601
|
+
);
|
|
1324
1602
|
}
|
|
1325
1603
|
}
|
|
1326
1604
|
|
|
@@ -1388,7 +1666,13 @@ export function isConvex(polygon) {
|
|
|
1388
1666
|
|
|
1389
1667
|
// Validate all polygon points have x and y properties
|
|
1390
1668
|
for (let i = 0; i < n; i++) {
|
|
1391
|
-
if (
|
|
1669
|
+
if (
|
|
1670
|
+
!polygon[i] ||
|
|
1671
|
+
polygon[i].x === null ||
|
|
1672
|
+
polygon[i].x === undefined ||
|
|
1673
|
+
polygon[i].y === null ||
|
|
1674
|
+
polygon[i].y === undefined
|
|
1675
|
+
) {
|
|
1392
1676
|
throw new Error(`isConvex: polygon[${i}] must have x and y properties`);
|
|
1393
1677
|
}
|
|
1394
1678
|
}
|
|
@@ -1438,7 +1722,9 @@ export function isConvex(polygon) {
|
|
|
1438
1722
|
function generalPolygonIntersection(subject, clip) {
|
|
1439
1723
|
// Validate inputs are arrays (defensive check for internal function)
|
|
1440
1724
|
if (!Array.isArray(subject) || !Array.isArray(clip)) {
|
|
1441
|
-
throw new Error(
|
|
1725
|
+
throw new Error(
|
|
1726
|
+
"generalPolygonIntersection: both arguments must be arrays",
|
|
1727
|
+
);
|
|
1442
1728
|
}
|
|
1443
1729
|
|
|
1444
1730
|
const intersectionPoints = [];
|
|
@@ -1566,15 +1852,31 @@ export function polygonUnion(polygon1, polygon2) {
|
|
|
1566
1852
|
|
|
1567
1853
|
// Validate all polygon1 points have x and y properties
|
|
1568
1854
|
for (let i = 0; i < polygon1.length; i++) {
|
|
1569
|
-
if (
|
|
1570
|
-
|
|
1855
|
+
if (
|
|
1856
|
+
!polygon1[i] ||
|
|
1857
|
+
polygon1[i].x === null ||
|
|
1858
|
+
polygon1[i].x === undefined ||
|
|
1859
|
+
polygon1[i].y === null ||
|
|
1860
|
+
polygon1[i].y === undefined
|
|
1861
|
+
) {
|
|
1862
|
+
throw new Error(
|
|
1863
|
+
`polygonUnion: polygon1[${i}] must have x and y properties`,
|
|
1864
|
+
);
|
|
1571
1865
|
}
|
|
1572
1866
|
}
|
|
1573
1867
|
|
|
1574
1868
|
// Validate all polygon2 points have x and y properties
|
|
1575
1869
|
for (let i = 0; i < polygon2.length; i++) {
|
|
1576
|
-
if (
|
|
1577
|
-
|
|
1870
|
+
if (
|
|
1871
|
+
!polygon2[i] ||
|
|
1872
|
+
polygon2[i].x === null ||
|
|
1873
|
+
polygon2[i].x === undefined ||
|
|
1874
|
+
polygon2[i].y === null ||
|
|
1875
|
+
polygon2[i].y === undefined
|
|
1876
|
+
) {
|
|
1877
|
+
throw new Error(
|
|
1878
|
+
`polygonUnion: polygon2[${i}] must have x and y properties`,
|
|
1879
|
+
);
|
|
1578
1880
|
}
|
|
1579
1881
|
}
|
|
1580
1882
|
|
|
@@ -1913,15 +2215,31 @@ export function polygonDifference(polygon1, polygon2) {
|
|
|
1913
2215
|
|
|
1914
2216
|
// Validate all polygon1 points have x and y properties
|
|
1915
2217
|
for (let i = 0; i < polygon1.length; i++) {
|
|
1916
|
-
if (
|
|
1917
|
-
|
|
2218
|
+
if (
|
|
2219
|
+
!polygon1[i] ||
|
|
2220
|
+
polygon1[i].x === null ||
|
|
2221
|
+
polygon1[i].x === undefined ||
|
|
2222
|
+
polygon1[i].y === null ||
|
|
2223
|
+
polygon1[i].y === undefined
|
|
2224
|
+
) {
|
|
2225
|
+
throw new Error(
|
|
2226
|
+
`polygonDifference: polygon1[${i}] must have x and y properties`,
|
|
2227
|
+
);
|
|
1918
2228
|
}
|
|
1919
2229
|
}
|
|
1920
2230
|
|
|
1921
2231
|
// Validate all polygon2 points have x and y properties
|
|
1922
2232
|
for (let i = 0; i < polygon2.length; i++) {
|
|
1923
|
-
if (
|
|
1924
|
-
|
|
2233
|
+
if (
|
|
2234
|
+
!polygon2[i] ||
|
|
2235
|
+
polygon2[i].x === null ||
|
|
2236
|
+
polygon2[i].x === undefined ||
|
|
2237
|
+
polygon2[i].y === null ||
|
|
2238
|
+
polygon2[i].y === undefined
|
|
2239
|
+
) {
|
|
2240
|
+
throw new Error(
|
|
2241
|
+
`polygonDifference: polygon2[${i}] must have x and y properties`,
|
|
2242
|
+
);
|
|
1925
2243
|
}
|
|
1926
2244
|
}
|
|
1927
2245
|
|