@weasel-js/geom 1.9.3 → 1.10.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/dist/3d/index.js +1 -1
- package/dist/booleans/index.d.ts +51 -29
- package/dist/booleans/index.js +562 -482
- package/dist/booleans/index.js.map +1 -1
- package/dist/{chunk-7ROQRYOA.js → chunk-755Y4YZS.js} +6 -3
- package/dist/chunk-755Y4YZS.js.map +1 -0
- package/dist/{chunk-6T5I3PR5.js → chunk-MDT7F32A.js} +16 -5
- package/dist/chunk-MDT7F32A.js.map +1 -0
- package/dist/{chunk-HEZTRG2M.js → chunk-OXH3NOXC.js} +10 -3
- package/dist/chunk-OXH3NOXC.js.map +1 -0
- package/dist/{chunk-RQYCDPU5.js → chunk-WQMYOCFB.js} +27 -18
- package/dist/chunk-WQMYOCFB.js.map +1 -0
- package/dist/{chunk-HPVINMOM.js → chunk-XS6ERH3X.js} +2 -2
- package/dist/chunk-XS6ERH3X.js.map +1 -0
- package/dist/cubicMath-CFXbq6vp.d.ts +116 -0
- package/dist/curves/index.d.ts +1 -1
- package/dist/curves/index.js +18 -71
- package/dist/curves/index.js.map +1 -1
- package/dist/index.d.ts +612 -116
- package/dist/index.js +904 -112
- package/dist/index.js.map +1 -1
- package/dist/{path-D0CoudGM.d.ts → path-Bf9KeVxC.d.ts} +10 -11
- package/dist/tessellate/index.d.ts +8 -12
- package/dist/tessellate/index.js +36 -10
- package/dist/tessellate/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-6T5I3PR5.js.map +0 -1
- package/dist/chunk-7ROQRYOA.js.map +0 -1
- package/dist/chunk-HEZTRG2M.js.map +0 -1
- package/dist/chunk-HPVINMOM.js.map +0 -1
- package/dist/chunk-RQYCDPU5.js.map +0 -1
- package/dist/cubicMath-CpCvuEl8.d.ts +0 -37
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/box.ts","../src/tessellate/polyline.ts"],"names":[],"mappings":"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","file":"chunk-MDT7F32A.js","sourcesContent":["/** Axis-aligned box as [minX, minY, maxX, maxY]. */\nexport type Box = readonly [number, number, number, number];\n\n/** An axis-aligned rectangle in object form. `Box` is the tuple form; this is\n * the one that survives being read by a human. */\nexport interface Rect { x: number; y: number; width: number; height: number }\n\n/** Tight bounds of an interleaved coord stream, or null if empty. */\nexport function boundsOfCoords(coords: ArrayLike<number>): Box | null {\n if (coords.length < 2) return null;\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (let i = 0; i + 1 < coords.length; i += 2) {\n const x = coords[i], y = coords[i + 1];\n if (x < minX) minX = x;\n if (y < minY) minY = y;\n if (x > maxX) maxX = x;\n if (y > maxY) maxY = y;\n }\n return [minX, minY, maxX, maxY];\n}\n\n/** Smallest box containing both inputs. */\nexport function unionBox(a: Box, b: Box): Box {\n return [\n Math.min(a[0], b[0]),\n Math.min(a[1], b[1]),\n Math.max(a[2], b[2]),\n Math.max(a[3], b[3]),\n ];\n}\n\n/** Inclusive point-in-box test. */\nexport function boxContainsPoint(b: Box, x: number, y: number): boolean {\n return x >= b[0] && x <= b[2] && y >= b[1] && y <= b[3];\n}\n\n/** Whether `outer` wholly holds `inner`, edges inclusive. Two boxes that merely\n * overlap answer false. */\nexport function boxContainsBox(outer: Box, inner: Box): boolean {\n return inner[0] >= outer[0] && inner[1] >= outer[1] && inner[2] <= outer[2] && inner[3] <= outer[3];\n}\n\n/** Interleaved corner ring for a rect at (x,y,w,h), wound clockwise from the\n * origin corner. The closing edge is implicit — the same unclosed shape\n * `pointInPolygon` takes, and what a repeated first vertex would leave as a\n * zero-length segment for anything that strokes it. */\nexport function rectToContour(x: number, y: number, w: number, h: number): Float64Array {\n return Float64Array.of(x, y, x + w, y, x + w, y + h, x, y + h);\n}\n","import { forEachSegment, PATH_M, PATH_L, PATH_Z, PATH_C, PATH_Q } from '../commands';\nimport { rectToContour } from '../box';\nimport { DEFAULT_FLATTEN_TOLERANCE, flattenCubicWithArcLen, flattenQuadraticWithArcLen } from '../flatten';\nimport type { Path, PolygonPath, RectPath } from '../path';\n\n/** One contour of a path, flattened to straight segments. */\nexport interface Polyline {\n /** Interleaved x,y vertices (length = 2 × point count). */\n points: number[];\n /** Whether the contour was closed (ends with Z, or is a RectPath). */\n closed: boolean;\n /** For each point, the previous anchor index. Anchor-aligned points set A === B. */\n anchorA?: Uint32Array;\n /** For each point, the next anchor index. */\n anchorB?: Uint32Array;\n /** For each point, the arc-length fraction along (A, B). 0 at anchor A; for anchor-aligned, set to 0. */\n anchorT?: Float32Array;\n /** Per-point stroke width, populated by the tessellator when the Stroke\n * carries `vertexWidths`. Undefined means uniform `Stroke.width`. */\n widths?: Float32Array;\n}\n\n/** Options for `extractPolylines`. */\nexport interface ExtractOptions {\n flattenTolerance?: number;\n}\n\n/** Flatten each contour of a path to a straight-segment polyline, carrying the\n * anchor parameterization per point. A rect yields one closed contour. */\nexport function extractPolylines(path: Path, opts: ExtractOptions = {}): Polyline[] {\n if (path.kind === 'rect') return [extractRect(path)];\n return extractPolygon(path, opts);\n}\n\nfunction extractRect(p: RectPath): Polyline {\n const { x, y, width: w, height: h } = p;\n return {\n points: Array.from(rectToContour(x, y, w, h)),\n closed: true,\n anchorA: new Uint32Array([0, 1, 2, 3]),\n anchorB: new Uint32Array([0, 1, 2, 3]),\n anchorT: new Float32Array([0, 0, 0, 0]),\n };\n}\n\nfunction extractPolygon(p: PolygonPath, opts: ExtractOptions): Polyline[] {\n const tolerance = opts.flattenTolerance ?? DEFAULT_FLATTEN_TOLERANCE;\n const { commands, coords } = p;\n const out: Polyline[] = [];\n // Anchors are numbered globally (across all contours) in command-stream order.\n let anchorCounter = 0;\n\n // Builders for the current polyline.\n let pts: number[] | null = null;\n let aA: number[] | null = null;\n let aB: number[] | null = null;\n let aT: number[] | null = null;\n let current: Polyline | null = null;\n\n let prevAnchor = -1;\n // The anchor a subpath opened by a bare drawing command starts from.\n let startAnchor = 0;\n\n const beginContour = (): Polyline => {\n pts = [];\n aA = [];\n aB = [];\n aT = [];\n const next: Polyline = { points: pts, closed: false };\n out.push(next);\n return next;\n };\n\n /**\n * A closed contour's last point repeating its first leaves a zero-length\n * closing segment, which the stroker discards along with the wrap-around\n * join it should have carried, notching the ribbon at the contour's start.\n * Every font outline serialized by opentype.js is written this way. Exact\n * equality is the right test: the duplicate is a re-emission of the same\n * number, and a near-miss is a genuine (if tiny) segment the author asked for.\n */\n const dropDuplicateClosingPoint = (): void => {\n if (!pts || !aA || !aB || !aT) return;\n const n = pts.length / 2;\n if (n < 2) return;\n if (pts[0] !== pts[(n - 1) * 2] || pts[1] !== pts[(n - 1) * 2 + 1]) return;\n pts.length -= 2;\n aA.length -= 1;\n aB.length -= 1;\n aT.length -= 1;\n };\n\n const commit = (target: Polyline): void => {\n if (!pts || !aA || !aB || !aT) return;\n target.anchorA = new Uint32Array(aA);\n target.anchorB = new Uint32Array(aB);\n target.anchorT = new Float32Array(aT);\n };\n\n // Fill anchorA/B/T for each point a curve just appended: interior points\n // interpolate (prevAnchor → target), and the final point is pinned to the\n // target so the draw-time lerp returns anchor B's color exactly.\n const pushCurveAnchors = (segStart: number, arcAccum: number[], total: number, target: number): void => {\n for (let k = 0; k < arcAccum.length; k++) {\n aA!.push(prevAnchor);\n aB!.push(target);\n aT!.push(total > 0 ? arcAccum[k] / total : 0);\n }\n const lastIdx = (segStart + arcAccum.length) - 1;\n aA![lastIdx] = target;\n aB![lastIdx] = target;\n aT![lastIdx] = 0;\n };\n\n forEachSegment(commands, coords, (cmd, coordIdx, prevX, prevY, _i, opensSubpath) => {\n if (opensSubpath) {\n if (current) commit(current);\n current = beginContour();\n pts!.push(prevX, prevY);\n aA!.push(startAnchor);\n aB!.push(startAnchor);\n aT!.push(0);\n prevAnchor = startAnchor;\n }\n switch (cmd) {\n case PATH_M:\n case PATH_L: {\n if (cmd === PATH_M) {\n if (current) commit(current);\n current = beginContour();\n startAnchor = anchorCounter;\n }\n pts!.push(coords[coordIdx], coords[coordIdx + 1]);\n aA!.push(anchorCounter);\n aB!.push(anchorCounter);\n aT!.push(0);\n prevAnchor = anchorCounter;\n anchorCounter++;\n break;\n }\n case PATH_Q: {\n const target = anchorCounter;\n const segStart = pts!.length / 2;\n const arcAccum: number[] = [];\n const total = flattenQuadraticWithArcLen(\n prevX, prevY,\n coords[coordIdx], coords[coordIdx + 1],\n coords[coordIdx + 2], coords[coordIdx + 3],\n tolerance, pts!, arcAccum,\n );\n pushCurveAnchors(segStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_C: {\n const target = anchorCounter;\n const segStart = pts!.length / 2;\n const arcAccum: number[] = [];\n const total = flattenCubicWithArcLen(\n prevX, prevY,\n coords[coordIdx], coords[coordIdx + 1],\n coords[coordIdx + 2], coords[coordIdx + 3],\n coords[coordIdx + 4], coords[coordIdx + 5],\n tolerance, pts!, arcAccum,\n );\n pushCurveAnchors(segStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_Z: {\n if (current) {\n current.closed = true;\n dropDuplicateClosingPoint();\n }\n break;\n }\n default:\n throw new Error(`extractPolylines: unknown command code ${cmd}`);\n }\n });\n\n if (current) commit(current);\n return out;\n}\n"]}
|
|
@@ -30,9 +30,16 @@ function forEachSegment(commands, coords, visit) {
|
|
|
30
30
|
let ci = 0;
|
|
31
31
|
let px = 0, py = 0;
|
|
32
32
|
let startX = 0, startY = 0;
|
|
33
|
+
let open = false;
|
|
33
34
|
for (let i = 0; i < commands.length; i++) {
|
|
34
35
|
const cmd = commands[i];
|
|
35
|
-
|
|
36
|
+
const opens = !open && cmd !== PATH_M && cmd !== PATH_Z;
|
|
37
|
+
if (opens) {
|
|
38
|
+
startX = px;
|
|
39
|
+
startY = py;
|
|
40
|
+
}
|
|
41
|
+
open = cmd !== PATH_Z;
|
|
42
|
+
if (visit(cmd, ci, px, py, i, opens) === false) return;
|
|
36
43
|
const len = pathCommandCoordCount(cmd);
|
|
37
44
|
if (len === void 0) throw new Error(`forEachSegment: unknown command code ${cmd}`);
|
|
38
45
|
if (len > 0) {
|
|
@@ -51,5 +58,5 @@ function forEachSegment(commands, coords, visit) {
|
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
export { PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_Z, forEachSegment, pathCommandCoordCount };
|
|
54
|
-
//# sourceMappingURL=chunk-
|
|
55
|
-
//# sourceMappingURL=chunk-
|
|
61
|
+
//# sourceMappingURL=chunk-OXH3NOXC.js.map
|
|
62
|
+
//# sourceMappingURL=chunk-OXH3NOXC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands.ts"],"names":[],"mappings":";AAWO,IAAM,aAAA,GAAgB;AAAA;AAAA,EAE3B,CAAA,EAAG,EAAE,IAAA,EAAM,CAAA,EAAG,QAAQ,CAAA,EAAE;AAAA;AAAA,EAExB,CAAA,EAAG,EAAE,IAAA,EAAM,CAAA,EAAG,QAAQ,CAAA,EAAE;AAAA;AAAA,EAExB,CAAA,EAAG,EAAE,IAAA,EAAM,CAAA,EAAG,QAAQ,CAAA,EAAE;AAAA;AAAA,EAExB,CAAA,EAAG,EAAE,IAAA,EAAM,CAAA,EAAG,QAAQ,CAAA,EAAE;AAAA;AAAA;AAAA,EAGxB,CAAA,EAAG,EAAE,IAAA,EAAM,CAAA,EAAG,QAAQ,CAAA;AACxB;AAQO,IAAM,MAAA,GAAS,cAAc,CAAA,CAAE;AAE/B,IAAM,MAAA,GAAS,cAAc,CAAA,CAAE;AAE/B,IAAM,MAAA,GAAS,cAAc,CAAA,CAAE;AAE/B,IAAM,MAAA,GAAS,cAAc,CAAA,CAAE;AAE/B,IAAM,MAAA,GAAS,cAAc,CAAA,CAAE;AAG/B,IAAM,mBAAsC,eAAA;AAEnD,SAAS,eAAA,GAA4B;AACnC,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,KAAA,MAAW,EAAE,IAAA,EAAM,MAAA,EAAO,IAAK,MAAA,CAAO,OAAO,aAAa,CAAA,EAAG,OAAA,CAAQ,IAAI,CAAA,GAAI,MAAA;AAC7E,EAAA,OAAO,OAAA;AACT;AAGO,SAAS,sBAAsB,GAAA,EAAqB;AACzD,EAAA,OAAO,iBAAiB,GAAG,CAAA;AAC7B;AAcO,SAAS,cAAA,CACd,QAAA,EACA,MAAA,EACA,KAAA,EAQM;AACN,EAAA,IAAI,EAAA,GAAK,CAAA;AACT,EAAA,IAAI,EAAA,GAAK,GAAG,EAAA,GAAK,CAAA;AACjB,EAAA,IAAI,MAAA,GAAS,GAAG,MAAA,GAAS,CAAA;AACzB,EAAA,IAAI,IAAA,GAAO,KAAA;AACX,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,QAAQ,CAAA,EAAA,EAAK;AACxC,IAAA,MAAM,GAAA,GAAM,SAAS,CAAC,CAAA;AACtB,IAAA,MAAM,KAAA,GAAQ,CAAC,IAAA,IAAQ,GAAA,KAAQ,UAAU,GAAA,KAAQ,MAAA;AACjD,IAAA,IAAI,KAAA,EAAO;AAAE,MAAA,MAAA,GAAS,EAAA;AAAI,MAAA,MAAA,GAAS,EAAA;AAAA,IAAI;AACvC,IAAA,IAAA,GAAO,GAAA,KAAQ,MAAA;AACf,IAAA,IAAI,KAAA,CAAM,KAAK,EAAA,EAAI,EAAA,EAAI,IAAI,CAAA,EAAG,KAAK,MAAM,KAAA,EAAO;AAChD,IAAA,MAAM,GAAA,GAAM,sBAAsB,GAAG,CAAA;AACrC,IAAA,IAAI,QAAQ,MAAA,EAAW,MAAM,IAAI,KAAA,CAAM,CAAA,qCAAA,EAAwC,GAAG,CAAA,CAAE,CAAA;AACpF,IAAA,IAAI,MAAM,CAAA,EAAG;AACX,MAAA,EAAA,GAAK,MAAA,CAAO,EAAA,GAAK,GAAA,GAAM,CAAC,CAAA;AACxB,MAAA,EAAA,GAAK,MAAA,CAAO,EAAA,GAAK,GAAA,GAAM,CAAC,CAAA;AACxB,MAAA,EAAA,IAAM,GAAA;AACN,MAAA,IAAI,QAAQ,MAAA,EAAQ;AAAE,QAAA,MAAA,GAAS,EAAA;AAAI,QAAA,MAAA,GAAS,EAAA;AAAA,MAAI;AAAA,IAClD,CAAA,MAAA,IAAW,QAAQ,MAAA,EAAQ;AACzB,MAAA,EAAA,GAAK,MAAA;AAAQ,MAAA,EAAA,GAAK,MAAA;AAAA,IACpB;AAAA,EACF;AACF","file":"chunk-OXH3NOXC.js","sourcesContent":["/**\n * SVG-style command-stream encoding — the kit's single declaration of the path\n * opcodes.\n *\n * The codes index a `Uint8Array` command stream whose coords live in a\n * parallel float array, so a code declared anywhere but `PATH_COMMANDS` makes\n * every walker that doesn't know it misread the coord stream from that command\n * on — silently, for every path.\n */\n\n/** Opcode table: command code and the float coords it consumes. */\nexport const PATH_COMMANDS = {\n /** moveTo — opens a new subpath. */\n M: { code: 0, coords: 2 },\n /** Straight segment from the pen to the next coord pair. */\n L: { code: 1, coords: 2 },\n /** Cubic bezier: two control points then the endpoint. */\n C: { code: 2, coords: 6 },\n /** Quadratic bezier: one control point then the endpoint. */\n Q: { code: 3, coords: 4 },\n /** Close the current subpath back to its start. Consumes no coords and\n * leaves the pen where it is. */\n Z: { code: 4, coords: 0 },\n} as const;\n\n/** Mnemonic of a declared command (`'M' | 'L' | …`). */\nexport type PathCommandName = keyof typeof PATH_COMMANDS;\n/** Numeric code of a declared command. */\nexport type PathCommandCode = (typeof PATH_COMMANDS)[PathCommandName]['code'];\n\n/** Command code of `M` (moveTo). */\nexport const PATH_M = PATH_COMMANDS.M.code;\n/** Command code of `L` (lineTo). */\nexport const PATH_L = PATH_COMMANDS.L.code;\n/** Command code of `C` (cubic bezier). */\nexport const PATH_C = PATH_COMMANDS.C.code;\n/** Command code of `Q` (quadratic bezier). */\nexport const PATH_Q = PATH_COMMANDS.Q.code;\n/** Command code of `Z` (close subpath). */\nexport const PATH_Z = PATH_COMMANDS.Z.code;\n\n/** Float coords consumed by each command, indexed by command code. */\nexport const PATH_CMD_LENGTHS: readonly number[] = buildCmdLengths();\n\nfunction buildCmdLengths(): number[] {\n const lengths: number[] = [];\n for (const { code, coords } of Object.values(PATH_COMMANDS)) lengths[code] = coords;\n return lengths;\n}\n\n/** Float coords consumed by the command with this code. */\nexport function pathCommandCoordCount(cmd: number): number {\n return PATH_CMD_LENGTHS[cmd];\n}\n\n/**\n * Visit each command with its coord offset and the pen position BEFORE the\n * command consumes its coords (the segment start). The callback stops the\n * walk by returning `false`. `Z` returns the pen to the subpath's opening `M`.\n *\n * A command following a `Z` without an intervening `M` opens a new subpath at\n * the pen, as does a drawing command no `M` precedes at all. The visitor is\n * told with `opensSubpath`, and has to start its contour at `(penX, penY)`\n * then: there is no `M` to do it.\n *\n * A code `PATH_COMMANDS` does not declare throws once the visitor has seen it.\n */\nexport function forEachSegment(\n commands: ArrayLike<number>,\n coords: ArrayLike<number>,\n visit: (\n cmd: number,\n coordIndex: number,\n penX: number,\n penY: number,\n commandIndex: number,\n opensSubpath: boolean,\n ) => void | boolean,\n): void {\n let ci = 0;\n let px = 0, py = 0;\n let startX = 0, startY = 0;\n let open = false;\n for (let i = 0; i < commands.length; i++) {\n const cmd = commands[i];\n const opens = !open && cmd !== PATH_M && cmd !== PATH_Z;\n if (opens) { startX = px; startY = py; }\n open = cmd !== PATH_Z;\n if (visit(cmd, ci, px, py, i, opens) === false) return;\n const len = pathCommandCoordCount(cmd);\n if (len === undefined) throw new Error(`forEachSegment: unknown command code ${cmd}`);\n if (len > 0) {\n px = coords[ci + len - 2];\n py = coords[ci + len - 1];\n ci += len;\n if (cmd === PATH_M) { startX = px; startY = py; }\n } else if (cmd === PATH_Z) {\n px = startX; py = startY;\n }\n }\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { sign, len2, dot } from './chunk-
|
|
1
|
+
import { sign, len2, dot } from './chunk-755Y4YZS.js';
|
|
2
2
|
|
|
3
3
|
// src/flatten.ts
|
|
4
4
|
var DEFAULT_FLATTEN_TOLERANCE = 0.5;
|
|
@@ -13,17 +13,14 @@ function finite6(a, b, c, d, e, f) {
|
|
|
13
13
|
function finite8(a, b, c, d, e, f, g, h) {
|
|
14
14
|
return finite6(a, b, c, d, e, f) && Number.isFinite(g) && Number.isFinite(h);
|
|
15
15
|
}
|
|
16
|
-
function
|
|
16
|
+
function distPointToSegment(px, py, ax, ay, bx, by) {
|
|
17
17
|
const dx = bx - ax;
|
|
18
18
|
const dy = by - ay;
|
|
19
19
|
const len22 = dx * dx + dy * dy;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
const cross = (px - ax) * dy - (py - ay) * dx;
|
|
26
|
-
return Math.abs(cross) / Math.sqrt(len22);
|
|
20
|
+
const along = len22 === 0 ? 0 : ((px - ax) * dx + (py - ay) * dy) / len22;
|
|
21
|
+
if (along <= 0) return Math.hypot(px - ax, py - ay);
|
|
22
|
+
if (along >= 1) return Math.hypot(px - bx, py - by);
|
|
23
|
+
return Math.abs((px - ax) * dy - (py - ay) * dx) / Math.sqrt(len22);
|
|
27
24
|
}
|
|
28
25
|
function flattenCubic(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out) {
|
|
29
26
|
if (!finite8(x0, y0, x1, y1, x2, y2, x3, y3)) {
|
|
@@ -33,8 +30,8 @@ function flattenCubic(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out) {
|
|
|
33
30
|
flattenCubicRec(x0, y0, x1, y1, x2, y2, x3, y3, usableTolerance(tolerance), out, 0);
|
|
34
31
|
}
|
|
35
32
|
function flattenCubicRec(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out, depth) {
|
|
36
|
-
const d1 =
|
|
37
|
-
const d2 =
|
|
33
|
+
const d1 = distPointToSegment(x1, y1, x0, y0, x3, y3);
|
|
34
|
+
const d2 = distPointToSegment(x2, y2, x0, y0, x3, y3);
|
|
38
35
|
if (Math.max(d1, d2) <= tolerance || depth >= MAX_FLATTEN_DEPTH) {
|
|
39
36
|
out.push(x3, y3);
|
|
40
37
|
return;
|
|
@@ -56,7 +53,7 @@ function flattenQuadratic(x0, y0, x1, y1, x2, y2, tolerance, out) {
|
|
|
56
53
|
flattenQuadraticRec(x0, y0, x1, y1, x2, y2, usableTolerance(tolerance), out, 0);
|
|
57
54
|
}
|
|
58
55
|
function flattenQuadraticRec(x0, y0, x1, y1, x2, y2, tolerance, out, depth) {
|
|
59
|
-
const d =
|
|
56
|
+
const d = distPointToSegment(x1, y1, x0, y0, x2, y2);
|
|
60
57
|
if (d <= tolerance || depth >= MAX_FLATTEN_DEPTH) {
|
|
61
58
|
out.push(x2, y2);
|
|
62
59
|
return;
|
|
@@ -76,8 +73,8 @@ function flattenCubicWithArcLen(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out,
|
|
|
76
73
|
return flattenCubicArcRec(x0, y0, x1, y1, x2, y2, x3, y3, usableTolerance(tolerance), out, arcOut, 0, 0);
|
|
77
74
|
}
|
|
78
75
|
function flattenCubicArcRec(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out, arcOut, accum, depth) {
|
|
79
|
-
const d1 =
|
|
80
|
-
const d2 =
|
|
76
|
+
const d1 = distPointToSegment(x1, y1, x0, y0, x3, y3);
|
|
77
|
+
const d2 = distPointToSegment(x2, y2, x0, y0, x3, y3);
|
|
81
78
|
if (Math.max(d1, d2) <= tolerance || depth >= MAX_FLATTEN_DEPTH) {
|
|
82
79
|
const lastX = out.length >= 2 ? out[out.length - 2] : x0;
|
|
83
80
|
const lastY = out.length >= 2 ? out[out.length - 1] : y0;
|
|
@@ -106,7 +103,7 @@ function flattenQuadraticWithArcLen(x0, y0, x1, y1, x2, y2, tolerance, out, arcO
|
|
|
106
103
|
return flattenQuadraticArcRec(x0, y0, x1, y1, x2, y2, usableTolerance(tolerance), out, arcOut, 0, 0);
|
|
107
104
|
}
|
|
108
105
|
function flattenQuadraticArcRec(x0, y0, x1, y1, x2, y2, tolerance, out, arcOut, accum, depth) {
|
|
109
|
-
const d =
|
|
106
|
+
const d = distPointToSegment(x1, y1, x0, y0, x2, y2);
|
|
110
107
|
if (d <= tolerance || depth >= MAX_FLATTEN_DEPTH) {
|
|
111
108
|
const lastX = out.length >= 2 ? out[out.length - 2] : x0;
|
|
112
109
|
const lastY = out.length >= 2 ? out[out.length - 1] : y0;
|
|
@@ -153,6 +150,18 @@ function pointSegmentDist2(px, py, ax, ay, bx, by) {
|
|
|
153
150
|
return len2(dx, dy);
|
|
154
151
|
}
|
|
155
152
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
153
|
+
// src/openFill.ts
|
|
154
|
+
var fallback = "close";
|
|
155
|
+
function setDefaultOpenFill(rule) {
|
|
156
|
+
fallback = rule;
|
|
157
|
+
}
|
|
158
|
+
function defaultOpenFill() {
|
|
159
|
+
return fallback;
|
|
160
|
+
}
|
|
161
|
+
function fillsOpenSubpaths(path) {
|
|
162
|
+
return (path.openFill ?? fallback) === "close";
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export { DEFAULT_FLATTEN_TOLERANCE, defaultOpenFill, fillsOpenSubpaths, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, pointInPolygon, pointSegmentDist2, segmentsCross, setDefaultOpenFill };
|
|
166
|
+
//# sourceMappingURL=chunk-WQMYOCFB.js.map
|
|
167
|
+
//# sourceMappingURL=chunk-WQMYOCFB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/flatten.ts","../src/polyline.ts","../src/openFill.ts"],"names":["len2"],"mappings":"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","file":"chunk-WQMYOCFB.js","sourcesContent":["/**\n * Bezier flattening — subdivide cubic and quadratic segments into polyline\n * approximations within a flatness tolerance.\n *\n * The flatness metric is the maximum distance from any control point to the\n * chord between endpoints.\n *\n * Tolerance is in world units. 0.5 is a sensible default for screen-rate\n * rendering at 1× zoom; consumers that zoom in heavily should pass a\n * tighter tolerance.\n */\n\nexport const DEFAULT_FLATTEN_TOLERANCE = 0.5;\n\n/** Floor for a non-positive or NaN tolerance. Without it the flatness test can\n * never be satisfied and the subdivision recurses until the stack blows. */\nconst MIN_FLATTEN_TOLERANCE = 1e-6;\n\n/** Subdivision ceiling. The tolerance floor bounds the common runaway; this\n * bounds the other one, coordinates large enough that reaching 1e-6 takes\n * hundreds of levels. Error falls roughly 4x per level, so 16 is far beyond\n * any tolerance a caller can mean. */\nconst MAX_FLATTEN_DEPTH = 16;\n\nfunction usableTolerance(tolerance: number): number {\n return tolerance > 0 ? tolerance : MIN_FLATTEN_TOLERANCE;\n}\n\nfunction finite6(a: number, b: number, c: number, d: number, e: number, f: number): boolean {\n return Number.isFinite(a) && Number.isFinite(b) && Number.isFinite(c)\n && Number.isFinite(d) && Number.isFinite(e) && Number.isFinite(f);\n}\n\nfunction finite8(\n a: number, b: number, c: number, d: number,\n e: number, f: number, g: number, h: number,\n): boolean {\n return finite6(a, b, c, d, e, f) && Number.isFinite(g) && Number.isFinite(h);\n}\n\n/**\n * Distance from point P to segment AB. To the segment, not the line through\n * it: a control point on that line but past an end still pulls the curve out\n * beyond the chord, and measures zero against the line.\n */\nfunction distPointToSegment(px: number, py: number, ax: number, ay: number, bx: number, by: number): number {\n const dx = bx - ax;\n const dy = by - ay;\n const len2 = dx * dx + dy * dy;\n const along = len2 === 0 ? 0 : ((px - ax) * dx + (py - ay) * dy) / len2;\n if (along <= 0) return Math.hypot(px - ax, py - ay);\n if (along >= 1) return Math.hypot(px - bx, py - by);\n return Math.abs((px - ax) * dy - (py - ay) * dx) / Math.sqrt(len2);\n}\n\n/**\n * Recursively subdivide a cubic bezier (P0..P3) and append `lineTo`-style\n * vertices to `out` (interleaved x,y). The starting endpoint is *not*\n * appended — callers usually emitted it as the segment's previous vertex.\n */\nexport function flattenCubic(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n x3: number, y3: number,\n tolerance: number,\n out: number[],\n): void {\n if (!finite8(x0, y0, x1, y1, x2, y2, x3, y3)) {\n out.push(x3, y3);\n return;\n }\n flattenCubicRec(x0, y0, x1, y1, x2, y2, x3, y3, usableTolerance(tolerance), out, 0);\n}\n\nfunction flattenCubicRec(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n x3: number, y3: number,\n tolerance: number,\n out: number[],\n depth: number,\n): void {\n const d1 = distPointToSegment(x1, y1, x0, y0, x3, y3);\n const d2 = distPointToSegment(x2, y2, x0, y0, x3, y3);\n if (Math.max(d1, d2) <= tolerance || depth >= MAX_FLATTEN_DEPTH) {\n out.push(x3, y3);\n return;\n }\n // De Casteljau split at t=0.5\n const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;\n const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;\n const x23 = (x2 + x3) * 0.5, y23 = (y2 + y3) * 0.5;\n const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;\n const x123 = (x12 + x23) * 0.5, y123 = (y12 + y23) * 0.5;\n const x0123 = (x012 + x123) * 0.5, y0123 = (y012 + y123) * 0.5;\n flattenCubicRec(x0, y0, x01, y01, x012, y012, x0123, y0123, tolerance, out, depth + 1);\n flattenCubicRec(x0123, y0123, x123, y123, x23, y23, x3, y3, tolerance, out, depth + 1);\n}\n\n/** Recursively subdivide a quadratic bezier (P0, P1, P2). */\nexport function flattenQuadratic(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n tolerance: number,\n out: number[],\n): void {\n if (!finite6(x0, y0, x1, y1, x2, y2)) {\n out.push(x2, y2);\n return;\n }\n flattenQuadraticRec(x0, y0, x1, y1, x2, y2, usableTolerance(tolerance), out, 0);\n}\n\nfunction flattenQuadraticRec(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n tolerance: number,\n out: number[],\n depth: number,\n): void {\n const d = distPointToSegment(x1, y1, x0, y0, x2, y2);\n if (d <= tolerance || depth >= MAX_FLATTEN_DEPTH) {\n out.push(x2, y2);\n return;\n }\n const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;\n const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;\n const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;\n flattenQuadraticRec(x0, y0, x01, y01, x012, y012, tolerance, out, depth + 1);\n flattenQuadraticRec(x012, y012, x12, y12, x2, y2, tolerance, out, depth + 1);\n}\n\n/**\n * Like `flattenCubic` but also appends to `arcOut`, for each new flattened\n * point, its *cumulative distance from the segment start* — not a normalized\n * fraction. The caller divides each by the segment's total flattened arc\n * length to yield t ∈ (0, 1].\n */\nexport function flattenCubicWithArcLen(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n x3: number, y3: number,\n tolerance: number,\n out: number[],\n arcOut: number[],\n): number {\n if (!finite8(x0, y0, x1, y1, x2, y2, x3, y3)) {\n out.push(x3, y3);\n arcOut.push(0);\n return 0;\n }\n return flattenCubicArcRec(x0, y0, x1, y1, x2, y2, x3, y3, usableTolerance(tolerance), out, arcOut, 0, 0);\n}\n\nfunction flattenCubicArcRec(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n x3: number, y3: number,\n tolerance: number,\n out: number[],\n arcOut: number[],\n accum: number,\n depth: number,\n): number {\n const d1 = distPointToSegment(x1, y1, x0, y0, x3, y3);\n const d2 = distPointToSegment(x2, y2, x0, y0, x3, y3);\n if (Math.max(d1, d2) <= tolerance || depth >= MAX_FLATTEN_DEPTH) {\n const lastX = out.length >= 2 ? out[out.length - 2] : x0;\n const lastY = out.length >= 2 ? out[out.length - 1] : y0;\n const seg = Math.hypot(x3 - lastX, y3 - lastY);\n accum += seg;\n out.push(x3, y3);\n arcOut.push(accum);\n return accum;\n }\n const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;\n const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;\n const x23 = (x2 + x3) * 0.5, y23 = (y2 + y3) * 0.5;\n const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;\n const x123 = (x12 + x23) * 0.5, y123 = (y12 + y23) * 0.5;\n const x0123 = (x012 + x123) * 0.5, y0123 = (y012 + y123) * 0.5;\n accum = flattenCubicArcRec(x0, y0, x01, y01, x012, y012, x0123, y0123, tolerance, out, arcOut, accum, depth + 1);\n accum = flattenCubicArcRec(x0123, y0123, x123, y123, x23, y23, x3, y3, tolerance, out, arcOut, accum, depth + 1);\n return accum;\n}\n\n/** Flatten a quadratic bezier into line segments within `tolerance`, appending\n * points to `out` and their cumulative arc lengths to `arcOut`. The arc\n * lengths are what lets per-anchor color and dash phase be interpolated\n * evenly along the curve rather than per segment. */\nexport function flattenQuadraticWithArcLen(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n tolerance: number,\n out: number[],\n arcOut: number[],\n): number {\n if (!finite6(x0, y0, x1, y1, x2, y2)) {\n out.push(x2, y2);\n arcOut.push(0);\n return 0;\n }\n return flattenQuadraticArcRec(x0, y0, x1, y1, x2, y2, usableTolerance(tolerance), out, arcOut, 0, 0);\n}\n\nfunction flattenQuadraticArcRec(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n tolerance: number,\n out: number[],\n arcOut: number[],\n accum: number,\n depth: number,\n): number {\n const d = distPointToSegment(x1, y1, x0, y0, x2, y2);\n if (d <= tolerance || depth >= MAX_FLATTEN_DEPTH) {\n const lastX = out.length >= 2 ? out[out.length - 2] : x0;\n const lastY = out.length >= 2 ? out[out.length - 1] : y0;\n const seg = Math.hypot(x2 - lastX, y2 - lastY);\n accum += seg;\n out.push(x2, y2);\n arcOut.push(accum);\n return accum;\n }\n const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;\n const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;\n const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;\n accum = flattenQuadraticArcRec(x0, y0, x01, y01, x012, y012, tolerance, out, arcOut, accum, depth + 1);\n accum = flattenQuadraticArcRec(x012, y012, x12, y12, x2, y2, tolerance, out, arcOut, accum, depth + 1);\n return accum;\n}\n\n","import { sign, dot, len2 } from './scalar';\n\n/**\n * Even-odd ray-cast point-in-polygon over an interleaved, unclosed contour\n * [x0,y0,x1,y1,…]. The closing edge (last→first) is implicit.\n *\n * `start`/`end` are vertex indices, not float offsets, and bound one contour\n * inside a buffer holding several.\n */\nexport function pointInPolygon(\n coords: ArrayLike<number>,\n px: number,\n py: number,\n start = 0,\n end = coords.length >> 1,\n): boolean {\n if (end - start < 3) return false;\n let inside = false;\n for (let i = start, j = end - 1; i < end; j = i++) {\n const xi = coords[i * 2], yi = coords[i * 2 + 1];\n const xj = coords[j * 2], yj = coords[j * 2 + 1];\n const crosses =\n (yi > py) !== (yj > py) &&\n px < ((xj - xi) * (py - yi)) / (yj - yi) + xi;\n if (crosses) inside = !inside;\n }\n return inside;\n}\n\n/**\n * True if segments (ax,ay)-(bx,by) and (cx,cy)-(dx,dy) intersect at a single\n * point. An endpoint landing on the other segment counts (a T-junction and a\n * shared endpoint both answer true) — hit-testing wants a grazing edge to\n * register. Collinear overlap answers false: there is no single crossing\n * point, so the sign test both segments rely on is zero on all four sides.\n */\nexport function segmentsCross(\n ax: number, ay: number, bx: number, by: number,\n cx: number, cy: number, dx: number, dy: number,\n): boolean {\n const d1 = sign((dx - cx) * (ay - cy) - (dy - cy) * (ax - cx));\n const d2 = sign((dx - cx) * (by - cy) - (dy - cy) * (bx - cx));\n const d3 = sign((bx - ax) * (cy - ay) - (by - ay) * (cx - ax));\n const d4 = sign((bx - ax) * (dy - ay) - (by - ay) * (dx - ax));\n return d1 !== d2 && d3 !== d4;\n}\n\n/** Squared distance from (px,py) to segment (ax,ay)-(bx,by), endpoint-clamped. */\nexport function pointSegmentDist2(\n px: number, py: number, ax: number, ay: number, bx: number, by: number,\n): number {\n const vx = bx - ax, vy = by - ay;\n const wx = px - ax, wy = py - ay;\n const vv = len2(vx, vy);\n let t = vv === 0 ? 0 : dot(wx, wy, vx, vy) / vv;\n t = t < 0 ? 0 : t > 1 ? 1 : t;\n const dx = px - (ax + t * vx), dy = py - (ay + t * vy);\n return len2(dx, dy);\n}\n","import type { PathOpenFill, PolygonPath } from './path';\n\nlet fallback: PathOpenFill = 'close';\n\n/** Set whether a fill closes an open subpath, for every path that names no\n * `openFill` of its own. Starts at `'close'`. */\nexport function setDefaultOpenFill(rule: PathOpenFill): void {\n fallback = rule;\n}\n\n/** The rule a path with no `openFill` of its own follows. */\nexport function defaultOpenFill(): PathOpenFill {\n return fallback;\n}\n\n/** Whether `path`'s open subpaths fill, each closed by a straight edge back to\n * its start. What painting, area, and the filled-region hit tests all ask. */\nexport function fillsOpenSubpaths(path: PolygonPath): boolean {\n return (path.openFill ?? fallback) === 'close';\n}\n"]}
|
|
@@ -30,5 +30,5 @@ function controlOnSide(anchor, dirX, dirY, dist, fraction) {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
export { cubicPointAt, fitCubicThroughDeletion, splitCubicAtT };
|
|
33
|
-
//# sourceMappingURL=chunk-
|
|
34
|
-
//# sourceMappingURL=chunk-
|
|
33
|
+
//# sourceMappingURL=chunk-XS6ERH3X.js.map
|
|
34
|
+
//# sourceMappingURL=chunk-XS6ERH3X.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/paths/cubicMath.ts"],"names":[],"mappings":"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","file":"chunk-XS6ERH3X.js","sourcesContent":["import { cubicEvalAt, splitCubicAt, type CubicCoords } from '../curve';\nimport type { PenAnchor } from './anchors';\n\n/** A 2D point, the shape the point-taking path helpers read and return. */\nexport interface Point { x: number; y: number; }\n\n/** Point on the cubic Bezier (p0, p1, p2, p3) at parameter t. The point-shaped\n * face of geom's `cubicEvalAt`. */\nexport function cubicPointAt(p0: Point, p1: Point, p2: Point, p3: Point, t: number): Point {\n const [x, y] = cubicEvalAt(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, t);\n return { x, y };\n}\n\n/** De Casteljau subdivision of a cubic at parameter t. The point-shaped face\n * of geom's `splitCubicAt`; `left[3]` and `right[0]` are the point at t. */\nexport function splitCubicAtT(\n p0: Point, p1: Point, p2: Point, p3: Point,\n t: number,\n): { left: [Point, Point, Point, Point]; right: [Point, Point, Point, Point] } {\n const [l, r] = splitCubicAt(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, t);\n const quad = (c: CubicCoords): [Point, Point, Point, Point] =>\n [{ x: c[0], y: c[1] }, { x: c[2], y: c[3] }, { x: c[4], y: c[5] }, { x: c[6], y: c[7] }];\n return { left: quad(l), right: quad(r) };\n}\n\n/**\n * When an interior anchor is deleted, the two flanking segments fuse into one\n * cubic. We pick controls c1 and c2 that:\n * - lie along prev's outHandle direction (if present)\n * - lie along next's inHandle direction (if present)\n * - are placed at roughly 1/3 and 2/3 of the prev→next distance\n * Fallbacks: missing handles use prev→next as the direction.\n *\n * This is an approximate fit — the new curve will shift slightly from the\n * original two-segment path. Acceptable per spec.\n */\nexport function fitCubicThroughDeletion(\n prev: PenAnchor,\n next: PenAnchor,\n): { c1: Point; c2: Point } {\n const dx = next.x - prev.x;\n const dy = next.y - prev.y;\n const dist = Math.sqrt(dx * dx + dy * dy);\n // c1: project along outHandle direction (or prev→next fallback) at 1/3 of dist.\n const c1DirX = prev.outHandle ? prev.outHandle.x - prev.x : dx;\n const c1DirY = prev.outHandle ? prev.outHandle.y - prev.y : dy;\n const c1 = controlOnSide(prev, c1DirX, c1DirY, dist, 1 / 3);\n // c2: project along inHandle direction (or next→prev fallback) at 1/3 of dist.\n const c2DirX = next.inHandle ? next.inHandle.x - next.x : -dx;\n const c2DirY = next.inHandle ? next.inHandle.y - next.y : -dy;\n const c2 = controlOnSide(next, c2DirX, c2DirY, dist, 1 / 3);\n return { c1, c2 };\n}\n\nfunction controlOnSide(\n anchor: PenAnchor,\n dirX: number,\n dirY: number,\n dist: number,\n fraction: number,\n): Point {\n const targetDist = dist * fraction;\n const len = Math.hypot(dirX, dirY) || 1;\n const ux = dirX / len, uy = dirY / len;\n return { x: anchor.x + ux * targetDist, y: anchor.y + uy * targetDist };\n}\n"]}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { P as PolygonPath, a as Path } from './path-Bf9KeVxC.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Counts the path anchors used by the per-anchor coloring surface. An
|
|
5
|
+
* "anchor" is the destination point of a path command: M, L, C, Q each
|
|
6
|
+
* contribute one (the (x, y) where the pen ends up); Z contributes none
|
|
7
|
+
* (it closes back to the subpath's first M). RectPath has four implicit
|
|
8
|
+
* anchors — the corners — matching its M/L/L/L/Z stroke tessellation.
|
|
9
|
+
*
|
|
10
|
+
* Consumers use this to size their per-anchor color array; the renderer
|
|
11
|
+
* uses it to validate the array length in dev builds.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** One anchor of an editable path: its on-curve point plus the two control
|
|
15
|
+
* handles that shape the segments either side of it. Handles are in the same
|
|
16
|
+
* space as the point, and absent when the adjoining segment is straight. */
|
|
17
|
+
interface PenAnchor {
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
inHandle?: {
|
|
21
|
+
x: number;
|
|
22
|
+
y: number;
|
|
23
|
+
};
|
|
24
|
+
outHandle?: {
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Derive a per-subpath anchor model from a PolygonPath. Subpaths split on
|
|
31
|
+
* every `M` command; a subpath is closed iff it ends with `Z`.
|
|
32
|
+
*
|
|
33
|
+
* Cubic-segment control points become the outHandle of the previous anchor
|
|
34
|
+
* and the inHandle of the next anchor. A closed subpath whose last curve ends
|
|
35
|
+
* exactly on its first point holds that point twice; the two are one anchor,
|
|
36
|
+
* and the curve's second control is that anchor's inHandle. Quadratic segments are upgraded to
|
|
37
|
+
* cubics (each control reused for both adjacent handles) — this loses no
|
|
38
|
+
* geometry. Linear segments produce anchors with no handles.
|
|
39
|
+
*/
|
|
40
|
+
declare function pathToAnchors(path: PolygonPath): {
|
|
41
|
+
anchors: PenAnchor[][];
|
|
42
|
+
closed: boolean[];
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Serialize the per-subpath anchor model back to a PolygonPath. Inverse of
|
|
46
|
+
* `pathToAnchors`. Curve-vs-line decision per segment:
|
|
47
|
+
* - Both adjacent handles absent → straight L segment.
|
|
48
|
+
* - Either handle present → C segment, with missing handles defaulting to
|
|
49
|
+
* the anchor point itself (degenerate but valid; renders as a near-line).
|
|
50
|
+
* Given `like`, the path being reshaped, the result keeps its fill rules.
|
|
51
|
+
*/
|
|
52
|
+
declare function anchorsToPath(anchors: PenAnchor[][], closed: boolean[], like?: PolygonPath): PolygonPath;
|
|
53
|
+
/**
|
|
54
|
+
* Returns true if the anchor's in-handle and out-handle are collinear with
|
|
55
|
+
* the anchor point, indicating "smooth" (mirror-drag) behavior. Detected via
|
|
56
|
+
* the magnitude of the normalized cross product of the two handle vectors.
|
|
57
|
+
*
|
|
58
|
+
* Edge cases:
|
|
59
|
+
* - Missing in or out handle → false (corner by definition).
|
|
60
|
+
* - Either handle at zero distance from anchor → false.
|
|
61
|
+
*/
|
|
62
|
+
declare function isAnchorSmooth(a: PenAnchor): boolean;
|
|
63
|
+
/** How many anchors a path has. Matches the per-anchor arrays the renderer
|
|
64
|
+
* expects for `vertexColors`. */
|
|
65
|
+
declare function countPathAnchors(path: Path): number;
|
|
66
|
+
/** The segment `(sub, segIdx)` as its two end anchors, or null when it
|
|
67
|
+
* doesn't exist. `segIdx === sub.length - 1` names a closed subpath's
|
|
68
|
+
* closing segment, which runs from the last anchor back to the first. */
|
|
69
|
+
declare function segmentEnds(anchors: readonly PenAnchor[][], closed: readonly boolean[] | undefined, sub: number, segIdx: number): {
|
|
70
|
+
a: PenAnchor;
|
|
71
|
+
b: PenAnchor;
|
|
72
|
+
} | null;
|
|
73
|
+
/** Whether the segment from `a` to `b` is a straight line (no handles). */
|
|
74
|
+
declare function isStraightSegment(a: PenAnchor, b: PenAnchor): boolean;
|
|
75
|
+
/** The segment of a decoded path nearest `(wx, wy)`, and the parameter `t`
|
|
76
|
+
* on it closest to that point. Pass `closed` (from `pathToAnchors`) to
|
|
77
|
+
* include each closed subpath's closing segment, reported as
|
|
78
|
+
* `segIdx === sub.length - 1`. `t` spans `[0, 1]`, endpoints included.
|
|
79
|
+
* Returns `null` only when there are no segments. */
|
|
80
|
+
declare function nearestSegmentT(anchors: PenAnchor[][], wx: number, wy: number, closed?: readonly boolean[]): {
|
|
81
|
+
sub: number;
|
|
82
|
+
segIdx: number;
|
|
83
|
+
t: number;
|
|
84
|
+
} | null;
|
|
85
|
+
|
|
86
|
+
/** A 2D point, the shape the point-taking path helpers read and return. */
|
|
87
|
+
interface Point {
|
|
88
|
+
x: number;
|
|
89
|
+
y: number;
|
|
90
|
+
}
|
|
91
|
+
/** Point on the cubic Bezier (p0, p1, p2, p3) at parameter t. The point-shaped
|
|
92
|
+
* face of geom's `cubicEvalAt`. */
|
|
93
|
+
declare function cubicPointAt(p0: Point, p1: Point, p2: Point, p3: Point, t: number): Point;
|
|
94
|
+
/** De Casteljau subdivision of a cubic at parameter t. The point-shaped face
|
|
95
|
+
* of geom's `splitCubicAt`; `left[3]` and `right[0]` are the point at t. */
|
|
96
|
+
declare function splitCubicAtT(p0: Point, p1: Point, p2: Point, p3: Point, t: number): {
|
|
97
|
+
left: [Point, Point, Point, Point];
|
|
98
|
+
right: [Point, Point, Point, Point];
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* When an interior anchor is deleted, the two flanking segments fuse into one
|
|
102
|
+
* cubic. We pick controls c1 and c2 that:
|
|
103
|
+
* - lie along prev's outHandle direction (if present)
|
|
104
|
+
* - lie along next's inHandle direction (if present)
|
|
105
|
+
* - are placed at roughly 1/3 and 2/3 of the prev→next distance
|
|
106
|
+
* Fallbacks: missing handles use prev→next as the direction.
|
|
107
|
+
*
|
|
108
|
+
* This is an approximate fit — the new curve will shift slightly from the
|
|
109
|
+
* original two-segment path. Acceptable per spec.
|
|
110
|
+
*/
|
|
111
|
+
declare function fitCubicThroughDeletion(prev: PenAnchor, next: PenAnchor): {
|
|
112
|
+
c1: Point;
|
|
113
|
+
c2: Point;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export { type Point as P, type PenAnchor as a, anchorsToPath as b, countPathAnchors as c, cubicPointAt as d, isStraightSegment as e, fitCubicThroughDeletion as f, splitCubicAtT as g, isAnchorSmooth as i, nearestSegmentT as n, pathToAnchors as p, segmentEnds as s };
|
package/dist/curves/index.d.ts
CHANGED
package/dist/curves/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { cubicPointAt } from '../chunk-
|
|
1
|
+
import { cubicPointAt } from '../chunk-XS6ERH3X.js';
|
|
2
2
|
import '../chunk-URQMDR6Q.js';
|
|
3
|
-
import { PATH_M, PATH_C, PATH_L, PATH_Q } from '../chunk-
|
|
3
|
+
import { PATH_M, PATH_C, PATH_L, PATH_Q } from '../chunk-OXH3NOXC.js';
|
|
4
4
|
|
|
5
|
-
// src/curves/
|
|
5
|
+
// src/curves/anchorHandles.ts
|
|
6
6
|
var DEFAULT_HANDLE_FRACTION = 1 / 3;
|
|
7
7
|
function smoothTangent(anchors, i) {
|
|
8
8
|
const prev = i > 0 ? anchors[i - 1] : null;
|
|
@@ -51,6 +51,8 @@ function segmentAt(anchors, t) {
|
|
|
51
51
|
const localT = scaled - segIdx;
|
|
52
52
|
return { segIdx, localT };
|
|
53
53
|
}
|
|
54
|
+
|
|
55
|
+
// src/curves/bezierCubic.ts
|
|
54
56
|
function cubicDeriv1(p0, p1, p2, p3, t) {
|
|
55
57
|
const u = 1 - t;
|
|
56
58
|
return {
|
|
@@ -127,59 +129,11 @@ var bezierCubic = {
|
|
|
127
129
|
};
|
|
128
130
|
|
|
129
131
|
// src/curves/bezierQuadratic.ts
|
|
130
|
-
var DEFAULT_HANDLE_FRACTION2 = 1 / 3;
|
|
131
|
-
function smoothTangent2(anchors, i) {
|
|
132
|
-
const prev = i > 0 ? anchors[i - 1] : null;
|
|
133
|
-
const next = i + 1 < anchors.length ? anchors[i + 1] : null;
|
|
134
|
-
if (!prev && next) return { x: next.x - anchors[i].x, y: next.y - anchors[i].y };
|
|
135
|
-
if (prev && !next) return { x: anchors[i].x - prev.x, y: anchors[i].y - prev.y };
|
|
136
|
-
if (prev && next) {
|
|
137
|
-
const inLen = Math.hypot(anchors[i].x - prev.x, anchors[i].y - prev.y) || 1;
|
|
138
|
-
const outLen = Math.hypot(next.x - anchors[i].x, next.y - anchors[i].y) || 1;
|
|
139
|
-
return {
|
|
140
|
-
x: (anchors[i].x - prev.x) / inLen + (next.x - anchors[i].x) / outLen,
|
|
141
|
-
y: (anchors[i].y - prev.y) / inLen + (next.y - anchors[i].y) / outLen
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
return { x: 0, y: 0 };
|
|
145
|
-
}
|
|
146
|
-
function defaultOutHandle2(anchors, i) {
|
|
147
|
-
const a = anchors[i];
|
|
148
|
-
if (a.outHandle) return a.outHandle;
|
|
149
|
-
const next = anchors[i + 1];
|
|
150
|
-
const edgeLen = Math.hypot(next.x - a.x, next.y - a.y);
|
|
151
|
-
const t = smoothTangent2(anchors, i);
|
|
152
|
-
const tLen = Math.hypot(t.x, t.y) || 1;
|
|
153
|
-
return {
|
|
154
|
-
x: a.x + t.x / tLen * edgeLen * DEFAULT_HANDLE_FRACTION2,
|
|
155
|
-
y: a.y + t.y / tLen * edgeLen * DEFAULT_HANDLE_FRACTION2
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
function defaultInHandle2(anchors, i) {
|
|
159
|
-
const b = anchors[i + 1];
|
|
160
|
-
if (b.inHandle) return b.inHandle;
|
|
161
|
-
const a = anchors[i];
|
|
162
|
-
const edgeLen = Math.hypot(b.x - a.x, b.y - a.y);
|
|
163
|
-
const t = smoothTangent2(anchors, i + 1);
|
|
164
|
-
const tLen = Math.hypot(t.x, t.y) || 1;
|
|
165
|
-
return {
|
|
166
|
-
x: b.x - t.x / tLen * edgeLen * DEFAULT_HANDLE_FRACTION2,
|
|
167
|
-
y: b.y - t.y / tLen * edgeLen * DEFAULT_HANDLE_FRACTION2
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
132
|
function quadControl(anchors, i) {
|
|
171
|
-
const c1 =
|
|
172
|
-
const c2 =
|
|
133
|
+
const c1 = defaultOutHandle(anchors, i);
|
|
134
|
+
const c2 = defaultInHandle(anchors, i);
|
|
173
135
|
return { x: (c1.x + c2.x) / 2, y: (c1.y + c2.y) / 2 };
|
|
174
136
|
}
|
|
175
|
-
function segmentAt2(anchors, t) {
|
|
176
|
-
if (anchors.length < 2) return { segIdx: 0, localT: 0 };
|
|
177
|
-
const segments = anchors.length - 1;
|
|
178
|
-
const scaled = Math.min(Math.max(t, 0), 1) * segments;
|
|
179
|
-
const segIdx = Math.min(Math.floor(scaled), segments - 1);
|
|
180
|
-
const localT = scaled - segIdx;
|
|
181
|
-
return { segIdx, localT };
|
|
182
|
-
}
|
|
183
137
|
function quadEval(p0, p1, p2, t) {
|
|
184
138
|
const u = 1 - t;
|
|
185
139
|
return {
|
|
@@ -205,7 +159,7 @@ var bezierQuadratic = {
|
|
|
205
159
|
label: "Quadratic Bezier",
|
|
206
160
|
evaluate(anchors, t) {
|
|
207
161
|
if (anchors.length < 2) return { x: anchors[0]?.x ?? 0, y: anchors[0]?.y ?? 0 };
|
|
208
|
-
const { segIdx, localT } =
|
|
162
|
+
const { segIdx, localT } = segmentAt(anchors, t);
|
|
209
163
|
const a = anchors[segIdx];
|
|
210
164
|
const b = anchors[segIdx + 1];
|
|
211
165
|
return quadEval(a, quadControl(anchors, segIdx), b, localT);
|
|
@@ -231,7 +185,7 @@ var bezierQuadratic = {
|
|
|
231
185
|
},
|
|
232
186
|
curvatureAt(anchors, t) {
|
|
233
187
|
if (anchors.length < 2) return 0;
|
|
234
|
-
const { segIdx, localT } =
|
|
188
|
+
const { segIdx, localT } = segmentAt(anchors, t);
|
|
235
189
|
const a = anchors[segIdx];
|
|
236
190
|
const b = anchors[segIdx + 1];
|
|
237
191
|
const p1 = quadControl(anchors, segIdx);
|
|
@@ -348,11 +302,12 @@ var nurbs = {
|
|
|
348
302
|
curvatureAt(anchors, t) {
|
|
349
303
|
if (anchors.length < 2) return 0;
|
|
350
304
|
const eps = 1e-3;
|
|
351
|
-
const
|
|
352
|
-
const
|
|
305
|
+
const tm = Math.min(1 - eps, Math.max(eps, t));
|
|
306
|
+
const t0 = tm - eps;
|
|
307
|
+
const t1 = tm + eps;
|
|
353
308
|
const p0 = evalNurbs(anchors, t0);
|
|
354
309
|
const p2 = evalNurbs(anchors, t1);
|
|
355
|
-
const pm = evalNurbs(anchors,
|
|
310
|
+
const pm = evalNurbs(anchors, tm);
|
|
356
311
|
const d1x = (p2.x - p0.x) / (t1 - t0);
|
|
357
312
|
const d1y = (p2.y - p0.y) / (t1 - t0);
|
|
358
313
|
const d2x = (p2.x - 2 * pm.x + p0.x) / (eps * eps);
|
|
@@ -385,7 +340,7 @@ var TANGENT_SCALE = 1 / 3;
|
|
|
385
340
|
function isCorner(a) {
|
|
386
341
|
return a.spiroType === "corner";
|
|
387
342
|
}
|
|
388
|
-
function
|
|
343
|
+
function smoothTangent2(anchors, i) {
|
|
389
344
|
if (isCorner(anchors[i])) return null;
|
|
390
345
|
const prev = i > 0 ? anchors[i - 1] : null;
|
|
391
346
|
const next = i + 1 < anchors.length ? anchors[i + 1] : null;
|
|
@@ -412,8 +367,8 @@ function controlsFor(anchors, i) {
|
|
|
412
367
|
const b = anchors[i + 1];
|
|
413
368
|
const edge = { x: b.x - a.x, y: b.y - a.y };
|
|
414
369
|
const edgeLen = Math.hypot(edge.x, edge.y) || 1;
|
|
415
|
-
const tA =
|
|
416
|
-
const tB =
|
|
370
|
+
const tA = smoothTangent2(anchors, i);
|
|
371
|
+
const tB = smoothTangent2(anchors, i + 1);
|
|
417
372
|
const outA = tA ?? edge;
|
|
418
373
|
const outB = tB ?? edge;
|
|
419
374
|
const outALen = Math.hypot(outA.x, outA.y) || 1;
|
|
@@ -430,20 +385,12 @@ function controlsFor(anchors, i) {
|
|
|
430
385
|
}
|
|
431
386
|
};
|
|
432
387
|
}
|
|
433
|
-
function segmentAt3(anchors, t) {
|
|
434
|
-
if (anchors.length < 2) return { segIdx: 0, localT: 0 };
|
|
435
|
-
const segments = anchors.length - 1;
|
|
436
|
-
const scaled = Math.min(Math.max(t, 0), 1) * segments;
|
|
437
|
-
const segIdx = Math.min(Math.floor(scaled), segments - 1);
|
|
438
|
-
const localT = scaled - segIdx;
|
|
439
|
-
return { segIdx, localT };
|
|
440
|
-
}
|
|
441
388
|
var spiro = {
|
|
442
389
|
kind: "spiro",
|
|
443
390
|
label: "Spiro (\u03BA-curves v1)",
|
|
444
391
|
evaluate(anchors, t) {
|
|
445
392
|
if (anchors.length < 2) return { x: anchors[0]?.x ?? 0, y: anchors[0]?.y ?? 0 };
|
|
446
|
-
const { segIdx, localT } =
|
|
393
|
+
const { segIdx, localT } = segmentAt(anchors, t);
|
|
447
394
|
const a = anchors[segIdx];
|
|
448
395
|
const b = anchors[segIdx + 1];
|
|
449
396
|
const { c1, c2 } = controlsFor(anchors, segIdx);
|
|
@@ -470,7 +417,7 @@ var spiro = {
|
|
|
470
417
|
},
|
|
471
418
|
curvatureAt(anchors, t) {
|
|
472
419
|
if (anchors.length < 2) return 0;
|
|
473
|
-
const { segIdx, localT } =
|
|
420
|
+
const { segIdx, localT } = segmentAt(anchors, t);
|
|
474
421
|
const a = anchors[segIdx];
|
|
475
422
|
const b = anchors[segIdx + 1];
|
|
476
423
|
const { c1, c2 } = controlsFor(anchors, segIdx);
|