@weasel-js/geom 1.13.0 → 1.14.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/README.md +6 -2
- package/dist/3d/index.d.ts +8 -1
- package/dist/3d/index.js +25 -1
- package/dist/3d/index.js.map +1 -1
- package/dist/booleans/index.d.ts +6 -5
- package/dist/booleans/index.js +583 -73
- package/dist/booleans/index.js.map +1 -1
- package/dist/{chunk-CE7IY7TB.js → chunk-2N6OWA7E.js} +3 -3
- package/dist/{chunk-CE7IY7TB.js.map → chunk-2N6OWA7E.js.map} +1 -1
- package/dist/{chunk-Q66NA2FU.js → chunk-3HQJGI63.js} +8 -5
- package/dist/chunk-3HQJGI63.js.map +1 -0
- package/dist/{chunk-YPWFGFQX.js → chunk-3YH5XU3H.js} +125 -8
- package/dist/chunk-3YH5XU3H.js.map +1 -0
- package/dist/{chunk-UI3FUWXM.js → chunk-42TZDN5C.js} +4 -4
- package/dist/{chunk-UI3FUWXM.js.map → chunk-42TZDN5C.js.map} +1 -1
- package/dist/{chunk-B53BERKG.js → chunk-B3D6KWW3.js} +110 -8
- package/dist/chunk-B3D6KWW3.js.map +1 -0
- package/dist/{chunk-2PKPKU4P.js → chunk-EURWZUNY.js} +25 -22
- package/dist/chunk-EURWZUNY.js.map +1 -0
- package/dist/{chunk-VHXOCDZ2.js → chunk-FROQPADA.js} +6 -6
- package/dist/{chunk-VHXOCDZ2.js.map → chunk-FROQPADA.js.map} +1 -1
- package/dist/{chunk-UGE57OTX.js → chunk-GWSJQSQE.js} +11 -8
- package/dist/chunk-GWSJQSQE.js.map +1 -0
- package/dist/chunk-XXNK4N7Z.js +683 -0
- package/dist/chunk-XXNK4N7Z.js.map +1 -0
- package/dist/chunk-ZOMUTU7J.js +249 -0
- package/dist/chunk-ZOMUTU7J.js.map +1 -0
- package/dist/{curvature-PkoLduGc.d.ts → curvature-CDOI32hv.d.ts} +46 -3
- package/dist/curves/index.d.ts +2 -2
- package/dist/curves/index.js +4 -4
- package/dist/index.d.ts +172 -45
- package/dist/index.js +244 -178
- package/dist/index.js.map +1 -1
- package/dist/nd/index.d.ts +28 -1
- package/dist/nd/index.js +27 -675
- package/dist/nd/index.js.map +1 -1
- package/dist/{path-BW8d_2RY.d.ts → path-t80OoJnM.d.ts} +11 -0
- package/dist/tessellate/index.d.ts +11 -4
- package/dist/tessellate/index.js +4 -4
- package/dist/warp/index.d.ts +1 -1
- package/dist/warp/index.js +238 -64
- package/dist/warp/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-2PKPKU4P.js.map +0 -1
- package/dist/chunk-B53BERKG.js.map +0 -1
- package/dist/chunk-Q66NA2FU.js.map +0 -1
- package/dist/chunk-STGSBIOL.js +0 -152
- package/dist/chunk-STGSBIOL.js.map +0 -1
- package/dist/chunk-UGE57OTX.js.map +0 -1
- package/dist/chunk-YPWFGFQX.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
import { carryCorners,
|
|
2
|
-
export { CORNER_RESTORE_TOLERANCE, cornerTraces, keepCorners, restoreCorners } from './chunk-
|
|
1
|
+
import { carryCorners, parseSubpaths, intersectSegments, evalSeg, keepCorners, anchorRange, subSeg, writePath, derivSeg } from './chunk-3YH5XU3H.js';
|
|
2
|
+
export { CORNER_RESTORE_TOLERANCE, cornerTraces, intersectSegments, keepCorners, restoreCorners } from './chunk-3YH5XU3H.js';
|
|
3
|
+
import { createBvh } from './chunk-XXNK4N7Z.js';
|
|
3
4
|
import { PORT_REACH, portControls, portCurvePoints } from './chunk-YQADYJJ7.js';
|
|
4
5
|
export { PORT_REACH } from './chunk-YQADYJJ7.js';
|
|
5
|
-
import { cubicDerivativeAt, cubicCurvatureAt } from './chunk-
|
|
6
|
-
export { SPIRO_KINDS, combTeeth, cubicCurvatureAt, cubicCurvatureSource, cubicDerivativeAt, curvatureComb, eulerAngleAt, eulerCurvatureAt, eulerCurvatureDerivativesAt, eulerPointAt, fitEulerSegment, isSpiroKind, placeEulerSegment, solveSpiro, spiroContoursFromControl, spiroContoursOf, spiroControlPath, spiroToPath } from './chunk-
|
|
7
|
-
import { extractPolylines } from './chunk-
|
|
8
|
-
import { boundsOfPath, fitPointRun, keepCorner } from './chunk-
|
|
9
|
-
export { boundsOfPath } from './chunk-
|
|
10
|
-
import { countPathAnchors, pathToAnchors, anchorsToPath, isAnchorSmooth, segmentEnds, isStraightSegment, nearestSegmentT } from './chunk-
|
|
11
|
-
export { anchorsToPath, countPathAnchors, isAnchorSmooth, isStraightSegment, nearestSegmentT, pathToAnchors, segmentEnds } from './chunk-
|
|
12
|
-
import { nearestOnLine, nearestOnPath, nearestOnQuadratic, nearestOnCubic } from './chunk-
|
|
13
|
-
export { nearestOnCubic, nearestOnLine, nearestOnPath, nearestOnQuadratic } from './chunk-
|
|
14
|
-
import { resolveCorners, pointInPolygon, cornerCuts, fillsOpenSubpaths, schneiderFit, fitCubicWithTangents, flattenCubic, pointSegmentDist2, flattenQuadratic, DEFAULT_FLATTEN_TOLERANCE, segmentsCross } from './chunk-
|
|
15
|
-
export { CORNER_FIT_TOLERANCE, CORNER_KEYWORDS, DEFAULT_FLATTEN_TOLERANCE, cornerCenter, cornerCuts, cornerFrameAt, cornerFrames, cornerKeywordOf, cornerShapeK, cornerShapePieces, cornerShapePoint, defaultOpenFill, fillsOpenSubpaths, fitCubicWithTangents, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, isCornerShape, nextCornerShape, pointInPolygon, pointSegmentDist2, remapPerAnchor, resolveCorners, resolveCornersWithSources, schneiderFit, segmentsCross, setDefaultOpenFill } from './chunk-
|
|
6
|
+
import { cubicDerivativeAt, cubicCurvatureAt } from './chunk-42TZDN5C.js';
|
|
7
|
+
export { SPIRO_KINDS, combTeeth, cubicCurvatureAt, cubicCurvatureSource, cubicDerivativeAt, curvatureComb, eulerAngleAt, eulerCurvatureAt, eulerCurvatureDerivativesAt, eulerPointAt, fitEulerSegment, isSpiroKind, placeEulerSegment, solveSpiro, spiroContoursFromControl, spiroContoursOf, spiroControlPath, spiroToPath } from './chunk-42TZDN5C.js';
|
|
8
|
+
import { extractPolylines } from './chunk-FROQPADA.js';
|
|
9
|
+
import { boundsOfPath, fitPointRun, keepCorner } from './chunk-ZOMUTU7J.js';
|
|
10
|
+
export { boundsOfPath } from './chunk-ZOMUTU7J.js';
|
|
11
|
+
import { countPathAnchors, pathToAnchors, anchorsToPath, isAnchorSmooth, segmentEnds, isStraightSegment, nearestSegmentT } from './chunk-3HQJGI63.js';
|
|
12
|
+
export { anchorsToPath, countPathAnchors, isAnchorSmooth, isStraightSegment, nearestSegmentT, pathToAnchors, segmentEnds } from './chunk-3HQJGI63.js';
|
|
13
|
+
import { nearestOnLine, nearestOnPath, nearestOnQuadratic, nearestOnCubic } from './chunk-2N6OWA7E.js';
|
|
14
|
+
export { nearestOnCubic, nearestOnLine, nearestOnPath, nearestOnQuadratic } from './chunk-2N6OWA7E.js';
|
|
15
|
+
import { resolveCorners, pointInPolygon, cornerCuts, fillsOpenSubpaths, schneiderFit, fitCubicWithTangents, flattenCubic, pointSegmentDist2, flattenQuadratic, DEFAULT_FLATTEN_TOLERANCE, segmentsCross, tangentAt } from './chunk-EURWZUNY.js';
|
|
16
|
+
export { CORNER_FIT_TOLERANCE, CORNER_KEYWORDS, DEFAULT_FLATTEN_TOLERANCE, cornerCenter, cornerCuts, cornerFrameAt, cornerFrames, cornerKeywordOf, cornerShapeK, cornerShapePieces, cornerShapePoint, defaultOpenFill, fillsOpenSubpaths, fitCubicWithTangents, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, isCornerShape, nextCornerShape, pointInPolygon, pointSegmentDist2, remapPerAnchor, resolveCorners, resolveCornersWithSources, schneiderFit, segmentsCross, setDefaultOpenFill } from './chunk-EURWZUNY.js';
|
|
16
17
|
import { SINGULAR_RATIO, clamp } from './chunk-755Y4YZS.js';
|
|
17
18
|
export { EPS, approxEq, clamp, cross, dot, len2, sign, sub } from './chunk-755Y4YZS.js';
|
|
18
|
-
import { PATH_M, PATH_L, PATH_C, PATH_Q, PATH_Z, PathBuilder, withCorner, scaleCorners, forEachSegment, pathCommandCoordCount, withoutCorners, elevateQuadraticToCubic, cubicEvalAt, cubicPointAt, splitCubicAtT, cubicAxisExtremaTs, rectToContour, splitCubicAt } from './chunk-
|
|
19
|
-
export { PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_Z, PathBuilder, asPolygonPath, boundsOfCoords, boxContainsBox, boxContainsPoint, compactCorners, cornerAt, cornerSpecAt, cubicAxisExtremaTs, cubicBounds, cubicEvalAt, cubicPointAt, elevateQuadraticToCubic, ellipsePath, forEachSegment, hasCorners, lerpCorners, linePath, pathCommandCoordCount, polygonFromPoints, polylineFromPoints, quadraticEvalAt, rectPath, rectToContour, regularPolygonPath, scaleCorners, splitCubicAt, splitCubicAtT, splitLineAt, splitQuadraticAt, starPath, unionBox, withCorner, withoutCorners } from './chunk-
|
|
19
|
+
import { worldCoords, PATH_M, PATH_L, PATH_C, PATH_Q, PATH_Z, PathBuilder, withCorner, scaleCorners, originFor, coordsFrom, forEachSegment, pathCommandCoordCount, withoutCorners, elevateQuadraticToCubic, cubicEvalAt, cubicPointAt, splitCubicAtT, cubicAxisExtremaTs, rectToContour, splitCubicAt } from './chunk-B3D6KWW3.js';
|
|
20
|
+
export { ORIGIN_THRESHOLD, PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_Z, PathBuilder, addOrigin, asPolygonPath, boundsOfCoords, boxContainsBox, boxContainsPoint, compactCorners, coordsFrom, cornerAt, cornerSpecAt, cubicAxisExtremaTs, cubicBounds, cubicEvalAt, cubicPointAt, elevateQuadraticToCubic, ellipsePath, forEachSegment, hasCorners, joinPaths, lerpCorners, linePath, originFor, originOf, pathCommandCoordCount, pathPoint, polygonFromPoints, polylineFromPoints, quadraticEvalAt, rectPath, rectToContour, regularPolygonPath, scaleCorners, splitCubicAt, splitCubicAtT, splitLineAt, splitQuadraticAt, starPath, unionBox, withCorner, withoutCorners, worldCoords } from './chunk-B3D6KWW3.js';
|
|
20
21
|
|
|
21
22
|
// src/view.ts
|
|
22
23
|
var ZOOM_FLOOR = 1e-9;
|
|
@@ -440,25 +441,26 @@ function pathShape(path, options = {}) {
|
|
|
440
441
|
// src/track/run.ts
|
|
441
442
|
var pointsDown = (normal2) => normal2.y > 1e-9;
|
|
442
443
|
function trackRun(shape, from = 0, to = 1, options = {}) {
|
|
443
|
-
const { side = "auto", about = (from + to) / 2 } = options;
|
|
444
|
+
const { side = "auto", about = (from + to) / 2, direction = "ltr" } = options;
|
|
445
|
+
const rtl = direction === "rtl";
|
|
444
446
|
const mid = shape.at(about);
|
|
445
447
|
const flipped = side === "auto" ? pointsDown(mid.normal) : side === "flipped";
|
|
446
448
|
const sgn = flipped ? -1 : 1;
|
|
447
449
|
const reading = (n) => ({ x: -(sgn * n.y), y: sgn * n.x });
|
|
448
450
|
const r0 = reading(mid.normal);
|
|
449
|
-
const reversed3 = r0.x * mid.tangent.x + r0.y * mid.tangent.y < 0;
|
|
451
|
+
const reversed3 = r0.x * mid.tangent.x + r0.y * mid.tangent.y < 0 !== rtl;
|
|
450
452
|
const span = to - from;
|
|
451
453
|
const lo = Math.min(from, to);
|
|
452
454
|
const hi = Math.max(from, to);
|
|
453
|
-
const
|
|
455
|
+
const toShape = (g) => reversed3 ? to - g * span : from + g * span;
|
|
454
456
|
const at2 = (g, options2) => {
|
|
455
|
-
const s = options2?.open ? shape.at(
|
|
457
|
+
const s = options2?.open ? shape.at(toShape(g), options2) : shape.at(toShape(clamp(g, 0, 1)));
|
|
456
458
|
const dir = reading(s.normal);
|
|
457
459
|
const angle = Math.atan2(dir.y, dir.x) * 180 / Math.PI;
|
|
458
460
|
const normal2 = { x: sgn * s.normal.x, y: sgn * s.normal.y };
|
|
459
461
|
return {
|
|
460
462
|
point: s.point,
|
|
461
|
-
tangent: dir,
|
|
463
|
+
tangent: rtl ? { x: -dir.x, y: -dir.y } : dir,
|
|
462
464
|
normal: normal2,
|
|
463
465
|
angle: angle === 0 ? 0 : angle === -180 ? 180 : angle,
|
|
464
466
|
turned: pointsDown(normal2)
|
|
@@ -470,7 +472,7 @@ function trackRun(shape, from = 0, to = 1, options = {}) {
|
|
|
470
472
|
const q = shape.at(f).point;
|
|
471
473
|
const dist = Math.hypot(p.x - q.x, p.y - q.y);
|
|
472
474
|
if (!options2?.open) return { f: toG(f), dist };
|
|
473
|
-
return { f: toG(shape.nearest(p, { open: true, about:
|
|
475
|
+
return { f: toG(shape.nearest(p, { open: true, about: toShape(options2.about ?? 0.5) }).f), dist };
|
|
474
476
|
};
|
|
475
477
|
return {
|
|
476
478
|
kind: shape.kind,
|
|
@@ -481,7 +483,9 @@ function trackRun(shape, from = 0, to = 1, options = {}) {
|
|
|
481
483
|
to,
|
|
482
484
|
flipped,
|
|
483
485
|
reversed: reversed3,
|
|
486
|
+
direction,
|
|
484
487
|
at: at2,
|
|
488
|
+
toShape,
|
|
485
489
|
nearest
|
|
486
490
|
};
|
|
487
491
|
}
|
|
@@ -495,7 +499,7 @@ function pathToD(given) {
|
|
|
495
499
|
return `M${num(x)} ${num(y)}h${num(width)}v${num(height)}h${num(-width)}Z`;
|
|
496
500
|
}
|
|
497
501
|
const cmds = path.commands;
|
|
498
|
-
const xs = path
|
|
502
|
+
const xs = worldCoords(path);
|
|
499
503
|
const out = [];
|
|
500
504
|
let ci = 0;
|
|
501
505
|
for (let i = 0; i < cmds.length; i++) {
|
|
@@ -732,7 +736,9 @@ function portCurvePoints2(ax, ay, bx, by, outNormal, inNormal, samples, reach =
|
|
|
732
736
|
|
|
733
737
|
// src/pathSubpaths.ts
|
|
734
738
|
function flatSubpaths(path, tolerance) {
|
|
735
|
-
const
|
|
739
|
+
const drawn = resolveCorners(path);
|
|
740
|
+
const { commands } = drawn;
|
|
741
|
+
const coords = worldCoords(drawn);
|
|
736
742
|
const closed = [];
|
|
737
743
|
const open = [];
|
|
738
744
|
let sub3 = [];
|
|
@@ -1174,7 +1180,7 @@ function unionBoundsPath(paths) {
|
|
|
1174
1180
|
|
|
1175
1181
|
// src/paths/transformPath.ts
|
|
1176
1182
|
var AXIS_ALIGNED_EPSILON = 1e-9;
|
|
1177
|
-
function transformPath(path, m) {
|
|
1183
|
+
function transformPath(path, m, opts = {}) {
|
|
1178
1184
|
const [a, b, c, d, e, f] = m;
|
|
1179
1185
|
if (path.kind === "rect") {
|
|
1180
1186
|
if (Math.abs(b) < AXIS_ALIGNED_EPSILON && Math.abs(c) < AXIS_ALIGNED_EPSILON) {
|
|
@@ -1190,15 +1196,25 @@ function transformPath(path, m) {
|
|
|
1190
1196
|
height: Math.abs(y1 - y0)
|
|
1191
1197
|
};
|
|
1192
1198
|
}
|
|
1193
|
-
const poly = new PathBuilder().moveTo(path.x, path.y).lineTo(path.x + path.width, path.y).lineTo(path.x + path.width, path.y + path.height).lineTo(path.x, path.y + path.height).close().build();
|
|
1194
|
-
return transformPolygon(poly, m);
|
|
1199
|
+
const poly = new PathBuilder().autoOrigin().moveTo(path.x, path.y).lineTo(path.x + path.width, path.y).lineTo(path.x + path.width, path.y + path.height).lineTo(path.x, path.y + path.height).close().build();
|
|
1200
|
+
return transformPolygon(poly, m, opts);
|
|
1195
1201
|
}
|
|
1196
|
-
return transformPolygon(path, m);
|
|
1202
|
+
return transformPolygon(path, m, opts);
|
|
1197
1203
|
}
|
|
1198
|
-
function transformPolygon(path, m) {
|
|
1199
|
-
const mapped = transformCoords(path.coords, m);
|
|
1204
|
+
function transformPolygon(path, m, opts) {
|
|
1200
1205
|
const scaled2 = scaleCorners(path, Math.sqrt(Math.abs(m[0] * m[3] - m[1] * m[2])));
|
|
1201
|
-
|
|
1206
|
+
const o = path.origin;
|
|
1207
|
+
if (o === void 0) {
|
|
1208
|
+
const mapped = transformCoords(path.coords, m);
|
|
1209
|
+
const picked = opts.autoOrigin !== false ? originFor(mapped) : void 0;
|
|
1210
|
+
return picked ? { ...scaled2, coords: coordsFrom(picked, mapped), origin: picked } : { ...scaled2, coords: Float32Array.from(mapped) };
|
|
1211
|
+
}
|
|
1212
|
+
const [a, b, c, d, e, f] = m;
|
|
1213
|
+
return {
|
|
1214
|
+
...scaled2,
|
|
1215
|
+
coords: Float32Array.from(transformCoords(path.coords, [a, b, c, d, 0, 0])),
|
|
1216
|
+
origin: { x: a * o.x + c * o.y + e, y: b * o.x + d * o.y + f }
|
|
1217
|
+
};
|
|
1202
1218
|
}
|
|
1203
1219
|
|
|
1204
1220
|
// src/paths/transform.ts
|
|
@@ -1209,6 +1225,8 @@ function translatePath(path, dx2, dy2) {
|
|
|
1209
1225
|
return translatePolygonCopy(path, dx2, dy2);
|
|
1210
1226
|
}
|
|
1211
1227
|
function translatePolygonCopy(path, dx2, dy2) {
|
|
1228
|
+
const o = path.origin;
|
|
1229
|
+
if (o) return { ...path, coords: path.coords.slice(), origin: { x: o.x + dx2, y: o.y + dy2 } };
|
|
1212
1230
|
const next = new Float32Array(path.coords.length);
|
|
1213
1231
|
const { commands, coords } = path;
|
|
1214
1232
|
forEachSegment(commands, coords, (cmd, ci) => {
|
|
@@ -1529,7 +1547,7 @@ var ARG_COUNTS = {
|
|
|
1529
1547
|
};
|
|
1530
1548
|
function pathFromD(d, onWarn) {
|
|
1531
1549
|
const tokens = tokenize(d);
|
|
1532
|
-
const b = new PathBuilder();
|
|
1550
|
+
const b = new PathBuilder().autoOrigin();
|
|
1533
1551
|
const st = {
|
|
1534
1552
|
x: 0,
|
|
1535
1553
|
y: 0,
|
|
@@ -1797,7 +1815,9 @@ function pathToCubicContours(path) {
|
|
|
1797
1815
|
if (current.segs.length > 0) out.push(current);
|
|
1798
1816
|
current = null;
|
|
1799
1817
|
};
|
|
1800
|
-
const
|
|
1818
|
+
const drawn = resolveCorners(path);
|
|
1819
|
+
const { commands } = drawn;
|
|
1820
|
+
const coords = worldCoords(drawn);
|
|
1801
1821
|
forEachSegment(commands, coords, (cmd, ci, px, py, _i, opens) => {
|
|
1802
1822
|
if (opens) {
|
|
1803
1823
|
current = { segs: [], closed: false };
|
|
@@ -2105,6 +2125,103 @@ function repeatAlongPath(shape, path, opts = {}) {
|
|
|
2105
2125
|
});
|
|
2106
2126
|
}
|
|
2107
2127
|
|
|
2128
|
+
// src/paths/contourSamples.ts
|
|
2129
|
+
function sampleAt({ c, line }, t) {
|
|
2130
|
+
const [x, y] = cubicEvalAt(...c, t);
|
|
2131
|
+
const seg = { line, p0: { x: c[0], y: c[1] }, c1: { x: c[2], y: c[3] }, c2: { x: c[4], y: c[5] }, p3: { x: c[6], y: c[7] } };
|
|
2132
|
+
return { at: { x, y }, dir: tangentAt(seg, t) };
|
|
2133
|
+
}
|
|
2134
|
+
function sampleContour(contour, pieces) {
|
|
2135
|
+
const out = [];
|
|
2136
|
+
for (const seg of contour.segs) for (let k = 0; k < pieces; k++) out.push(sampleAt(seg, k / pieces));
|
|
2137
|
+
const last = contour.segs.at(-1);
|
|
2138
|
+
if (!contour.closed && last !== void 0) out.push(sampleAt(last, 1));
|
|
2139
|
+
return out;
|
|
2140
|
+
}
|
|
2141
|
+
function polylineContour(points, closed) {
|
|
2142
|
+
const segs = [];
|
|
2143
|
+
for (let i = 1; i < points.length; i++) {
|
|
2144
|
+
segs.push(lineSegment(points[i - 1].x, points[i - 1].y, points[i].x, points[i].y));
|
|
2145
|
+
}
|
|
2146
|
+
return { segs, closed };
|
|
2147
|
+
}
|
|
2148
|
+
function countParam(value, fallback, min = 0) {
|
|
2149
|
+
const v = value === void 0 || !Number.isFinite(value) ? fallback : Math.round(value);
|
|
2150
|
+
return Math.max(min, Math.min(v, 1e3));
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
// src/paths/roughenPath.ts
|
|
2154
|
+
function hash01(seed, i, k) {
|
|
2155
|
+
let h = Math.imul((seed | 0) ^ 625341585, 2654435761) ^ Math.imul(i + 1, 2246822519) ^ Math.imul(k + 1, 3266489917);
|
|
2156
|
+
h = Math.imul(h ^ h >>> 16, 2146121005);
|
|
2157
|
+
h = Math.imul(h ^ h >>> 15, 2221713035);
|
|
2158
|
+
h ^= h >>> 16;
|
|
2159
|
+
return (h >>> 0) / 4294967296;
|
|
2160
|
+
}
|
|
2161
|
+
function roughenPath(path, opts) {
|
|
2162
|
+
const { size, seed = 0 } = opts;
|
|
2163
|
+
if (!(size > 0 && Number.isFinite(size))) return path;
|
|
2164
|
+
const pieces = countParam(opts.detail, 4) + 1;
|
|
2165
|
+
const contours = pathToCubicContours(path).map((contour, r) => polylineContour(
|
|
2166
|
+
sampleContour(contour, pieces).map(({ at: at2 }, i) => ({
|
|
2167
|
+
x: at2.x + (hash01(seed, r * 65536 + i, 0) * 2 - 1) * size,
|
|
2168
|
+
y: at2.y + (hash01(seed, r * 65536 + i, 1) * 2 - 1) * size
|
|
2169
|
+
})),
|
|
2170
|
+
contour.closed
|
|
2171
|
+
));
|
|
2172
|
+
return cubicContoursToPath(contours, path.kind === "polygon" ? path.fillRule : "nonzero");
|
|
2173
|
+
}
|
|
2174
|
+
|
|
2175
|
+
// src/paths/zigzagPath.ts
|
|
2176
|
+
function zigzagPath(path, opts) {
|
|
2177
|
+
const { size, smooth = false } = opts;
|
|
2178
|
+
if (!(size !== 0 && Number.isFinite(size))) return path;
|
|
2179
|
+
const pieces = countParam(opts.ridges, 4) + 1;
|
|
2180
|
+
const contours = pathToCubicContours(path).map((contour) => {
|
|
2181
|
+
let normal2 = { x: 0, y: 0 };
|
|
2182
|
+
const points = sampleContour(contour, pieces).map(({ at: at2, dir }, i) => {
|
|
2183
|
+
if (dir) normal2 = { x: -dir.y, y: dir.x };
|
|
2184
|
+
const side = i % 2 === 0 ? size : -size;
|
|
2185
|
+
return { x: at2.x + normal2.x * side, y: at2.y + normal2.y * side };
|
|
2186
|
+
});
|
|
2187
|
+
return smooth ? smoothThrough(points, contour.closed) : polylineContour(points, contour.closed);
|
|
2188
|
+
});
|
|
2189
|
+
return cubicContoursToPath(contours, path.kind === "polygon" ? path.fillRule : "nonzero");
|
|
2190
|
+
}
|
|
2191
|
+
function smoothThrough(points, closed) {
|
|
2192
|
+
const n = points.length;
|
|
2193
|
+
const at2 = (i) => closed ? points[(i + n) % n] : points[Math.max(0, Math.min(n - 1, i))];
|
|
2194
|
+
const reach = (i) => ({ x: (at2(i + 1).x - at2(i - 1).x) / 6, y: (at2(i + 1).y - at2(i - 1).y) / 6 });
|
|
2195
|
+
const segs = [];
|
|
2196
|
+
for (let i = 0; i < (closed ? n : n - 1); i++) {
|
|
2197
|
+
const a = at2(i);
|
|
2198
|
+
const b = at2(i + 1);
|
|
2199
|
+
const ra = reach(i);
|
|
2200
|
+
const rb = reach(i + 1);
|
|
2201
|
+
segs.push({ c: [a.x, a.y, a.x + ra.x, a.y + ra.y, b.x - rb.x, b.y - rb.y, b.x, b.y], line: false });
|
|
2202
|
+
}
|
|
2203
|
+
return { segs, closed };
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2206
|
+
// src/paths/puckerBloatPath.ts
|
|
2207
|
+
function puckerBloatPath(path, opts) {
|
|
2208
|
+
const { amount } = opts;
|
|
2209
|
+
if (!(amount !== 0 && Number.isFinite(amount))) return path;
|
|
2210
|
+
const b = boundsOfPath(path);
|
|
2211
|
+
const cx = b.x + b.width / 2;
|
|
2212
|
+
const cy = b.y + b.height / 2;
|
|
2213
|
+
const handle = (x, y) => [x + (x - cx) * amount, y + (y - cy) * amount];
|
|
2214
|
+
const anchor = (x, y) => [x - (x - cx) * amount / 2, y - (y - cy) * amount / 2];
|
|
2215
|
+
const contours = pathToCubicContours(path).map(({ segs, closed }) => ({
|
|
2216
|
+
closed,
|
|
2217
|
+
segs: segs.map(({ c }) => ({
|
|
2218
|
+
c: [...anchor(c[0], c[1]), ...handle(c[2], c[3]), ...handle(c[4], c[5]), ...anchor(c[6], c[7])],
|
|
2219
|
+
line: false
|
|
2220
|
+
}))
|
|
2221
|
+
}));
|
|
2222
|
+
return cubicContoursToPath(contours, path.kind === "polygon" ? path.fillRule : "nonzero");
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2108
2225
|
// src/paths/pathDistance.ts
|
|
2109
2226
|
function pointToRectPerimeterDist(px, py, rx, ry, rw, rh) {
|
|
2110
2227
|
const dx2 = Math.max(rx - px, px - (rx + rw), 0);
|
|
@@ -2119,116 +2236,7 @@ function pathDistanceToPoint(path, px, py) {
|
|
|
2119
2236
|
return pointToRectPerimeterDist(px, py, path.x, path.y, path.width, path.height);
|
|
2120
2237
|
}
|
|
2121
2238
|
const drawn = resolveCorners(path);
|
|
2122
|
-
return nearestOnPath(drawn.commands, drawn
|
|
2123
|
-
}
|
|
2124
|
-
|
|
2125
|
-
// src/intersect/segmentIntersections.ts
|
|
2126
|
-
var FLAT = 1e-4;
|
|
2127
|
-
var MAX_DEPTH = 48;
|
|
2128
|
-
var SAME_T = 1e-7;
|
|
2129
|
-
var MAX_HITS = 16;
|
|
2130
|
-
function boxOf(pts) {
|
|
2131
|
-
let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
|
|
2132
|
-
for (const p of pts) {
|
|
2133
|
-
if (p.x < x0) x0 = p.x;
|
|
2134
|
-
if (p.x > x1) x1 = p.x;
|
|
2135
|
-
if (p.y < y0) y0 = p.y;
|
|
2136
|
-
if (p.y > y1) y1 = p.y;
|
|
2137
|
-
}
|
|
2138
|
-
return [x0, y0, x1, y1];
|
|
2139
|
-
}
|
|
2140
|
-
function flatness(pts) {
|
|
2141
|
-
if (pts.length === 2) return 0;
|
|
2142
|
-
const a = pts[0], b = pts[pts.length - 1];
|
|
2143
|
-
const dx2 = b.x - a.x, dy2 = b.y - a.y;
|
|
2144
|
-
const len = Math.hypot(dx2, dy2);
|
|
2145
|
-
let worst2 = 0;
|
|
2146
|
-
for (let i = 1; i < pts.length - 1; i++) {
|
|
2147
|
-
const p = pts[i];
|
|
2148
|
-
const d = len === 0 ? Math.hypot(p.x - a.x, p.y - a.y) : Math.abs((p.x - a.x) * dy2 - (p.y - a.y) * dx2) / len;
|
|
2149
|
-
if (d > worst2) worst2 = d;
|
|
2150
|
-
}
|
|
2151
|
-
return worst2;
|
|
2152
|
-
}
|
|
2153
|
-
function halve(p) {
|
|
2154
|
-
let row = p.pts;
|
|
2155
|
-
const left = [row[0]];
|
|
2156
|
-
const right = [row[row.length - 1]];
|
|
2157
|
-
while (row.length > 1) {
|
|
2158
|
-
const next = [];
|
|
2159
|
-
for (let i = 0; i + 1 < row.length; i++) {
|
|
2160
|
-
next.push({ x: (row[i].x + row[i + 1].x) / 2, y: (row[i].y + row[i + 1].y) / 2 });
|
|
2161
|
-
}
|
|
2162
|
-
row = next;
|
|
2163
|
-
left.push(row[0]);
|
|
2164
|
-
right.unshift(row[row.length - 1]);
|
|
2165
|
-
}
|
|
2166
|
-
const tm = (p.t0 + p.t1) / 2;
|
|
2167
|
-
return [{ pts: left, t0: p.t0, t1: tm }, { pts: right, t0: tm, t1: p.t1 }];
|
|
2168
|
-
}
|
|
2169
|
-
function chordCross(p0, p1, q0, q1, slack) {
|
|
2170
|
-
const rx = p1.x - p0.x, ry = p1.y - p0.y;
|
|
2171
|
-
const sx = q1.x - q0.x, sy = q1.y - q0.y;
|
|
2172
|
-
const den = rx * sy - ry * sx;
|
|
2173
|
-
if (den === 0) return null;
|
|
2174
|
-
const qx = q0.x - p0.x, qy = q0.y - p0.y;
|
|
2175
|
-
const u = (qx * sy - qy * sx) / den;
|
|
2176
|
-
const v = (qx * ry - qy * rx) / den;
|
|
2177
|
-
if (u < -slack || u > 1 + slack || v < -slack || v > 1 + slack) return null;
|
|
2178
|
-
return [u, v];
|
|
2179
|
-
}
|
|
2180
|
-
function refine(a, b, ta, tb) {
|
|
2181
|
-
for (let i = 0; i < 12; i++) {
|
|
2182
|
-
const pa = evalSeg(a, ta), pb = evalSeg(b, tb);
|
|
2183
|
-
const fx = pa.x - pb.x, fy = pa.y - pb.y;
|
|
2184
|
-
if (Math.abs(fx) + Math.abs(fy) < 1e-12) break;
|
|
2185
|
-
const da = derivSeg(a, ta), db = derivSeg(b, tb);
|
|
2186
|
-
const det = -da.x * db.y + da.y * db.x;
|
|
2187
|
-
if (det === 0) break;
|
|
2188
|
-
const dta = (-fx * -db.y - -fy * -db.x) / det;
|
|
2189
|
-
const dtb = (da.x * -fy - da.y * -fx) / det;
|
|
2190
|
-
ta = Math.min(1, Math.max(0, ta + dta));
|
|
2191
|
-
tb = Math.min(1, Math.max(0, tb + dtb));
|
|
2192
|
-
}
|
|
2193
|
-
return [ta, tb];
|
|
2194
|
-
}
|
|
2195
|
-
function intersectSegments(a, b) {
|
|
2196
|
-
if (a.length === 2 && b.length === 2) {
|
|
2197
|
-
const uv = chordCross(a[0], a[1], b[0], b[1], 1e-12);
|
|
2198
|
-
if (!uv) return [];
|
|
2199
|
-
const ta = Math.min(1, Math.max(0, uv[0]));
|
|
2200
|
-
const tb = Math.min(1, Math.max(0, uv[1]));
|
|
2201
|
-
const p = evalSeg(a, ta);
|
|
2202
|
-
return [{ ta, tb, x: p.x, y: p.y }];
|
|
2203
|
-
}
|
|
2204
|
-
const out = [];
|
|
2205
|
-
const push = (ta, tb) => {
|
|
2206
|
-
[ta, tb] = refine(a, b, ta, tb);
|
|
2207
|
-
const pa = evalSeg(a, ta), pb = evalSeg(b, tb);
|
|
2208
|
-
if (Math.hypot(pa.x - pb.x, pa.y - pb.y) > 1e-6 * (1 + Math.abs(pa.x) + Math.abs(pa.y))) return;
|
|
2209
|
-
if (out.some((h) => Math.abs(h.ta - ta) < SAME_T && Math.abs(h.tb - tb) < SAME_T)) return;
|
|
2210
|
-
out.push({ ta, tb, x: pa.x, y: pa.y });
|
|
2211
|
-
};
|
|
2212
|
-
const stack = [[{ pts: a, t0: 0, t1: 1 }, { pts: b, t0: 0, t1: 1 }, 0]];
|
|
2213
|
-
while (stack.length > 0 && out.length < MAX_HITS) {
|
|
2214
|
-
const [p, q, depth] = stack.pop();
|
|
2215
|
-
const bp = boxOf(p.pts), bq = boxOf(q.pts);
|
|
2216
|
-
if (bp[0] > bq[2] + FLAT || bq[0] > bp[2] + FLAT || bp[1] > bq[3] + FLAT || bq[1] > bp[3] + FLAT) continue;
|
|
2217
|
-
const fp = flatness(p.pts), fq = flatness(q.pts);
|
|
2218
|
-
if (fp <= FLAT && fq <= FLAT || depth >= MAX_DEPTH) {
|
|
2219
|
-
const uv = chordCross(p.pts[0], p.pts[p.pts.length - 1], q.pts[0], q.pts[q.pts.length - 1], 1e-6);
|
|
2220
|
-
if (uv) push(p.t0 + uv[0] * (p.t1 - p.t0), q.t0 + uv[1] * (q.t1 - q.t0));
|
|
2221
|
-
continue;
|
|
2222
|
-
}
|
|
2223
|
-
if (fp >= fq) {
|
|
2224
|
-
const [l, r] = halve(p);
|
|
2225
|
-
stack.push([l, q, depth + 1], [r, q, depth + 1]);
|
|
2226
|
-
} else {
|
|
2227
|
-
const [l, r] = halve(q);
|
|
2228
|
-
stack.push([p, l, depth + 1], [p, r, depth + 1]);
|
|
2229
|
-
}
|
|
2230
|
-
}
|
|
2231
|
-
return out.sort((h, k) => h.ta - k.ta);
|
|
2239
|
+
return nearestOnPath(drawn.commands, worldCoords(drawn), px, py)?.dist ?? Infinity;
|
|
2232
2240
|
}
|
|
2233
2241
|
|
|
2234
2242
|
// src/intersect/pathSegments.ts
|
|
@@ -2494,6 +2502,45 @@ function quadrantPoints(segs) {
|
|
|
2494
2502
|
}
|
|
2495
2503
|
return out;
|
|
2496
2504
|
}
|
|
2505
|
+
var SPATIAL = /* @__PURE__ */ new WeakMap();
|
|
2506
|
+
function spatialOf(index) {
|
|
2507
|
+
let sp = SPATIAL.get(index);
|
|
2508
|
+
if (!sp) SPATIAL.set(index, sp = { targets: /* @__PURE__ */ new Map() });
|
|
2509
|
+
return sp;
|
|
2510
|
+
}
|
|
2511
|
+
function targetsIn(index, kind, box) {
|
|
2512
|
+
const sp = spatialOf(index);
|
|
2513
|
+
const list = index.targets(kind);
|
|
2514
|
+
let held = sp.targets.get(kind);
|
|
2515
|
+
if (held?.list !== list) {
|
|
2516
|
+
const tree = createBvh(2, list.map((t, i) => [i, [t.x, t.y, t.x, t.y]]));
|
|
2517
|
+
sp.targets.set(kind, held = { list, tree });
|
|
2518
|
+
}
|
|
2519
|
+
const out = [];
|
|
2520
|
+
held.tree.queryBox(box, (i) => {
|
|
2521
|
+
out.push(i);
|
|
2522
|
+
});
|
|
2523
|
+
return out.sort((a, b) => a - b);
|
|
2524
|
+
}
|
|
2525
|
+
function segmentsIn(index, box) {
|
|
2526
|
+
const sp = spatialOf(index);
|
|
2527
|
+
const list = index.segments;
|
|
2528
|
+
if (sp.segments?.list !== list) {
|
|
2529
|
+
const at3 = [];
|
|
2530
|
+
const entries = [];
|
|
2531
|
+
list.forEach((segs, path) => segs.forEach((seg, k) => {
|
|
2532
|
+
entries.push([at3.length, [seg.box.x0, seg.box.y0, seg.box.x1, seg.box.y1]]);
|
|
2533
|
+
at3.push([path, k]);
|
|
2534
|
+
}));
|
|
2535
|
+
sp.segments = { list, tree: createBvh(2, entries), at: at3 };
|
|
2536
|
+
}
|
|
2537
|
+
const { tree, at: at2 } = sp.segments;
|
|
2538
|
+
const found = [];
|
|
2539
|
+
tree.queryBox(box, (i) => {
|
|
2540
|
+
found.push(i);
|
|
2541
|
+
});
|
|
2542
|
+
return found.sort((a, b) => a - b).map((i) => at2[i]);
|
|
2543
|
+
}
|
|
2497
2544
|
function nearestOnSeg(s, p) {
|
|
2498
2545
|
if (s.length === 2) return nearestOnLine(p.x, p.y, s[0].x, s[0].y, s[1].x, s[1].y);
|
|
2499
2546
|
if (s.length === 3) return nearestOnQuadratic(p.x, p.y, s[0].x, s[0].y, s[1].x, s[1].y, s[2].x, s[2].y);
|
|
@@ -2515,39 +2562,39 @@ function findPathSnaps(index, probe, query) {
|
|
|
2515
2562
|
const distance = metric(x - probe.x, y - probe.y);
|
|
2516
2563
|
if (distance <= r) hits.push({ kind, x, y, distance, paths });
|
|
2517
2564
|
};
|
|
2565
|
+
const rx = sx > 0 ? r / sx : Infinity, ry = sy > 0 ? r / sy : Infinity;
|
|
2566
|
+
const box = [probe.x - rx, probe.y - ry, probe.x + rx, probe.y + ry];
|
|
2518
2567
|
for (const kind of STATIC_KINDS) {
|
|
2519
2568
|
if (!kinds.has(kind)) continue;
|
|
2520
|
-
|
|
2569
|
+
const list = index.targets(kind);
|
|
2570
|
+
for (const i of targetsIn(index, kind, box)) {
|
|
2571
|
+
const t = list[i];
|
|
2572
|
+
if (!t.paths.some(skip)) offer(kind, t.x, t.y, t.paths);
|
|
2573
|
+
}
|
|
2521
2574
|
}
|
|
2522
|
-
const rx = r / (sx || 1), ry = r / (sy || 1);
|
|
2523
|
-
const near2 = (s) => s.box.x0 - rx <= probe.x && probe.x <= s.box.x1 + rx && s.box.y0 - ry <= probe.y && probe.y <= s.box.y1 + ry;
|
|
2524
2575
|
const o = query.origin;
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2576
|
+
const tangents = o !== void 0 && (kinds.has("tangent") || kinds.has("perpendicular"));
|
|
2577
|
+
if (!tangents && !kinds.has("nearest")) return hits;
|
|
2578
|
+
const near2 = segmentsIn(index, box).filter(([path]) => !skip(path));
|
|
2579
|
+
if (o && tangents) {
|
|
2580
|
+
for (const [path, k] of near2) {
|
|
2581
|
+
const s = index.segments[path][k];
|
|
2582
|
+
const lists = [];
|
|
2583
|
+
if (kinds.has("tangent")) lists.push(["tangent", tangentTsFrom(s.pts, o)]);
|
|
2584
|
+
if (kinds.has("perpendicular")) lists.push(["perpendicular", perpendicularTsFrom(s.pts, o)]);
|
|
2585
|
+
for (const [kind, ts] of lists) {
|
|
2586
|
+
for (const t of ts) {
|
|
2587
|
+
const p = evalSeg(s.pts, t);
|
|
2588
|
+
if (metric(p.x - o.x, p.y - o.y) > r) offer(kind, p.x, p.y, [path]);
|
|
2538
2589
|
}
|
|
2539
2590
|
}
|
|
2540
|
-
}
|
|
2591
|
+
}
|
|
2541
2592
|
}
|
|
2542
2593
|
if (hits.length > 0 || !kinds.has("nearest")) return hits;
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
const n = nearestOnSeg(s.pts, probe);
|
|
2548
|
-
offer("nearest", n.x, n.y, [path]);
|
|
2549
|
-
}
|
|
2550
|
-
});
|
|
2594
|
+
for (const [path, k] of near2) {
|
|
2595
|
+
const n = nearestOnSeg(index.segments[path][k].pts, probe);
|
|
2596
|
+
offer("nearest", n.x, n.y, [path]);
|
|
2597
|
+
}
|
|
2551
2598
|
return hits;
|
|
2552
2599
|
}
|
|
2553
2600
|
|
|
@@ -2675,7 +2722,8 @@ var keyOf = (p) => `${p.x},${p.y}`;
|
|
|
2675
2722
|
function heldBy(path, set) {
|
|
2676
2723
|
const coords = new Float32Array(path.coords.length);
|
|
2677
2724
|
for (let i = 0; i < coords.length; i++) coords[i] = i >> 1;
|
|
2678
|
-
const
|
|
2725
|
+
const { origin: _indicesHaveNone, ...bare } = path;
|
|
2726
|
+
const indexed = pathToAnchors({ ...bare, coords }).anchors;
|
|
2679
2727
|
return indexed.map((sub3, s) => {
|
|
2680
2728
|
if (sub3.length === set.anchors[s].length + 1) sub3[0].inHandle = sub3.pop().inHandle;
|
|
2681
2729
|
return sub3.map((a, i) => ({ point: a.x, in: a.inHandle?.x, out: a.outHandle?.x, sub: s, idx: i }));
|
|
@@ -2694,7 +2742,7 @@ function writtenFrom(set) {
|
|
|
2694
2742
|
...a.outHandle ? { outHandle: at(k + 2) } : {}
|
|
2695
2743
|
};
|
|
2696
2744
|
}));
|
|
2697
|
-
return anchorsToPath(coded, set.closed)
|
|
2745
|
+
return worldCoords(anchorsToPath(coded, set.closed));
|
|
2698
2746
|
}
|
|
2699
2747
|
function neighbor(sub3, closed, i, step) {
|
|
2700
2748
|
for (let n = 1; n < sub3.length; n++) {
|
|
@@ -2817,6 +2865,14 @@ function standoff(anchor, normal2, px, scale3) {
|
|
|
2817
2865
|
ny /= l;
|
|
2818
2866
|
return { x: anchor.x + nx * px / scale3.x, y: anchor.y + ny * px / scale3.y, nx, ny };
|
|
2819
2867
|
}
|
|
2868
|
+
function pxExtentInFrame(px, scale3, frame) {
|
|
2869
|
+
const [a, b, c, d] = frame;
|
|
2870
|
+
const ux = a * scale3.x, uy = b * scale3.y;
|
|
2871
|
+
const vx = c * scale3.x, vy = d * scale3.y;
|
|
2872
|
+
const det = Math.abs(ux * vy - uy * vx);
|
|
2873
|
+
if (det === 0) return { x: 0, y: 0 };
|
|
2874
|
+
return { x: px * Math.hypot(vx, vy) / det, y: px * Math.hypot(ux, uy) / det };
|
|
2875
|
+
}
|
|
2820
2876
|
function screenAngleOf(rotation, scale3) {
|
|
2821
2877
|
return Math.atan2(Math.sin(rotation) * scale3.y, Math.cos(rotation) * scale3.x);
|
|
2822
2878
|
}
|
|
@@ -3427,7 +3483,7 @@ function unit(p) {
|
|
|
3427
3483
|
}
|
|
3428
3484
|
|
|
3429
3485
|
// src/paths/growRegion.ts
|
|
3430
|
-
var
|
|
3486
|
+
var MAX_DEPTH = 6;
|
|
3431
3487
|
var SAMPLES3 = [0.2, 0.35, 0.5, 0.65, 0.8];
|
|
3432
3488
|
function growRegion(path, distance, opts = {}) {
|
|
3433
3489
|
const b = new PathBuilder();
|
|
@@ -3595,7 +3651,7 @@ function offsetSeg(seg, ctx, depth) {
|
|
|
3595
3651
|
],
|
|
3596
3652
|
line: false
|
|
3597
3653
|
};
|
|
3598
|
-
if (depth >=
|
|
3654
|
+
if (depth >= MAX_DEPTH || offsetError(c, out.c, ctx) <= ctx.tol) return [out];
|
|
3599
3655
|
const [l, r] = splitSegment(seg, 0.5);
|
|
3600
3656
|
return [...offsetSeg(l, ctx, depth + 1), ...offsetSeg(r, ctx, depth + 1)];
|
|
3601
3657
|
}
|
|
@@ -3663,7 +3719,7 @@ var STEPS = 16;
|
|
|
3663
3719
|
var END2 = 1e-7;
|
|
3664
3720
|
function segmentCrossings(segs) {
|
|
3665
3721
|
const flat = segs.map((s) => flatten2(s));
|
|
3666
|
-
const boxes = flat.map(
|
|
3722
|
+
const boxes = flat.map(boxOf);
|
|
3667
3723
|
const out = [];
|
|
3668
3724
|
for (let a = 0; a < segs.length; a++) {
|
|
3669
3725
|
for (let b = a + 1; b < segs.length; b++) {
|
|
@@ -3674,7 +3730,7 @@ function segmentCrossings(segs) {
|
|
|
3674
3730
|
const hit = linesCross(pa[i], pa[i + 1], pb[j], pb[j + 1]);
|
|
3675
3731
|
if (hit === null) continue;
|
|
3676
3732
|
const guess = [(i + hit[0]) / (pa.length - 1), (j + hit[1]) / (pb.length - 1)];
|
|
3677
|
-
const [s, t] = segs[a].line && segs[b].line ? guess :
|
|
3733
|
+
const [s, t] = segs[a].line && segs[b].line ? guess : refine(segs[a].c, segs[b].c, guess);
|
|
3678
3734
|
if (atEnd(s) && atEnd(t)) continue;
|
|
3679
3735
|
if (out.some((x) => x.a === a && x.b === b && Math.abs(x.s - s) < 1e-6 && Math.abs(x.t - t) < 1e-6)) continue;
|
|
3680
3736
|
out.push({ a, b, s, t });
|
|
@@ -3691,7 +3747,7 @@ function flatten2(seg) {
|
|
|
3691
3747
|
for (let i = 0; i <= STEPS; i++) out.push(cubicEvalAt(...seg.c, i / STEPS));
|
|
3692
3748
|
return out;
|
|
3693
3749
|
}
|
|
3694
|
-
function
|
|
3750
|
+
function boxOf(pts) {
|
|
3695
3751
|
const b = [Infinity, Infinity, -Infinity, -Infinity];
|
|
3696
3752
|
for (const [x, y] of pts) {
|
|
3697
3753
|
b[0] = Math.min(b[0], x);
|
|
@@ -3710,7 +3766,7 @@ function linesCross(a, b, c, d) {
|
|
|
3710
3766
|
const w = ((c[0] - a[0]) * ry - (c[1] - a[1]) * rx) / den;
|
|
3711
3767
|
return u >= 0 && u <= 1 && w >= 0 && w <= 1 ? [u, w] : null;
|
|
3712
3768
|
}
|
|
3713
|
-
function
|
|
3769
|
+
function refine(a, b, guess) {
|
|
3714
3770
|
const gap = (s2, t2) => {
|
|
3715
3771
|
const p = cubicEvalAt(...a, s2), q = cubicEvalAt(...b, t2);
|
|
3716
3772
|
return [p[0] - q[0], p[1] - q[1]];
|
|
@@ -4890,6 +4946,9 @@ function rotatePathAround(path, cx, cy, rotation) {
|
|
|
4890
4946
|
function rotatePolygon(path, cx, cy, rotation) {
|
|
4891
4947
|
const cos = Math.cos(rotation);
|
|
4892
4948
|
const sin = Math.sin(rotation);
|
|
4949
|
+
if (path.origin) {
|
|
4950
|
+
return transformPath(path, [cos, sin, -sin, cos, cx - cx * cos + cy * sin, cy - cx * sin - cy * cos]);
|
|
4951
|
+
}
|
|
4893
4952
|
const { commands, coords } = path;
|
|
4894
4953
|
const next = new Float32Array(coords.length);
|
|
4895
4954
|
forEachSegment(commands, coords, (cmd, ci) => {
|
|
@@ -4938,6 +4997,13 @@ function poseFrameOf(pose) {
|
|
|
4938
4997
|
const about = [a, b, c, d, cx - (a * cx + c * cy), cy - (b * cx + d * cy)];
|
|
4939
4998
|
return p.rotation ? multiply(rotateAboutPoint(cx, cy, p.rotation), about) : about;
|
|
4940
4999
|
}
|
|
5000
|
+
function boxFrameOf(pose) {
|
|
5001
|
+
const p = pose;
|
|
5002
|
+
if (!p || p.x == null || p.y == null || p.width == null || p.height == null) return null;
|
|
5003
|
+
const at2 = translate(p.x, p.y);
|
|
5004
|
+
const frame = poseFrameOf(p);
|
|
5005
|
+
return frame ? multiply(frame, at2) : at2;
|
|
5006
|
+
}
|
|
4941
5007
|
function poseFrameInverseOf(pose) {
|
|
4942
5008
|
if (!poseLinearOf(pose)) {
|
|
4943
5009
|
const r = poseRotationOf(pose);
|
|
@@ -5123,7 +5189,7 @@ function smudgePath(path, opts) {
|
|
|
5123
5189
|
if (!(radius > 0) || strength === 0 || delta.x === 0 && delta.y === 0) return path;
|
|
5124
5190
|
const detail = opts.detail ?? radius / 3;
|
|
5125
5191
|
return editAnchorSet(path, (set) => {
|
|
5126
|
-
|
|
5192
|
+
refine2(set, center, radius, detail);
|
|
5127
5193
|
let touched = false;
|
|
5128
5194
|
let flat = 0;
|
|
5129
5195
|
for (const sub3 of set.anchors) {
|
|
@@ -5143,7 +5209,7 @@ function weight(p, c, radius) {
|
|
|
5143
5209
|
const u2 = ((p.x - c.x) ** 2 + (p.y - c.y) ** 2) / (radius * radius);
|
|
5144
5210
|
return u2 >= 1 ? 0 : (1 - u2) ** 2;
|
|
5145
5211
|
}
|
|
5146
|
-
function
|
|
5212
|
+
function refine2(set, c, radius, detail) {
|
|
5147
5213
|
if (!Number.isFinite(detail) || detail <= 0) return;
|
|
5148
5214
|
let added = 0;
|
|
5149
5215
|
for (let sub3 = 0; sub3 < set.anchors.length; sub3++) {
|
|
@@ -6787,6 +6853,6 @@ function typedArrayReplacer(_key, value) {
|
|
|
6787
6853
|
return tagTypedArray(value) ?? value;
|
|
6788
6854
|
}
|
|
6789
6855
|
|
|
6790
|
-
export { ANCHOR_FIELDS, CONSTRAINT_TOLERANCE, EASINGS, PATH_SNAP_KINDS, SPRING_PRESETS, TYPED_ARRAY_CONSTRUCTORS, ZOOM_FLOOR, addExtremaAnchors, anchorAt, anchorCount, anchorOriginsOf, anchorSymmetries, anchorSymmetry, anchorsBefore, anchorsInRect, anchorsUnderBrush, anchorsWhere, applyToPoint, arcShape, averageAnchorsAt, balanceFactorToward, bendAlongPath, bendSegment, bendSide, blendPaths, boxToBox, circlePath, clampRectWithin, closestOpenEnds, composePath, conflictingConstraints, constrainPathEdit, constrainPathsEdit, constraintAnchors, constraintApplies, constraintFits, convertSegments, cornerAnchors, createPathSnapIndex, cubicBezierEasing, cubicContoursToPath, decomposePath, deleteAnchorsAt, directionMarks, easeIn, easeInBack, easeInBounce, easeInCirc, easeInCubic, easeInElastic, easeInExpo, easeInOut, easeInOutBack, easeInOutBounce, easeInOutCirc, easeInOutCubic, easeInOutElastic, easeInOutExpo, easeInOutQuad, easeInOutQuart, easeInOutQuint, easeInOutSine, easeInQuad, easeInQuart, easeInQuint, easeInSine, easeOut, easeOutBack, easeOutBounce, easeOutCirc, easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, editAnchorSet, editAnchorSetTracked, ellipseShape, equalizeSegmentHandles, everyNthAnchor, extendToMeet, findPathSnap, findPathSnaps, fitAffine, fitCubicThroughDeletion, flatAnchorIndex, flatIndexesAfterReverse, growAnchorSelection, growRegion, handleAlongItsAngle, handleAtItsLength, handleBalances, harmonizeAnchors, hasOpenSubpath, identity, insertAnchorOnSegment,
|
|
6856
|
+
export { ANCHOR_FIELDS, CONSTRAINT_TOLERANCE, EASINGS, PATH_SNAP_KINDS, SPRING_PRESETS, TYPED_ARRAY_CONSTRUCTORS, ZOOM_FLOOR, addExtremaAnchors, anchorAt, anchorCount, anchorOriginsOf, anchorSymmetries, anchorSymmetry, anchorsBefore, anchorsInRect, anchorsUnderBrush, anchorsWhere, applyToPoint, arcShape, averageAnchorsAt, balanceFactorToward, bendAlongPath, bendSegment, bendSide, blendPaths, boxFrameOf, boxToBox, circlePath, clampRectWithin, closestOpenEnds, composePath, conflictingConstraints, constrainPathEdit, constrainPathsEdit, constraintAnchors, constraintApplies, constraintFits, convertSegments, cornerAnchors, createPathSnapIndex, cubicBezierEasing, cubicContoursToPath, decomposePath, deleteAnchorsAt, directionMarks, easeIn, easeInBack, easeInBounce, easeInCirc, easeInCubic, easeInElastic, easeInExpo, easeInOut, easeInOutBack, easeInOutBounce, easeInOutCirc, easeInOutCubic, easeInOutElastic, easeInOutExpo, easeInOutQuad, easeInOutQuart, easeInOutQuint, easeInOutSine, easeInQuad, easeInQuart, easeInQuint, easeInSine, easeOut, easeOutBack, easeOutBounce, easeOutCirc, easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, editAnchorSet, editAnchorSetTracked, ellipseShape, equalizeSegmentHandles, everyNthAnchor, extendToMeet, findPathSnap, findPathSnaps, fitAffine, fitCubicThroughDeletion, flatAnchorIndex, flatIndexesAfterReverse, growAnchorSelection, growRegion, handleAlongItsAngle, handleAtItsLength, handleBalances, harmonizeAnchors, hasOpenSubpath, identity, insertAnchorOnSegment, invert, invertAnchorSelection, isSegmentStraight, joinAnchorsAt, joinSubpathEnds, lengthToward, lengthenOpenEnd, lengthenPathEnd, lineShape, linear, locateAnchor, makeHandlesSymmetric, mapConstraintAnchors, mat3, meanScale, measureAnchorPath, measurePath, mergeRegion, moveHandleSymmetric, moveHandleTo, multiply, nearestPathAnchor, normalizeZoom, offsetCornerTraces, openEndAt, openEndRay, openPathEnds, openSubpathAt, pathAnchorPoints, pathAwayFromAnchors, pathContainsPoint, pathContainsPolygon, pathContainsRect, pathCrossings, pathDistanceToPoint, pathEndAnchorIndex, pathEndFrame, pathFromD, pathInPoseFrame, pathInWorld, pathIntersectsPolygon, pathIntersectsRect, pathSegments, pathShape, pathSignedArea, pathThroughPoseFrame, pathToCubicContours, pathToD, placeAlongRun, placeRect, pointAlongPath, pointInPath, polygonContainsPath, polygonIntersectsPath, portControls2 as portControls, portCurvePoints2 as portCurvePoints, poseFrameInverseOf, poseFrameOf, poseLinearOf, poseRotationOf, prepareBlend, puckerBloatPath, pxExtent, pxExtentInFrame, readAnchorFields, rectMarkerPath, remapAnchorValues, remapConstraints, remapPointValues, repeatAlongPath, resamplePath, resolveEasing, retractHandles, reverseAnchors, reversePath, reverseSubpaths, reviveTypedArrays, rotate, rotateAboutPoint, rotatePathAround, roughenPath, roundRectPath, runLength, runPlaces, runStationAt, scale, scaleDelta, scalePathToBounds, scaleSegmentHandles, screenAngleOf, segmentAt2 as segmentAt, segmentBetween, segmentExtremaTs, segmentsBetweenAnchors, setSubpathStart, shiftTrack, shrinkAnchorSelection, simplifyAnchorsAt, simplifyPath, simplifySpan, simplifySubpath, smoothAnchors, smudgePath, softFalloff, softSelectionBand, softSelectionWeights, solveConstraints, solvePathConstraints, splitByClosure, splitSubpaths, squarePath, standoff, stationsAlongPath, strokeHitTest, subpathEndAt, subpathsOfAnchors, tagTypedArray, tagTypedArrays, trackRun, trackShapeD, trackSlice, transformCoords, transformPath, translate, translateAnchorBy, translateAnchorsSymmetric, translatePath, trimPathAt, typedArrayReplacer, unionBoundsPath, unsatisfiedConstraints, untagTypedArray, viewToMat3, withAnchorPoints, withinPxBox, withinPxRadius, worldEditToStorage, writeAnchorField, zigzagPath };
|
|
6791
6857
|
//# sourceMappingURL=index.js.map
|
|
6792
6858
|
//# sourceMappingURL=index.js.map
|