svg-path-commander 2.2.0 → 2.2.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/index.d.ts +1 -1
- package/dist/index.js +169 -163
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +2 -2
- package/dist/index.min.js.map +1 -1
- package/dist/util.d.ts +23 -19
- package/dist/util.js +168 -162
- package/dist/util.js.map +1 -1
- package/package.json +23 -16
- package/tsdown.config.ts +0 -75
package/dist/util.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* SVGPathCommander v2.2.
|
|
2
|
+
* SVGPathCommander v2.2.1 (http://thednp.github.io/svg-path-commander)
|
|
3
3
|
* Copyright 2026 © thednp
|
|
4
4
|
* Licensed under MIT (https://github.com/thednp/svg-path-commander/blob/master/LICENSE)
|
|
5
5
|
*/
|
|
@@ -1155,7 +1155,7 @@ declare const shortenSegment: (segment: AbsoluteSegment, normalSegment: NormalSe
|
|
|
1155
1155
|
//#region src/morph/fixPath.d.ts
|
|
1156
1156
|
/**
|
|
1157
1157
|
* Checks a `PathArray` for an unnecessary `Z` segment
|
|
1158
|
-
* and
|
|
1158
|
+
* and removes it. The `PathArray` is modified in place.
|
|
1159
1159
|
* In short, if the segment before `Z` extends to `M`,
|
|
1160
1160
|
* the `Z` segment must be removed.
|
|
1161
1161
|
*
|
|
@@ -1222,23 +1222,7 @@ declare const equalizeSegments: (path1: PathArray | string, path2: PathArray | s
|
|
|
1222
1222
|
*/
|
|
1223
1223
|
declare const equalizePaths: (pathInput1: string | PathArray, pathInput2: string | PathArray, initialCfg?: {}) => [MorphPathArray, MorphPathArray];
|
|
1224
1224
|
//#endregion
|
|
1225
|
-
//#region src/
|
|
1226
|
-
/**
|
|
1227
|
-
* Checks if a point is inside a bounding box.
|
|
1228
|
-
*
|
|
1229
|
-
* @param bbox - The bounding box as [minX, minY, maxX, maxY]
|
|
1230
|
-
* @param point - The point as [x, y]
|
|
1231
|
-
* @returns True if the point is inside or on the edge of the bounding box
|
|
1232
|
-
*/
|
|
1233
|
-
declare const isPointInsideBBox: (bbox: BBoxMaxima, [x, y]: PointTuple) => boolean;
|
|
1234
|
-
/**
|
|
1235
|
-
* Checks if two bounding boxes intersect.
|
|
1236
|
-
*
|
|
1237
|
-
* @param a - First bounding box as [minX, minY, maxX, maxY]
|
|
1238
|
-
* @param b - Second bounding box as [minX, minY, maxX, maxY]
|
|
1239
|
-
* @returns True if the bounding boxes overlap
|
|
1240
|
-
*/
|
|
1241
|
-
declare const boundingBoxIntersect: (a: BBoxMaxima, b: BBoxMaxima) => boolean;
|
|
1225
|
+
//#region src/intersect/pathIntersection.d.ts
|
|
1242
1226
|
/**
|
|
1243
1227
|
* Finds intersection points between two paths.
|
|
1244
1228
|
*
|
|
@@ -1257,5 +1241,25 @@ declare const boundingBoxIntersect: (a: BBoxMaxima, b: BBoxMaxima) => boolean;
|
|
|
1257
1241
|
*/
|
|
1258
1242
|
declare const pathsIntersection: <T extends string | PathArray>(pathInput1: T, pathInput2: T, justCount?: boolean) => number | IntersectionPoint[];
|
|
1259
1243
|
//#endregion
|
|
1244
|
+
//#region src/intersect/boundingBoxIntersect.d.ts
|
|
1245
|
+
/**
|
|
1246
|
+
* Checks if two bounding boxes intersect.
|
|
1247
|
+
*
|
|
1248
|
+
* @param a - First bounding box as [minX, minY, maxX, maxY]
|
|
1249
|
+
* @param b - Second bounding box as [minX, minY, maxX, maxY]
|
|
1250
|
+
* @returns True if the bounding boxes overlap
|
|
1251
|
+
*/
|
|
1252
|
+
declare const boundingBoxIntersect: (a: BBoxMaxima, b: BBoxMaxima) => boolean;
|
|
1253
|
+
//#endregion
|
|
1254
|
+
//#region src/intersect/isPointInsideBBox.d.ts
|
|
1255
|
+
/**
|
|
1256
|
+
* Checks if a point is inside a bounding box.
|
|
1257
|
+
*
|
|
1258
|
+
* @param bbox - The bounding box as [minX, minY, maxX, maxY]
|
|
1259
|
+
* @param point - The point as [x, y]
|
|
1260
|
+
* @returns True if the point is inside or on the edge of the bounding box
|
|
1261
|
+
*/
|
|
1262
|
+
declare const isPointInsideBBox: (bbox: BBoxMaxima, [x, y]: PointTuple) => boolean;
|
|
1263
|
+
//#endregion
|
|
1260
1264
|
export { PathParser, absolutizeSegment, arcToCubic, arcTools, bezierTools, boundingBoxIntersect, cubicTools, DISTANCE_EPSILON as distanceEpsilon, distanceSquareRoot, equalizePaths, equalizeSegments, finalizeSegment, fixPath, getClosestPoint, getDrawDirection, getPathArea, getPathBBox, getPointAtLength, getPropertiesAtLength, getPropertiesAtPoint, getSVGMatrix, getSegmentAtLength, getSegmentOfPoint, getTotalLength, invalidPathValue, isAbsoluteArray, isArcCommand, isClosedPath, isCurveArray, isDigit, isDigitStart, isMoveCommand, isMultiPath, isNormalizedArray, isPathArray, isPathCommand, isPointInStroke, isPointInsideBBox, isPolygonArray, isPolylineArray, isRelativeArray, isSpace, isValidPath, iterate, lineToCubic, lineTools, midPoint, normalizePath, normalizeSegment, optimizePath, paramsCounts, paramsParser, parsePathString, pathToAbsolute, pathToCurve, pathToRelative, pathToString, pathsIntersection, polygonTools, projection2d, quadToCubic, quadTools, relativizeSegment, reverseCurve, reversePath, rotateVector, roundPath, roundSegment, roundTo, scanFlag, scanParam, scanSegment, segmentToCubic, shapeParams, shapeToPath, shapeToPathArray, shortenSegment, skipSpaces, splitCubicSegment, splitPath, transformPath };
|
|
1261
1265
|
//# sourceMappingURL=util.d.ts.map
|
package/dist/util.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* SVGPathCommander v2.2.
|
|
2
|
+
* SVGPathCommander v2.2.1 (http://thednp.github.io/svg-path-commander)
|
|
3
3
|
* Copyright 2026 © thednp
|
|
4
4
|
* Licensed under MIT (https://github.com/thednp/svg-path-commander/blob/master/LICENSE)
|
|
5
5
|
*/
|
|
@@ -3393,7 +3393,7 @@ const roundPath = (path, roundOption) => {
|
|
|
3393
3393
|
//#region src/morph/fixPath.ts
|
|
3394
3394
|
/**
|
|
3395
3395
|
* Checks a `PathArray` for an unnecessary `Z` segment
|
|
3396
|
-
* and
|
|
3396
|
+
* and removes it. The `PathArray` is modified in place.
|
|
3397
3397
|
* In short, if the segment before `Z` extends to `M`,
|
|
3398
3398
|
* the `Z` segment must be removed.
|
|
3399
3399
|
*
|
|
@@ -3890,18 +3890,7 @@ const equalizeSegments = (path1, path2, initialCfg = {}) => {
|
|
|
3890
3890
|
return [equalP1, equalP2];
|
|
3891
3891
|
};
|
|
3892
3892
|
//#endregion
|
|
3893
|
-
//#region src/
|
|
3894
|
-
const intersect = (x1, y1, x2, y2, x3, y3, x4, y4) => {
|
|
3895
|
-
if (Math.max(x1, x2) < Math.min(x3, x4) || Math.min(x1, x2) > Math.max(x3, x4) || Math.max(y1, y2) < Math.min(y3, y4) || Math.min(y1, y2) > Math.max(y3, y4)) return;
|
|
3896
|
-
const nx = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4), ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4), denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
|
|
3897
|
-
if (!denominator) return;
|
|
3898
|
-
const px = nx / denominator, py = ny / denominator, px2 = roundTo(px, 2), py2 = roundTo(py, 2);
|
|
3899
|
-
if (px2 < roundTo(Math.min(x1, x2), 2) || px2 > roundTo(Math.max(x1, x2), 2) || px2 < roundTo(Math.min(x3, x4), 2) || px2 > roundTo(Math.max(x3, x4), 2) || py2 < roundTo(Math.min(y1, y2), 2) || py2 > roundTo(Math.max(y1, y2), 2) || py2 < roundTo(Math.min(y3, y4), 2) || py2 > roundTo(Math.max(y3, y4), 2)) return;
|
|
3900
|
-
return {
|
|
3901
|
-
x: px,
|
|
3902
|
-
y: py
|
|
3903
|
-
};
|
|
3904
|
-
};
|
|
3893
|
+
//#region src/intersect/isPointInsideBBox.ts
|
|
3905
3894
|
/**
|
|
3906
3895
|
* Checks if a point is inside a bounding box.
|
|
3907
3896
|
*
|
|
@@ -3913,6 +3902,8 @@ const isPointInsideBBox = (bbox, [x, y]) => {
|
|
|
3913
3902
|
const [minX, minY, maxX, maxY] = bbox;
|
|
3914
3903
|
return x >= minX && x <= maxX && y >= minY && y <= maxY;
|
|
3915
3904
|
};
|
|
3905
|
+
//#endregion
|
|
3906
|
+
//#region src/intersect/boundingBoxIntersect.ts
|
|
3916
3907
|
/**
|
|
3917
3908
|
* Checks if two bounding boxes intersect.
|
|
3918
3909
|
*
|
|
@@ -3925,154 +3916,6 @@ const boundingBoxIntersect = (a, b) => {
|
|
|
3925
3916
|
const [bx1, by1, bx2, by2] = b;
|
|
3926
3917
|
return isPointInsideBBox(b, [ax1, ay1]) || isPointInsideBBox(b, [ax2, ay1]) || isPointInsideBBox(b, [ax1, ay2]) || isPointInsideBBox(b, [ax2, ay2]) || isPointInsideBBox(a, [bx1, by1]) || isPointInsideBBox(a, [bx2, by1]) || isPointInsideBBox(a, [bx1, by2]) || isPointInsideBBox(a, [bx2, by2]) || (ax1 < bx2 && ax1 > bx1 || bx1 < ax2 && bx1 > ax1) && (ay1 < by2 && ay1 > by1 || by1 < ay2 && by1 > ay1);
|
|
3927
3918
|
};
|
|
3928
|
-
const interHelper = (bez1, bez2, config) => {
|
|
3929
|
-
const bbox1 = getCubicBBox(...bez1);
|
|
3930
|
-
const bbox2 = getCubicBBox(...bez2);
|
|
3931
|
-
const { justCount, epsilon } = Object.assign({
|
|
3932
|
-
justCount: true,
|
|
3933
|
-
epsilon: DISTANCE_EPSILON
|
|
3934
|
-
}, config);
|
|
3935
|
-
if (!boundingBoxIntersect(bbox1, bbox2)) return justCount ? 0 : [];
|
|
3936
|
-
const l1 = getCubicLength(...bez1), l2 = getCubicLength(...bez2), n1 = Math.max(l1 / 5 >> 0, 1), n2 = Math.max(l2 / 5 >> 0, 1), points1 = [], points2 = [], xy = {};
|
|
3937
|
-
let res = justCount ? 0 : [];
|
|
3938
|
-
for (let i = 0; i < n1 + 1; i++) {
|
|
3939
|
-
const p = getPointAtCubicLength(...bez1, i / n1 * l1);
|
|
3940
|
-
points1.push({
|
|
3941
|
-
x: p.x,
|
|
3942
|
-
y: p.y,
|
|
3943
|
-
t: i / n1
|
|
3944
|
-
});
|
|
3945
|
-
}
|
|
3946
|
-
for (let i = 0; i < n2 + 1; i++) {
|
|
3947
|
-
const p = getPointAtCubicLength(...bez2, i / n2 * l2);
|
|
3948
|
-
points2.push({
|
|
3949
|
-
x: p.x,
|
|
3950
|
-
y: p.y,
|
|
3951
|
-
t: i / n2
|
|
3952
|
-
});
|
|
3953
|
-
}
|
|
3954
|
-
for (let i = 0; i < n1; i++) for (let j = 0; j < n2; j++) {
|
|
3955
|
-
const maxLimit = 1 + epsilon, di = points1[i], di1 = points1[i + 1], dj = points2[j], dj1 = points2[j + 1], ci = Math.abs(di1.x - di.x) < .001 ? "y" : "x", cj = Math.abs(dj1.x - dj.x) < .001 ? "y" : "x", is = intersect(di.x, di.y, di1.x, di1.y, dj.x, dj.y, dj1.x, dj1.y);
|
|
3956
|
-
if (is) {
|
|
3957
|
-
if (xy[is.x.toFixed(4)] == is.y.toFixed(4)) continue;
|
|
3958
|
-
xy[is.x.toFixed(4)] = is.y.toFixed(4);
|
|
3959
|
-
const t1 = di.t + Math.abs((is[ci] - di[ci]) / (di1[ci] - di[ci])) * (di1.t - di.t), t2 = dj.t + Math.abs((is[cj] - dj[cj]) / (dj1[cj] - dj[cj])) * (dj1.t - dj.t);
|
|
3960
|
-
if (t1 >= 0 && t1 <= maxLimit && t2 >= 0 && t2 <= maxLimit) if (justCount) res++;
|
|
3961
|
-
else res.push({
|
|
3962
|
-
x: is.x,
|
|
3963
|
-
y: is.y,
|
|
3964
|
-
t1: Math.min(t1, 1),
|
|
3965
|
-
t2: Math.min(t2, 1)
|
|
3966
|
-
});
|
|
3967
|
-
}
|
|
3968
|
-
}
|
|
3969
|
-
return res;
|
|
3970
|
-
};
|
|
3971
|
-
/**
|
|
3972
|
-
* Finds intersection points between two paths.
|
|
3973
|
-
*
|
|
3974
|
-
* @param pathInput1 - First path string or PathArray
|
|
3975
|
-
* @param pathInput2 - Second path string or PathArray
|
|
3976
|
-
* @param justCount - If true, returns the count of intersections; if false, returns the intersection points
|
|
3977
|
-
* @returns The number of intersections (when justCount is true) or an array of IntersectionPoint objects
|
|
3978
|
-
*
|
|
3979
|
-
* @example
|
|
3980
|
-
* ```ts
|
|
3981
|
-
* pathsIntersection('M0 50C0 0,100 0,100 50', 'M50 0C100 0,100 100,50 100', true)
|
|
3982
|
-
* // => 1
|
|
3983
|
-
* pathsIntersection('M0 50C0 0,100 0,100 50', 'M50 0C100 0,100 100,50 100', false)
|
|
3984
|
-
* // => [{ x: 50, y: 25, t1: 0.5, t2: 0.5 }]
|
|
3985
|
-
* ```
|
|
3986
|
-
*/
|
|
3987
|
-
const pathsIntersection = (pathInput1, pathInput2, justCount = true) => {
|
|
3988
|
-
const path1 = pathToCurve(pathInput1);
|
|
3989
|
-
const path2 = pathToCurve(pathInput2);
|
|
3990
|
-
let x1 = 0, y1 = 0, x2 = 0, y2 = 0, x1m = 0, y1m = 0, x2m = 0, y2m = 0, bez1 = [
|
|
3991
|
-
x1,
|
|
3992
|
-
y1,
|
|
3993
|
-
x1,
|
|
3994
|
-
y1,
|
|
3995
|
-
x1m,
|
|
3996
|
-
y1m,
|
|
3997
|
-
x1m,
|
|
3998
|
-
y1m
|
|
3999
|
-
], bez2 = [
|
|
4000
|
-
x2,
|
|
4001
|
-
y2,
|
|
4002
|
-
x2,
|
|
4003
|
-
y2,
|
|
4004
|
-
x2m,
|
|
4005
|
-
y2m,
|
|
4006
|
-
x2m,
|
|
4007
|
-
y2m
|
|
4008
|
-
], countResult = 0;
|
|
4009
|
-
const pointsResult = [];
|
|
4010
|
-
const pathLen1 = path1.length;
|
|
4011
|
-
const pathLen2 = path2.length;
|
|
4012
|
-
for (let i = 0; i < pathLen1; i++) {
|
|
4013
|
-
const seg1 = path1[i];
|
|
4014
|
-
if (seg1[0] == "M") {
|
|
4015
|
-
x1 = seg1[1];
|
|
4016
|
-
y1 = seg1[2];
|
|
4017
|
-
x1m = x1;
|
|
4018
|
-
y1m = y1;
|
|
4019
|
-
} else {
|
|
4020
|
-
if (seg1[0] == "C") {
|
|
4021
|
-
bez1 = [
|
|
4022
|
-
x1,
|
|
4023
|
-
y1,
|
|
4024
|
-
seg1[1],
|
|
4025
|
-
seg1[2],
|
|
4026
|
-
seg1[3],
|
|
4027
|
-
seg1[4],
|
|
4028
|
-
seg1[5],
|
|
4029
|
-
seg1[6]
|
|
4030
|
-
];
|
|
4031
|
-
x1 = bez1[6];
|
|
4032
|
-
y1 = bez1[7];
|
|
4033
|
-
} else {
|
|
4034
|
-
bez1 = [
|
|
4035
|
-
x1,
|
|
4036
|
-
y1,
|
|
4037
|
-
x1,
|
|
4038
|
-
y1,
|
|
4039
|
-
x1m,
|
|
4040
|
-
y1m,
|
|
4041
|
-
x1m,
|
|
4042
|
-
y1m
|
|
4043
|
-
];
|
|
4044
|
-
x1 = x1m;
|
|
4045
|
-
y1 = y1m;
|
|
4046
|
-
}
|
|
4047
|
-
for (let j = 0; j < pathLen2; j++) {
|
|
4048
|
-
const seg2 = path2[j];
|
|
4049
|
-
if (seg2[0] == "M") {
|
|
4050
|
-
x2 = seg2[1];
|
|
4051
|
-
y2 = seg2[2];
|
|
4052
|
-
x2m = x2;
|
|
4053
|
-
y2m = y2;
|
|
4054
|
-
} else if (seg2[0] == "C") {
|
|
4055
|
-
bez2 = [
|
|
4056
|
-
x2,
|
|
4057
|
-
y2,
|
|
4058
|
-
seg2[1],
|
|
4059
|
-
seg2[2],
|
|
4060
|
-
seg2[3],
|
|
4061
|
-
seg2[4],
|
|
4062
|
-
seg2[5],
|
|
4063
|
-
seg2[6]
|
|
4064
|
-
];
|
|
4065
|
-
x2 = bez2[6];
|
|
4066
|
-
y2 = bez2[7];
|
|
4067
|
-
}
|
|
4068
|
-
const intr = interHelper(bez1, bez2, { justCount });
|
|
4069
|
-
if (justCount) countResult += intr;
|
|
4070
|
-
else pointsResult.push(...intr);
|
|
4071
|
-
}
|
|
4072
|
-
}
|
|
4073
|
-
}
|
|
4074
|
-
return justCount ? countResult : pointsResult;
|
|
4075
|
-
};
|
|
4076
3919
|
//#endregion
|
|
4077
3920
|
//#region src/morph/createPlaceholder.ts
|
|
4078
3921
|
/**
|
|
@@ -4272,6 +4115,169 @@ const equalizePaths = (pathInput1, pathInput2, initialCfg = {}) => {
|
|
|
4272
4115
|
return [equalizedPairs.map((p) => p[0]).flat(), equalizedPairs.map((p) => p[1]).flat()];
|
|
4273
4116
|
};
|
|
4274
4117
|
//#endregion
|
|
4118
|
+
//#region src/intersect/interHelper.ts
|
|
4119
|
+
const intersect = (x1, y1, x2, y2, x3, y3, x4, y4) => {
|
|
4120
|
+
if (Math.max(x1, x2) < Math.min(x3, x4) || Math.min(x1, x2) > Math.max(x3, x4) || Math.max(y1, y2) < Math.min(y3, y4) || Math.min(y1, y2) > Math.max(y3, y4)) return;
|
|
4121
|
+
const nx = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4), ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4), denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
|
|
4122
|
+
if (!denominator) return;
|
|
4123
|
+
const px = nx / denominator, py = ny / denominator, px2 = roundTo(px, 2), py2 = roundTo(py, 2);
|
|
4124
|
+
if (px2 < roundTo(Math.min(x1, x2), 2) || px2 > roundTo(Math.max(x1, x2), 2) || px2 < roundTo(Math.min(x3, x4), 2) || px2 > roundTo(Math.max(x3, x4), 2) || py2 < roundTo(Math.min(y1, y2), 2) || py2 > roundTo(Math.max(y1, y2), 2) || py2 < roundTo(Math.min(y3, y4), 2) || py2 > roundTo(Math.max(y3, y4), 2)) return;
|
|
4125
|
+
return {
|
|
4126
|
+
x: px,
|
|
4127
|
+
y: py
|
|
4128
|
+
};
|
|
4129
|
+
};
|
|
4130
|
+
const interHelper = (bez1, bez2, config) => {
|
|
4131
|
+
const bbox1 = getCubicBBox(...bez1);
|
|
4132
|
+
const bbox2 = getCubicBBox(...bez2);
|
|
4133
|
+
const { justCount, epsilon } = Object.assign({
|
|
4134
|
+
justCount: true,
|
|
4135
|
+
epsilon: DISTANCE_EPSILON
|
|
4136
|
+
}, config);
|
|
4137
|
+
if (!boundingBoxIntersect(bbox1, bbox2)) return justCount ? 0 : [];
|
|
4138
|
+
const l1 = getCubicLength(...bez1), l2 = getCubicLength(...bez2), n1 = Math.max(l1 / 5 >> 0, 1), n2 = Math.max(l2 / 5 >> 0, 1), points1 = [], points2 = [], xy = {};
|
|
4139
|
+
let res = justCount ? 0 : [];
|
|
4140
|
+
for (let i = 0; i < n1 + 1; i++) {
|
|
4141
|
+
const p = getPointAtCubicLength(...bez1, i / n1 * l1);
|
|
4142
|
+
points1.push({
|
|
4143
|
+
x: p.x,
|
|
4144
|
+
y: p.y,
|
|
4145
|
+
t: i / n1
|
|
4146
|
+
});
|
|
4147
|
+
}
|
|
4148
|
+
for (let i = 0; i < n2 + 1; i++) {
|
|
4149
|
+
const p = getPointAtCubicLength(...bez2, i / n2 * l2);
|
|
4150
|
+
points2.push({
|
|
4151
|
+
x: p.x,
|
|
4152
|
+
y: p.y,
|
|
4153
|
+
t: i / n2
|
|
4154
|
+
});
|
|
4155
|
+
}
|
|
4156
|
+
for (let i = 0; i < n1; i++) for (let j = 0; j < n2; j++) {
|
|
4157
|
+
const maxLimit = 1 + epsilon, di = points1[i], di1 = points1[i + 1], dj = points2[j], dj1 = points2[j + 1], ci = Math.abs(di1.x - di.x) < .001 ? "y" : "x", cj = Math.abs(dj1.x - dj.x) < .001 ? "y" : "x", is = intersect(di.x, di.y, di1.x, di1.y, dj.x, dj.y, dj1.x, dj1.y);
|
|
4158
|
+
if (is) {
|
|
4159
|
+
if (xy[is.x.toFixed(4)] == is.y.toFixed(4)) continue;
|
|
4160
|
+
xy[is.x.toFixed(4)] = is.y.toFixed(4);
|
|
4161
|
+
const t1 = di.t + Math.abs((is[ci] - di[ci]) / (di1[ci] - di[ci])) * (di1.t - di.t), t2 = dj.t + Math.abs((is[cj] - dj[cj]) / (dj1[cj] - dj[cj])) * (dj1.t - dj.t);
|
|
4162
|
+
if (t1 >= 0 && t1 <= maxLimit && t2 >= 0 && t2 <= maxLimit) if (justCount) res++;
|
|
4163
|
+
else res.push({
|
|
4164
|
+
x: is.x,
|
|
4165
|
+
y: is.y,
|
|
4166
|
+
t1: Math.min(t1, 1),
|
|
4167
|
+
t2: Math.min(t2, 1)
|
|
4168
|
+
});
|
|
4169
|
+
}
|
|
4170
|
+
}
|
|
4171
|
+
return res;
|
|
4172
|
+
};
|
|
4173
|
+
//#endregion
|
|
4174
|
+
//#region src/intersect/pathIntersection.ts
|
|
4175
|
+
/**
|
|
4176
|
+
* Finds intersection points between two paths.
|
|
4177
|
+
*
|
|
4178
|
+
* @param pathInput1 - First path string or PathArray
|
|
4179
|
+
* @param pathInput2 - Second path string or PathArray
|
|
4180
|
+
* @param justCount - If true, returns the count of intersections; if false, returns the intersection points
|
|
4181
|
+
* @returns The number of intersections (when justCount is true) or an array of IntersectionPoint objects
|
|
4182
|
+
*
|
|
4183
|
+
* @example
|
|
4184
|
+
* ```ts
|
|
4185
|
+
* pathsIntersection('M0 50C0 0,100 0,100 50', 'M50 0C100 0,100 100,50 100', true)
|
|
4186
|
+
* // => 1
|
|
4187
|
+
* pathsIntersection('M0 50C0 0,100 0,100 50', 'M50 0C100 0,100 100,50 100', false)
|
|
4188
|
+
* // => [{ x: 50, y: 25, t1: 0.5, t2: 0.5 }]
|
|
4189
|
+
* ```
|
|
4190
|
+
*/
|
|
4191
|
+
const pathsIntersection = (pathInput1, pathInput2, justCount = true) => {
|
|
4192
|
+
const path1 = pathToCurve(pathInput1);
|
|
4193
|
+
const path2 = pathToCurve(pathInput2);
|
|
4194
|
+
let x1 = 0, y1 = 0, x2 = 0, y2 = 0, x1m = 0, y1m = 0, x2m = 0, y2m = 0, bez1 = [
|
|
4195
|
+
x1,
|
|
4196
|
+
y1,
|
|
4197
|
+
x1,
|
|
4198
|
+
y1,
|
|
4199
|
+
x1m,
|
|
4200
|
+
y1m,
|
|
4201
|
+
x1m,
|
|
4202
|
+
y1m
|
|
4203
|
+
], bez2 = [
|
|
4204
|
+
x2,
|
|
4205
|
+
y2,
|
|
4206
|
+
x2,
|
|
4207
|
+
y2,
|
|
4208
|
+
x2m,
|
|
4209
|
+
y2m,
|
|
4210
|
+
x2m,
|
|
4211
|
+
y2m
|
|
4212
|
+
], countResult = 0;
|
|
4213
|
+
const pointsResult = [];
|
|
4214
|
+
const pathLen1 = path1.length;
|
|
4215
|
+
const pathLen2 = path2.length;
|
|
4216
|
+
for (let i = 0; i < pathLen1; i++) {
|
|
4217
|
+
const seg1 = path1[i];
|
|
4218
|
+
if (seg1[0] == "M") {
|
|
4219
|
+
x1 = seg1[1];
|
|
4220
|
+
y1 = seg1[2];
|
|
4221
|
+
x1m = x1;
|
|
4222
|
+
y1m = y1;
|
|
4223
|
+
} else {
|
|
4224
|
+
if (seg1[0] == "C") {
|
|
4225
|
+
bez1 = [
|
|
4226
|
+
x1,
|
|
4227
|
+
y1,
|
|
4228
|
+
seg1[1],
|
|
4229
|
+
seg1[2],
|
|
4230
|
+
seg1[3],
|
|
4231
|
+
seg1[4],
|
|
4232
|
+
seg1[5],
|
|
4233
|
+
seg1[6]
|
|
4234
|
+
];
|
|
4235
|
+
x1 = bez1[6];
|
|
4236
|
+
y1 = bez1[7];
|
|
4237
|
+
} else {
|
|
4238
|
+
bez1 = [
|
|
4239
|
+
x1,
|
|
4240
|
+
y1,
|
|
4241
|
+
x1,
|
|
4242
|
+
y1,
|
|
4243
|
+
x1m,
|
|
4244
|
+
y1m,
|
|
4245
|
+
x1m,
|
|
4246
|
+
y1m
|
|
4247
|
+
];
|
|
4248
|
+
x1 = x1m;
|
|
4249
|
+
y1 = y1m;
|
|
4250
|
+
}
|
|
4251
|
+
for (let j = 0; j < pathLen2; j++) {
|
|
4252
|
+
const seg2 = path2[j];
|
|
4253
|
+
if (seg2[0] == "M") {
|
|
4254
|
+
x2 = seg2[1];
|
|
4255
|
+
y2 = seg2[2];
|
|
4256
|
+
x2m = x2;
|
|
4257
|
+
y2m = y2;
|
|
4258
|
+
} else if (seg2[0] == "C") {
|
|
4259
|
+
bez2 = [
|
|
4260
|
+
x2,
|
|
4261
|
+
y2,
|
|
4262
|
+
seg2[1],
|
|
4263
|
+
seg2[2],
|
|
4264
|
+
seg2[3],
|
|
4265
|
+
seg2[4],
|
|
4266
|
+
seg2[5],
|
|
4267
|
+
seg2[6]
|
|
4268
|
+
];
|
|
4269
|
+
x2 = bez2[6];
|
|
4270
|
+
y2 = bez2[7];
|
|
4271
|
+
}
|
|
4272
|
+
const intr = interHelper(bez1, bez2, { justCount });
|
|
4273
|
+
if (justCount) countResult += intr;
|
|
4274
|
+
else pointsResult.push(...intr);
|
|
4275
|
+
}
|
|
4276
|
+
}
|
|
4277
|
+
}
|
|
4278
|
+
return justCount ? countResult : pointsResult;
|
|
4279
|
+
};
|
|
4280
|
+
//#endregion
|
|
4275
4281
|
export { PathParser, absolutizeSegment, arcToCubic, arcTools, bezierTools, boundingBoxIntersect, cubicTools, DISTANCE_EPSILON as distanceEpsilon, distanceSquareRoot, equalizePaths, equalizeSegments, finalizeSegment, fixPath, getClosestPoint, getDrawDirection, getPathArea, getPathBBox, getPointAtLength, getPropertiesAtLength, getPropertiesAtPoint, getSVGMatrix, getSegmentAtLength, getSegmentOfPoint, getTotalLength, invalidPathValue, isAbsoluteArray, isArcCommand, isClosedPath, isCurveArray, isDigit, isDigitStart, isMoveCommand, isMultiPath, isNormalizedArray, isPathArray, isPathCommand, isPointInStroke, isPointInsideBBox, isPolygonArray, isPolylineArray, isRelativeArray, isSpace, isValidPath, iterate, lineToCubic, lineTools, midPoint, normalizePath, normalizeSegment, optimizePath, paramsCounts, paramsParser, parsePathString, pathToAbsolute, pathToCurve, pathToRelative, pathToString, pathsIntersection, polygonTools, projection2d, quadToCubic, quadTools, relativizeSegment, reverseCurve, reversePath, rotateVector, roundPath, roundSegment, roundTo, scanFlag, scanParam, scanSegment, segmentToCubic, shapeParams, shapeToPath, shapeToPathArray, shortenSegment, skipSpaces, splitCubicSegment, splitPath, transformPath };
|
|
4276
4282
|
|
|
4277
4283
|
//# sourceMappingURL=util.js.map
|