@weasel-js/geom 1.6.0 → 1.7.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.
@@ -1,4 +1,4 @@
1
- import { PATH_Z, PATH_Q, elevateQuadraticToCubic, flattenCubic, PATH_C, PATH_L, PATH_M } from '../chunk-DQ6QRAWP.js';
1
+ import { PATH_Z, PATH_Q, elevateQuadraticToCubic, flattenCubic, PATH_C, PATH_L, PATH_M } from '../chunk-36DHVSOV.js';
2
2
  import polygonClipping from 'polygon-clipping';
3
3
 
4
4
  // src/booleans/adapter.ts
@@ -34,6 +34,7 @@ function forEachSegment(commands, coords, visit) {
34
34
  const cmd = commands[i];
35
35
  if (visit(cmd, ci, px, py, i) === false) return;
36
36
  const len = pathCommandCoordCount(cmd);
37
+ if (len === void 0) throw new Error(`forEachSegment: unknown command code ${cmd}`);
37
38
  if (len > 0) {
38
39
  px = coords[ci + len - 2];
39
40
  py = coords[ci + len - 1];
@@ -101,6 +102,30 @@ function cubicBounds(x0, y0, x1, y1, x2, y2, x3, y3) {
101
102
  }
102
103
  return [minX, minY, maxX, maxY];
103
104
  }
105
+ function quadraticEvalAt(x0, y0, x1, y1, x2, y2, t) {
106
+ const u = 1 - t;
107
+ const a = u * u, b = 2 * u * t, c = t * t;
108
+ return [a * x0 + b * x1 + c * x2, a * y0 + b * y1 + c * y2];
109
+ }
110
+ function splitCubicAt(x0, y0, x1, y1, x2, y2, x3, y3, t) {
111
+ const ax = x0 + (x1 - x0) * t, ay = y0 + (y1 - y0) * t;
112
+ const bx = x1 + (x2 - x1) * t, by = y1 + (y2 - y1) * t;
113
+ const cx = x2 + (x3 - x2) * t, cy = y2 + (y3 - y2) * t;
114
+ const dx = ax + (bx - ax) * t, dy = ay + (by - ay) * t;
115
+ const ex = bx + (cx - bx) * t, ey = by + (cy - by) * t;
116
+ const mx = dx + (ex - dx) * t, my = dy + (ey - dy) * t;
117
+ return [[x0, y0, ax, ay, dx, dy, mx, my], [mx, my, ex, ey, cx, cy, x3, y3]];
118
+ }
119
+ function splitQuadraticAt(x0, y0, x1, y1, x2, y2, t) {
120
+ const ax = x0 + (x1 - x0) * t, ay = y0 + (y1 - y0) * t;
121
+ const bx = x1 + (x2 - x1) * t, by = y1 + (y2 - y1) * t;
122
+ const mx = ax + (bx - ax) * t, my = ay + (by - ay) * t;
123
+ return [[x0, y0, ax, ay, mx, my], [mx, my, bx, by, x2, y2]];
124
+ }
125
+ function splitLineAt(x0, y0, x1, y1, t) {
126
+ const mx = x0 + (x1 - x0) * t, my = y0 + (y1 - y0) * t;
127
+ return [[x0, y0, mx, my], [mx, my, x1, y1]];
128
+ }
104
129
 
105
130
  // src/flatten.ts
106
131
  var DEFAULT_FLATTEN_TOLERANCE = 0.5;
@@ -226,6 +251,6 @@ function flattenQuadraticArcRec(x0, y0, x1, y1, x2, y2, tolerance, out, arcOut,
226
251
  return accum;
227
252
  }
228
253
 
229
- export { DEFAULT_FLATTEN_TOLERANCE, PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_Z, cubicBounds, cubicEvalAt, elevateQuadraticToCubic, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, forEachSegment, pathCommandCoordCount };
230
- //# sourceMappingURL=chunk-DQ6QRAWP.js.map
231
- //# sourceMappingURL=chunk-DQ6QRAWP.js.map
254
+ export { DEFAULT_FLATTEN_TOLERANCE, PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_Z, cubicBounds, cubicEvalAt, elevateQuadraticToCubic, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, forEachSegment, pathCommandCoordCount, quadraticEvalAt, splitCubicAt, splitLineAt, splitQuadraticAt };
255
+ //# sourceMappingURL=chunk-36DHVSOV.js.map
256
+ //# sourceMappingURL=chunk-36DHVSOV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands.ts","../src/curve.ts","../src/flatten.ts"],"names":[],"mappings":"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","file":"chunk-36DHVSOV.js","sourcesContent":["/**\n * SVG-style command-stream encoding — the kit's single declaration of the path\n * opcodes. `Path` in @weasel-js/core wraps this with `kind` + `fillRule`.\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. Derive, never restate.\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\nexport const PATH_M = PATH_COMMANDS.M.code;\nexport const PATH_L = PATH_COMMANDS.L.code;\nexport const PATH_C = PATH_COMMANDS.C.code;\nexport const PATH_Q = PATH_COMMANDS.Q.code;\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 receives\n * (cmd, coordIndex, penX, penY, commandIndex) and stops the walk by returning\n * `false`. The pen advances to the command's last coord pair afterward; `Z`\n * returns it to the subpath's opening `M`, so a command following a `Z`\n * without an intervening `M` starts where SVG says it does.\n *\n * A code `PATH_COMMANDS` does not declare throws once the visitor has seen it,\n * since the walker cannot tell how many coords it consumes.\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 ) => void | boolean,\n): void {\n let ci = 0;\n let px = 0, py = 0;\n let startX = 0, startY = 0;\n for (let i = 0; i < commands.length; i++) {\n const cmd = commands[i];\n if (visit(cmd, ci, px, py, i) === 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","import type { Box } from './box';\n\n/** Cubic Bezier point at parameter t (de Casteljau / Bernstein form). */\nexport function cubicEvalAt(\n x0: number, y0: number, x1: number, y1: number,\n x2: number, y2: number, x3: number, y3: number, t: number,\n): [number, number] {\n const u = 1 - t;\n const a = u * u * u, b = 3 * u * u * t, c = 3 * u * t * t, d = t * t * t;\n return [\n a * x0 + b * x1 + c * x2 + d * x3,\n a * y0 + b * y1 + c * y2 + d * y3,\n ];\n}\n\n/**\n * Degree-elevate a quadratic (q0, ctrl, q1) to a cubic. Returns the two\n * cubic control points [c1x, c1y, c2x, c2y]; the cubic endpoints equal the\n * quadratic endpoints. c1 = q0 + 2/3(ctrl-q0), c2 = q1 + 2/3(ctrl-q1).\n */\nexport function elevateQuadraticToCubic(\n q0x: number, q0y: number, cx: number, cy: number, q1x: number, q1y: number,\n): [number, number, number, number] {\n return [\n q0x + (2 / 3) * (cx - q0x),\n q0y + (2 / 3) * (cy - q0y),\n q1x + (2 / 3) * (cx - q1x),\n q1y + (2 / 3) * (cy - q1y),\n ];\n}\n\n/** Axis-aligned extrema parameters of one cubic component (the 0,1 ends plus\n * any derivative roots in (0,1)). Used by cubicBounds. */\nfunction componentExtremaTs(p0: number, p1: number, p2: number, p3: number): number[] {\n // B'(t)=0 → quadratic a t² + b t + c = 0 with:\n const a = -p0 + 3 * p1 - 3 * p2 + p3;\n const b = 2 * (p0 - 2 * p1 + p2);\n const c = -p0 + p1;\n const ts: number[] = [];\n const push = (t: number) => { if (t > 0 && t < 1) ts.push(t); };\n if (Math.abs(a) < 1e-12) {\n if (Math.abs(b) > 1e-12) push(-c / b);\n } else {\n const disc = b * b - 4 * a * c;\n if (disc >= 0) {\n const sq = Math.sqrt(disc);\n push((-b + sq) / (2 * a));\n push((-b - sq) / (2 * a));\n }\n }\n return ts;\n}\n\n/** Tight AABB of a cubic, evaluating only extrema that lie on the curve. */\nexport function cubicBounds(\n x0: number, y0: number, x1: number, y1: number,\n x2: number, y2: number, x3: number, y3: number,\n): Box {\n let minX = Math.min(x0, x3), maxX = Math.max(x0, x3);\n let minY = Math.min(y0, y3), maxY = Math.max(y0, y3);\n for (const t of componentExtremaTs(x0, x1, x2, x3)) {\n const [ex] = cubicEvalAt(x0, y0, x1, y1, x2, y2, x3, y3, t);\n if (ex < minX) minX = ex;\n if (ex > maxX) maxX = ex;\n }\n for (const t of componentExtremaTs(y0, y1, y2, y3)) {\n const [, ey] = cubicEvalAt(x0, y0, x1, y1, x2, y2, x3, y3, t);\n if (ey < minY) minY = ey;\n if (ey > maxY) maxY = ey;\n }\n return [minX, minY, maxX, maxY];\n}\n\n/** Quadratic Bezier point at parameter t (Bernstein form). */\nexport function quadraticEvalAt(\n x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, t: number,\n): [number, number] {\n const u = 1 - t;\n const a = u * u, b = 2 * u * t, c = t * t;\n return [a * x0 + b * x1 + c * x2, a * y0 + b * y1 + c * y2];\n}\n\n/** A line segment's coords: start, end. */\nexport type LineCoords = [number, number, number, number];\n/** A quadratic Bezier's coords: start, control, end. */\nexport type QuadraticCoords = [number, number, number, number, number, number];\n/** A cubic Bezier's coords: start, two controls, end. */\nexport type CubicCoords = [number, number, number, number, number, number, number, number];\n\n/**\n * Split a cubic at parameter t (de Casteljau). The two halves share the point\n * at t and together trace the original exactly. A t outside [0, 1] splits the\n * curve's polynomial extension.\n */\nexport function splitCubicAt(\n x0: number, y0: number, x1: number, y1: number,\n x2: number, y2: number, x3: number, y3: number, t: number,\n): [CubicCoords, CubicCoords] {\n const ax = x0 + (x1 - x0) * t, ay = y0 + (y1 - y0) * t;\n const bx = x1 + (x2 - x1) * t, by = y1 + (y2 - y1) * t;\n const cx = x2 + (x3 - x2) * t, cy = y2 + (y3 - y2) * t;\n const dx = ax + (bx - ax) * t, dy = ay + (by - ay) * t;\n const ex = bx + (cx - bx) * t, ey = by + (cy - by) * t;\n const mx = dx + (ex - dx) * t, my = dy + (ey - dy) * t;\n return [[x0, y0, ax, ay, dx, dy, mx, my], [mx, my, ex, ey, cx, cy, x3, y3]];\n}\n\n/** Split a quadratic at parameter t (de Casteljau). See {@link splitCubicAt}. */\nexport function splitQuadraticAt(\n x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, t: number,\n): [QuadraticCoords, QuadraticCoords] {\n const ax = x0 + (x1 - x0) * t, ay = y0 + (y1 - y0) * t;\n const bx = x1 + (x2 - x1) * t, by = y1 + (y2 - y1) * t;\n const mx = ax + (bx - ax) * t, my = ay + (by - ay) * t;\n return [[x0, y0, ax, ay, mx, my], [mx, my, bx, by, x2, y2]];\n}\n\n/** Split a line segment at parameter t. See {@link splitCubicAt}. */\nexport function splitLineAt(\n x0: number, y0: number, x1: number, y1: number, t: number,\n): [LineCoords, LineCoords] {\n const mx = x0 + (x1 - x0) * t, my = y0 + (y1 - y0) * t;\n return [[x0, y0, mx, my], [mx, my, x1, y1]];\n}\n","/**\n * Bezier flattening — subdivide cubic and quadratic segments into polyline\n * approximations within a flatness tolerance. Used by hit-testing and\n * (eventually) any kernel that doesn't want to special-case curves.\n *\n * The flatness metric is the maximum perpendicular distance from any\n * control point to the chord between endpoints. When that distance falls\n * below `tolerance`, the segment is \"flat enough\" and emitted as a single\n * line segment.\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/** Distance from point P to line AB (perpendicular). */\nfunction distPointToLine(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 if (len2 === 0) {\n const ex = px - ax;\n const ey = py - ay;\n return Math.sqrt(ex * ex + ey * ey);\n }\n const cross = (px - ax) * dy - (py - ay) * dx;\n return Math.abs(cross) / 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 = distPointToLine(x1, y1, x0, y0, x3, y3);\n const d2 = distPointToLine(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 = distPointToLine(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, for each new flattened point, its\n * arc-length fraction `t` (relative to the polyline distance accumulated so\n * far inside this curve) to `arcOut`. Caller then post-processes the segment's\n * `arcOut` range by dividing each by the segment's total flattened arc length\n * to yield t ∈ (0, 1].\n *\n * The returned values are *cumulative distance from the segment start*, not\n * normalized fractions. Two-pass design (accumulate, then divide) keeps the\n * recursive splitter simple — it doesn't need to know the total length up\n * front.\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 = distPointToLine(x1, y1, x0, y0, x3, y3);\n const d2 = distPointToLine(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 = distPointToLine(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"]}
package/dist/index.d.ts CHANGED
@@ -137,6 +137,9 @@ declare function pathCommandCoordCount(cmd: number): number;
137
137
  * `false`. The pen advances to the command's last coord pair afterward; `Z`
138
138
  * returns it to the subpath's opening `M`, so a command following a `Z`
139
139
  * without an intervening `M` starts where SVG says it does.
140
+ *
141
+ * A code `PATH_COMMANDS` does not declare throws once the visitor has seen it,
142
+ * since the walker cannot tell how many coords it consumes.
140
143
  */
141
144
  declare function forEachSegment(commands: ArrayLike<number>, coords: ArrayLike<number>, visit: (cmd: number, coordIndex: number, penX: number, penY: number, commandIndex: number) => void | boolean): void;
142
145
 
@@ -150,6 +153,58 @@ declare function cubicEvalAt(x0: number, y0: number, x1: number, y1: number, x2:
150
153
  declare function elevateQuadraticToCubic(q0x: number, q0y: number, cx: number, cy: number, q1x: number, q1y: number): [number, number, number, number];
151
154
  /** Tight AABB of a cubic, evaluating only extrema that lie on the curve. */
152
155
  declare function cubicBounds(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): Box;
156
+ /** Quadratic Bezier point at parameter t (Bernstein form). */
157
+ declare function quadraticEvalAt(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, t: number): [number, number];
158
+ /** A line segment's coords: start, end. */
159
+ type LineCoords = [number, number, number, number];
160
+ /** A quadratic Bezier's coords: start, control, end. */
161
+ type QuadraticCoords = [number, number, number, number, number, number];
162
+ /** A cubic Bezier's coords: start, two controls, end. */
163
+ type CubicCoords = [number, number, number, number, number, number, number, number];
164
+ /**
165
+ * Split a cubic at parameter t (de Casteljau). The two halves share the point
166
+ * at t and together trace the original exactly. A t outside [0, 1] splits the
167
+ * curve's polynomial extension.
168
+ */
169
+ declare function splitCubicAt(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, t: number): [CubicCoords, CubicCoords];
170
+ /** Split a quadratic at parameter t (de Casteljau). See {@link splitCubicAt}. */
171
+ declare function splitQuadraticAt(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, t: number): [QuadraticCoords, QuadraticCoords];
172
+ /** Split a line segment at parameter t. See {@link splitCubicAt}. */
173
+ declare function splitLineAt(x0: number, y0: number, x1: number, y1: number, t: number): [LineCoords, LineCoords];
174
+
175
+ /** The point on one segment nearest a probe. */
176
+ interface CurveNearest {
177
+ x: number;
178
+ y: number;
179
+ /** Curve parameter of the point, in [0, 1]. */
180
+ t: number;
181
+ /** Euclidean distance from the probe. */
182
+ dist: number;
183
+ }
184
+ /** The point on a path nearest a probe, and the command whose segment holds it. */
185
+ interface PathNearest extends CurveNearest {
186
+ /** Index of the segment's command in the command stream (`L`, `Q`, `C` or `Z`). */
187
+ commandIndex: number;
188
+ /** Offset of that command's first coord; for a `Z`, where its coords would begin. */
189
+ coordIndex: number;
190
+ }
191
+ /** Nearest point on segment (x0,y0)-(x1,y1) to (px,py). */
192
+ declare function nearestOnLine(px: number, py: number, x0: number, y0: number, x1: number, y1: number): CurveNearest;
193
+ /**
194
+ * Nearest point on the cubic (x0,y0)…(x3,y3) to (px,py). Samples the curve,
195
+ * then refines every sampled local minimum with bracketed Newton on the
196
+ * distance derivative, so a loop or cusp cannot capture it in the wrong basin.
197
+ */
198
+ declare function nearestOnCubic(px: number, py: number, x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): CurveNearest;
199
+ /** Nearest point on the quadratic (x0,y0)(x1,y1)(x2,y2) to (px,py). */
200
+ declare function nearestOnQuadratic(px: number, py: number, x0: number, y0: number, x1: number, y1: number, x2: number, y2: number): CurveNearest;
201
+ /**
202
+ * Nearest point on a command-stream path to (px,py), over every `L`, `Q`, `C`
203
+ * and the closing edge each `Z` draws. The earliest segment wins a tie.
204
+ * Returns `null` when the path has no segment, and throws on a command code
205
+ * `PATH_COMMANDS` does not declare.
206
+ */
207
+ declare function nearestOnPath(commands: ArrayLike<number>, coords: ArrayLike<number>, px: number, py: number): PathNearest | null;
153
208
 
154
209
  /**
155
210
  * The port-curve rule in the 2D kernel's currency: loose scalars, the way
@@ -275,4 +330,4 @@ interface PlacedRect {
275
330
  declare function clampRectWithin(rect: Rect, boundary: Rect, padding?: number): Rect;
276
331
  declare function placeRect(options: PlaceRectOptions): PlacedRect;
277
332
 
278
- export { type Box, DEFAULT_FLATTEN_TOLERANCE, EPS, type Mat3, PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_Z, type PathCommandCode, type PathCommandName, type PlaceRectOptions, type PlacedRect, type Placement, type PlacementAlign, type PlacementSide, type Rect, applyToPoint, approxEq, boundsOfCoords, boxContainsPoint, boxToBox, clampRectWithin, cross, cubicBounds, cubicEvalAt, dot, elevateQuadraticToCubic, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, forEachSegment, identity, invert, len2, multiply, pathCommandCoordCount, placeRect, pointInPolygon, pointSegmentDist2, portControls, portCurvePoints, rectToContour, rotate, rotateAboutPoint, scale, segmentsCross, sign, sub, transformCoords, translate, unionBox };
333
+ export { type Box, type CubicCoords, type CurveNearest, DEFAULT_FLATTEN_TOLERANCE, EPS, type LineCoords, type Mat3, PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_Z, type PathCommandCode, type PathCommandName, type PathNearest, type PlaceRectOptions, type PlacedRect, type Placement, type PlacementAlign, type PlacementSide, type QuadraticCoords, type Rect, applyToPoint, approxEq, boundsOfCoords, boxContainsPoint, boxToBox, clampRectWithin, cross, cubicBounds, cubicEvalAt, dot, elevateQuadraticToCubic, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, forEachSegment, identity, invert, len2, multiply, nearestOnCubic, nearestOnLine, nearestOnPath, nearestOnQuadratic, pathCommandCoordCount, placeRect, pointInPolygon, pointSegmentDist2, portControls, portCurvePoints, quadraticEvalAt, rectToContour, rotate, rotateAboutPoint, scale, segmentsCross, sign, splitCubicAt, splitLineAt, splitQuadraticAt, sub, transformCoords, translate, unionBox };
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
- export { DEFAULT_FLATTEN_TOLERANCE, PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_Z, cubicBounds, cubicEvalAt, elevateQuadraticToCubic, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, forEachSegment, pathCommandCoordCount } from './chunk-DQ6QRAWP.js';
1
+ import { cubicEvalAt, elevateQuadraticToCubic, forEachSegment, PATH_M, PATH_L, PATH_Q, PATH_C, PATH_Z } from './chunk-36DHVSOV.js';
2
+ export { DEFAULT_FLATTEN_TOLERANCE, PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_Z, cubicBounds, cubicEvalAt, elevateQuadraticToCubic, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, forEachSegment, pathCommandCoordCount, quadraticEvalAt, splitCubicAt, splitLineAt, splitQuadraticAt } from './chunk-36DHVSOV.js';
2
3
  import { PORT_REACH, SINGULAR_RATIO, portControls, cubicAt, sign, len2, dot } from './chunk-3GFNUO4N.js';
3
4
  export { EPS, PORT_REACH, approxEq, cross, dot, len2, sign, sub } from './chunk-3GFNUO4N.js';
4
5
 
@@ -78,6 +79,105 @@ function rectToContour(x, y, w, h) {
78
79
  return Float64Array.of(x, y, x + w, y, x + w, y + h, x, y + h);
79
80
  }
80
81
 
82
+ // src/nearest.ts
83
+ function nearestOnLine(px, py, x0, y0, x1, y1) {
84
+ const vx = x1 - x0, vy = y1 - y0;
85
+ const vv = vx * vx + vy * vy;
86
+ let t = vv === 0 ? 0 : ((px - x0) * vx + (py - y0) * vy) / vv;
87
+ t = t < 0 ? 0 : t > 1 ? 1 : t;
88
+ const x = t === 1 ? x1 : x0 + t * vx;
89
+ const y = t === 1 ? y1 : y0 + t * vy;
90
+ return { x, y, t, dist: Math.hypot(px - x, py - y) };
91
+ }
92
+ var CUBIC_SAMPLES = 32;
93
+ var REFINE_ITERS = 40;
94
+ var T_EPS = 1e-14;
95
+ function nearestOnCubic(px, py, x0, y0, x1, y1, x2, y2, x3, y3) {
96
+ const ax = -x0 + 3 * x1 - 3 * x2 + x3, ay = -y0 + 3 * y1 - 3 * y2 + y3;
97
+ const bx = 3 * x0 - 6 * x1 + 3 * x2, by = 3 * y0 - 6 * y1 + 3 * y2;
98
+ const cx = 3 * (x1 - x0), cy = 3 * (y1 - y0);
99
+ const d2At = (t) => {
100
+ const [x4, y4] = cubicEvalAt(x0, y0, x1, y1, x2, y2, x3, y3, t);
101
+ return (x4 - px) ** 2 + (y4 - py) ** 2;
102
+ };
103
+ const d2s = [];
104
+ for (let k = 0; k <= CUBIC_SAMPLES; k++) d2s.push(d2At(k / CUBIC_SAMPLES));
105
+ let bestT = 0, bestD2 = d2s[0];
106
+ for (let k = 0; k <= CUBIC_SAMPLES; k++) {
107
+ const d = d2s[k];
108
+ const prev = k > 0 ? d2s[k - 1] : Infinity;
109
+ const next = k < CUBIC_SAMPLES ? d2s[k + 1] : Infinity;
110
+ if (!(d <= prev && d <= next)) continue;
111
+ let lo = Math.max(0, (k - 1) / CUBIC_SAMPLES);
112
+ let hi = Math.min(1, (k + 1) / CUBIC_SAMPLES);
113
+ let t = k / CUBIC_SAMPLES;
114
+ for (let i = 0; i < REFINE_ITERS; i++) {
115
+ const t2 = t * t;
116
+ const ex = ax * t2 * t + bx * t2 + cx * t + x0 - px;
117
+ const ey = ay * t2 * t + by * t2 + cy * t + y0 - py;
118
+ const dx = 3 * ax * t2 + 2 * bx * t + cx, dy = 3 * ay * t2 + 2 * by * t + cy;
119
+ const ddx = 6 * ax * t + 2 * bx, ddy = 6 * ay * t + 2 * by;
120
+ const g = ex * dx + ey * dy;
121
+ const gp = dx * dx + dy * dy + ex * ddx + ey * ddy;
122
+ if (g > 0) hi = t;
123
+ else if (g < 0) lo = t;
124
+ else break;
125
+ let tn = gp > 0 ? t - g / gp : NaN;
126
+ if (!(tn > lo && tn < hi)) tn = (lo + hi) / 2;
127
+ const step = Math.abs(tn - t);
128
+ t = tn;
129
+ if (step < T_EPS || hi - lo < T_EPS) break;
130
+ }
131
+ const refined = d2At(t);
132
+ const [tk, dk] = refined <= d ? [t, refined] : [k / CUBIC_SAMPLES, d];
133
+ if (dk < bestD2) {
134
+ bestD2 = dk;
135
+ bestT = tk;
136
+ }
137
+ }
138
+ const [x, y] = cubicEvalAt(x0, y0, x1, y1, x2, y2, x3, y3, bestT);
139
+ return { x, y, t: bestT, dist: Math.hypot(x - px, y - py) };
140
+ }
141
+ function nearestOnQuadratic(px, py, x0, y0, x1, y1, x2, y2) {
142
+ const [c1x, c1y, c2x, c2y] = elevateQuadraticToCubic(x0, y0, x1, y1, x2, y2);
143
+ return nearestOnCubic(px, py, x0, y0, c1x, c1y, c2x, c2y, x2, y2);
144
+ }
145
+ function nearestOnPath(commands, coords, px, py) {
146
+ let best = null;
147
+ let startX = 0, startY = 0;
148
+ forEachSegment(commands, coords, (cmd, ci, x0, y0, commandIndex) => {
149
+ let hit;
150
+ if (cmd === PATH_M) {
151
+ startX = coords[ci];
152
+ startY = coords[ci + 1];
153
+ return;
154
+ } else if (cmd === PATH_L) {
155
+ hit = nearestOnLine(px, py, x0, y0, coords[ci], coords[ci + 1]);
156
+ } else if (cmd === PATH_Q) {
157
+ hit = nearestOnQuadratic(px, py, x0, y0, coords[ci], coords[ci + 1], coords[ci + 2], coords[ci + 3]);
158
+ } else if (cmd === PATH_C) {
159
+ hit = nearestOnCubic(
160
+ px,
161
+ py,
162
+ x0,
163
+ y0,
164
+ coords[ci],
165
+ coords[ci + 1],
166
+ coords[ci + 2],
167
+ coords[ci + 3],
168
+ coords[ci + 4],
169
+ coords[ci + 5]
170
+ );
171
+ } else if (cmd === PATH_Z) {
172
+ hit = nearestOnLine(px, py, x0, y0, startX, startY);
173
+ } else {
174
+ throw new Error(`nearestOnPath: unknown command code ${cmd}`);
175
+ }
176
+ if (best === null || hit.dist < best.dist) best = { ...hit, commandIndex, coordIndex: ci };
177
+ });
178
+ return best;
179
+ }
180
+
81
181
  // src/portCurve2.ts
82
182
  function portControls2(ax, ay, bx, by, outNormal, inNormal, reach = PORT_REACH) {
83
183
  const [c1, c2] = portControls([ax, ay], [bx, by], outNormal, inNormal, reach);
@@ -204,6 +304,6 @@ function placeRect(options) {
204
304
  return { rect: shiftAcross(rect, boundary, resolved.side, padding), placement: resolved };
205
305
  }
206
306
 
207
- export { applyToPoint, boundsOfCoords, boxContainsPoint, boxToBox, clampRectWithin, identity, invert, multiply, placeRect, pointInPolygon, pointSegmentDist2, portControls2 as portControls, portCurvePoints, rectToContour, rotate, rotateAboutPoint, scale, segmentsCross, transformCoords, translate, unionBox };
307
+ export { applyToPoint, boundsOfCoords, boxContainsPoint, boxToBox, clampRectWithin, identity, invert, multiply, nearestOnCubic, nearestOnLine, nearestOnPath, nearestOnQuadratic, placeRect, pointInPolygon, pointSegmentDist2, portControls2 as portControls, portCurvePoints, rectToContour, rotate, rotateAboutPoint, scale, segmentsCross, transformCoords, translate, unionBox };
208
308
  //# sourceMappingURL=index.js.map
209
309
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/mat3.ts","../src/box.ts","../src/portCurve2.ts","../src/polyline.ts","../src/affine.ts","../src/place.ts"],"names":["portControls"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * 2D affine transforms in canvas/DOMMatrix order: [a, b, c, d, e, f].\n * x' = a·x + c·y + e\n * y' = b·x + d·y + f\n * Represented as a readonly 6-tuple (f64). The affine tier of the kernel.\n *\n * Convention alignment: the renderer already has a `Mat3` in\n * `src/renderer/math/mat3.ts`. That one is a 9-element column-major\n * `Float32Array` (a full 3×3) shaped for `uniformMatrix3fv` — a deliberately\n * different *representation* for the WebGL upload path. Its *logical element\n * order* is identical to ours: `create(a, b, c, d, tx, ty)` maps\n * `x' = a·x + c·y + tx`, `y' = b·x + d·y + ty` (canvas/DOMMatrix a,b,c,d,e,f).\n * We keep the pure 6-tuple f64 form here (the kernel form); the 9-element f32\n * form stays a render-layer concern. No second logical convention is created.\n */\nimport { SINGULAR_RATIO } from './scalar';\n\nexport type Mat3 = readonly [number, number, number, number, number, number];\n\n/** The transform that leaves a point where it is. */\nexport function identity(): Mat3 {\n return [1, 0, 0, 1, 0, 0];\n}\n\n/** A pure translation by `(tx, ty)`. */\nexport function translate(tx: number, ty: number): Mat3 {\n return [1, 0, 0, 1, tx, ty];\n}\n\n/** A pure scale about the origin. Scale about another point by composing\n * translate → scale → inverse translate with `multiply`. */\nexport function scale(sx: number, sy: number): Mat3 {\n return [sx, 0, 0, sy, 0, 0];\n}\n\n/** A pure rotation about the origin, in radians, clockwise in canvas\n * coordinates (y down). */\nexport function rotate(rad: number): Mat3 {\n const c = Math.cos(rad);\n const s = Math.sin(rad);\n return [c, s, -s, c, 0, 0];\n}\n\n/** Compose: result applies `n` first, then `m` (m·n). */\nexport function multiply(m: Mat3, n: Mat3): Mat3 {\n return [\n m[0] * n[0] + m[2] * n[1],\n m[1] * n[0] + m[3] * n[1],\n m[0] * n[2] + m[2] * n[3],\n m[1] * n[2] + m[3] * n[3],\n m[0] * n[4] + m[2] * n[5] + m[4],\n m[1] * n[4] + m[3] * n[5] + m[5],\n ];\n}\n\n/** Inverse, or null when the matrix is singular, non-finite, or too\n * ill-conditioned to invert meaningfully at its own scale. */\nexport function invert(m: Mat3): Mat3 | null {\n const det = m[0] * m[3] - m[1] * m[2];\n // The determinant is an area, so it is judged against the squared column norms.\n const norm2 = Math.max(m[0] * m[0] + m[1] * m[1], m[2] * m[2] + m[3] * m[3]);\n // Negated so a non-finite determinant falls out as singular.\n if (!(Math.abs(det) > SINGULAR_RATIO * norm2)) return null;\n const id = 1 / det;\n const a = m[3] * id;\n const b = -m[1] * id;\n const c = -m[2] * id;\n const d = m[0] * id;\n return [a, b, c, d, -(m[4] * a + m[5] * c), -(m[4] * b + m[5] * d)];\n}\n\n/** Apply to a point, returning a tuple. Cold-path use; hot loops inline. */\nexport function applyToPoint(m: Mat3, x: number, y: number): [number, number] {\n return [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];\n}\n\n/** Affine that maps source box (sx,sy,sw,sh) onto destination box (dx,dy,dw,dh). */\nexport function boxToBox(\n sx: number, sy: number, sw: number, sh: number,\n dx: number, dy: number, dw: number, dh: number,\n): Mat3 {\n const kx = sw === 0 ? 1 : dw / sw;\n const ky = sh === 0 ? 1 : dh / sh;\n // translate(dx,dy) · scale(kx,ky) · translate(-sx,-sy)\n return [kx, 0, 0, ky, dx - sx * kx, dy - sy * ky];\n}\n\n/** Rotation by `rad` about pivot (cx,cy): translate(c)·rotate·translate(-c). */\nexport function rotateAboutPoint(cx: number, cy: number, rad: number): Mat3 {\n return multiply(translate(cx, cy), multiply(rotate(rad), translate(-cx, -cy)));\n}\n","/** 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/** 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","/**\n * The port-curve rule in the 2D kernel's currency: loose scalars, the way\n * `cubicEvalAt` and `applyToPoint` take them. The rule itself lives in\n * `./portCurve`, stated once over components, so this and `./3d` cannot drift.\n */\n\nimport { PORT_REACH, cubicAt as cubicAtN, portControls as portControlsN } from './portCurve';\n\nexport { PORT_REACH };\n\n/**\n * `[c1, c2]` for the cubic from `(ax, ay)` to `(bx, by)`.\n *\n * A null normal falls back to a lerp along the chord. See `./portCurve` for why\n * the two ends are not symmetric.\n */\nexport function portControls(\n ax: number,\n ay: number,\n bx: number,\n by: number,\n outNormal: readonly [number, number] | null | undefined,\n inNormal: readonly [number, number] | null | undefined,\n reach: number = PORT_REACH,\n): [[number, number], [number, number]] {\n const [c1, c2] = portControlsN([ax, ay], [bx, by], outNormal, inNormal, reach);\n return [\n [c1[0]!, c1[1]!],\n [c2[0]!, c2[1]!],\n ];\n}\n\n/** A port curve sampled into `samples` points, excluding its start. */\nexport function portCurvePoints(\n ax: number,\n ay: number,\n bx: number,\n by: number,\n outNormal: readonly [number, number] | null | undefined,\n inNormal: readonly [number, number] | null | undefined,\n samples: number,\n reach: number = PORT_REACH,\n): [number, number][] {\n const a = [ax, ay];\n const b = [bx, by];\n const [c1, c2] = portControlsN(a, b, outNormal, inNormal, reach);\n const out: [number, number][] = [];\n for (let s = 1; s <= samples; s++) {\n const p = cubicAtN(a, c1, c2, b, s / samples);\n out.push([p[0]!, p[1]!]);\n }\n return out;\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 { Mat3 } from './mat3';\n\n/**\n * Apply an affine to an interleaved coord stream, returning a fresh f64\n * buffer. Command codes are unaffected — for a Bezier the transformed control\n * points define the transformed curve exactly (affine invariance), so callers\n * pass `path.coords` straight through and keep `path.commands` as-is.\n */\nexport function transformCoords(coords: ArrayLike<number>, m: Mat3): Float64Array {\n const out = new Float64Array(coords.length);\n const a = m[0], b = m[1], c = m[2], d = m[3], e = m[4], f = m[5];\n for (let i = 0; i + 1 < coords.length; i += 2) {\n const x = coords[i], y = coords[i + 1];\n out[i] = a * x + c * y + e;\n out[i + 1] = b * x + d * y + f;\n }\n return out;\n}\n","import type { Rect } from './box';\n\n/** Which side of the anchor the overlay sits on. */\nexport type PlacementSide = 'top' | 'bottom' | 'left' | 'right';\n\n/** How the overlay lines up along the side it sits on. */\nexport type PlacementAlign = 'start' | 'center' | 'end';\n\n/** A side paired with an alignment along it. */\nexport interface Placement {\n side: PlacementSide;\n align: PlacementAlign;\n}\n\n/** Inputs to {@link placeRect}. All rects share one coordinate space. */\nexport interface PlaceRectOptions {\n anchor: Rect;\n overlay: { width: number; height: number };\n boundary: Rect;\n placement: Placement;\n /** Gap between anchor and overlay along the side axis. Default 0. */\n offset?: number;\n /** Shift along the alignment axis. Default 0. */\n crossOffset?: number;\n /** Minimum gap kept between the overlay and the boundary. Default 0. */\n padding?: number;\n /** Whether to try the opposite side when the preferred one lacks room. Default true. */\n flip?: boolean;\n}\n\n/** Where the overlay landed, and the placement that produced it. */\nexport interface PlacedRect {\n rect: Rect;\n placement: Placement;\n}\n\nfunction alignAlong(start: number, extent: number, size: number, align: PlacementAlign): number {\n if (align === 'start') return start;\n if (align === 'end') return start + extent - size;\n return start + (extent - size) / 2;\n}\n\nfunction positionOn(\n anchor: Rect,\n overlay: { width: number; height: number },\n placement: Placement,\n offset: number,\n crossOffset: number,\n): Rect {\n const { width, height } = overlay;\n const { side, align } = placement;\n if (side === 'top' || side === 'bottom') {\n const y = side === 'bottom' ? anchor.y + anchor.height + offset : anchor.y - offset - height;\n return { x: alignAlong(anchor.x, anchor.width, width, align) + crossOffset, y, width, height };\n }\n const x = side === 'right' ? anchor.x + anchor.width + offset : anchor.x - offset - width;\n return { x, y: alignAlong(anchor.y, anchor.height, height, align) + crossOffset, width, height };\n}\n\nfunction clampAxis(start: number, size: number, low: number, extent: number, padding: number): number {\n const min = low + padding;\n return Math.max(min, Math.min(start, min + extent - padding * 2 - size));\n}\n\n/**\n * Move `rect` the shortest distance that puts it inside `boundary`, keeping its\n * size. A rect too big to fit pins to the boundary's leading edge.\n */\nexport function clampRectWithin(rect: Rect, boundary: Rect, padding = 0): Rect {\n return {\n ...rect,\n x: clampAxis(rect.x, rect.width, boundary.x, boundary.width, padding),\n y: clampAxis(rect.y, rect.height, boundary.y, boundary.height, padding),\n };\n}\n\n/** Slide along the alignment axis until the overlay is inside. */\nfunction shiftAcross(rect: Rect, boundary: Rect, side: PlacementSide, padding: number): Rect {\n const vertical = side === 'top' || side === 'bottom';\n const size = vertical ? rect.width : rect.height;\n const low = (vertical ? boundary.x : boundary.y) + padding;\n const high = low + (vertical ? boundary.width : boundary.height) - padding * 2 - size;\n const placed = Math.max(low, Math.min(vertical ? rect.x : rect.y, high));\n return vertical ? { ...rect, x: placed } : { ...rect, y: placed };\n}\n\nconst OPPOSITE: Record<PlacementSide, PlacementSide> = {\n top: 'bottom',\n bottom: 'top',\n left: 'right',\n right: 'left',\n};\n\nfunction fitsAlongSide(rect: Rect, boundary: Rect, side: PlacementSide, padding: number): boolean {\n const vertical = side === 'top' || side === 'bottom';\n const start = vertical ? rect.y : rect.x;\n const end = start + (vertical ? rect.height : rect.width);\n const low = (vertical ? boundary.y : boundary.x) + padding;\n const high = low + (vertical ? boundary.height : boundary.width) - padding * 2;\n return start >= low && end <= high;\n}\n\nexport function placeRect(options: PlaceRectOptions): PlacedRect {\n const { anchor, overlay, boundary, placement, offset = 0, crossOffset = 0 } = options;\n const { padding = 0, flip = true } = options;\n\n let resolved = placement;\n let rect = positionOn(anchor, overlay, resolved, offset, crossOffset);\n\n if (flip && !fitsAlongSide(rect, boundary, resolved.side, padding)) {\n const opposite = { side: OPPOSITE[resolved.side], align: resolved.align };\n const flipped = positionOn(anchor, overlay, opposite, offset, crossOffset);\n if (fitsAlongSide(flipped, boundary, opposite.side, padding)) {\n resolved = opposite;\n rect = flipped;\n }\n }\n\n return { rect: shiftAcross(rect, boundary, resolved.side, padding), placement: resolved };\n}\n"]}
1
+ {"version":3,"sources":["../src/mat3.ts","../src/box.ts","../src/nearest.ts","../src/portCurve2.ts","../src/polyline.ts","../src/affine.ts","../src/place.ts"],"names":["x","y","portControls"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * 2D affine transforms in canvas/DOMMatrix order: [a, b, c, d, e, f].\n * x' = a·x + c·y + e\n * y' = b·x + d·y + f\n * Represented as a readonly 6-tuple (f64). The affine tier of the kernel.\n *\n * Convention alignment: the renderer already has a `Mat3` in\n * `src/renderer/math/mat3.ts`. That one is a 9-element column-major\n * `Float32Array` (a full 3×3) shaped for `uniformMatrix3fv` — a deliberately\n * different *representation* for the WebGL upload path. Its *logical element\n * order* is identical to ours: `create(a, b, c, d, tx, ty)` maps\n * `x' = a·x + c·y + tx`, `y' = b·x + d·y + ty` (canvas/DOMMatrix a,b,c,d,e,f).\n * We keep the pure 6-tuple f64 form here (the kernel form); the 9-element f32\n * form stays a render-layer concern. No second logical convention is created.\n */\nimport { SINGULAR_RATIO } from './scalar';\n\nexport type Mat3 = readonly [number, number, number, number, number, number];\n\n/** The transform that leaves a point where it is. */\nexport function identity(): Mat3 {\n return [1, 0, 0, 1, 0, 0];\n}\n\n/** A pure translation by `(tx, ty)`. */\nexport function translate(tx: number, ty: number): Mat3 {\n return [1, 0, 0, 1, tx, ty];\n}\n\n/** A pure scale about the origin. Scale about another point by composing\n * translate → scale → inverse translate with `multiply`. */\nexport function scale(sx: number, sy: number): Mat3 {\n return [sx, 0, 0, sy, 0, 0];\n}\n\n/** A pure rotation about the origin, in radians, clockwise in canvas\n * coordinates (y down). */\nexport function rotate(rad: number): Mat3 {\n const c = Math.cos(rad);\n const s = Math.sin(rad);\n return [c, s, -s, c, 0, 0];\n}\n\n/** Compose: result applies `n` first, then `m` (m·n). */\nexport function multiply(m: Mat3, n: Mat3): Mat3 {\n return [\n m[0] * n[0] + m[2] * n[1],\n m[1] * n[0] + m[3] * n[1],\n m[0] * n[2] + m[2] * n[3],\n m[1] * n[2] + m[3] * n[3],\n m[0] * n[4] + m[2] * n[5] + m[4],\n m[1] * n[4] + m[3] * n[5] + m[5],\n ];\n}\n\n/** Inverse, or null when the matrix is singular, non-finite, or too\n * ill-conditioned to invert meaningfully at its own scale. */\nexport function invert(m: Mat3): Mat3 | null {\n const det = m[0] * m[3] - m[1] * m[2];\n // The determinant is an area, so it is judged against the squared column norms.\n const norm2 = Math.max(m[0] * m[0] + m[1] * m[1], m[2] * m[2] + m[3] * m[3]);\n // Negated so a non-finite determinant falls out as singular.\n if (!(Math.abs(det) > SINGULAR_RATIO * norm2)) return null;\n const id = 1 / det;\n const a = m[3] * id;\n const b = -m[1] * id;\n const c = -m[2] * id;\n const d = m[0] * id;\n return [a, b, c, d, -(m[4] * a + m[5] * c), -(m[4] * b + m[5] * d)];\n}\n\n/** Apply to a point, returning a tuple. Cold-path use; hot loops inline. */\nexport function applyToPoint(m: Mat3, x: number, y: number): [number, number] {\n return [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];\n}\n\n/** Affine that maps source box (sx,sy,sw,sh) onto destination box (dx,dy,dw,dh). */\nexport function boxToBox(\n sx: number, sy: number, sw: number, sh: number,\n dx: number, dy: number, dw: number, dh: number,\n): Mat3 {\n const kx = sw === 0 ? 1 : dw / sw;\n const ky = sh === 0 ? 1 : dh / sh;\n // translate(dx,dy) · scale(kx,ky) · translate(-sx,-sy)\n return [kx, 0, 0, ky, dx - sx * kx, dy - sy * ky];\n}\n\n/** Rotation by `rad` about pivot (cx,cy): translate(c)·rotate·translate(-c). */\nexport function rotateAboutPoint(cx: number, cy: number, rad: number): Mat3 {\n return multiply(translate(cx, cy), multiply(rotate(rad), translate(-cx, -cy)));\n}\n","/** 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/** 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","/**\n * Nearest point on a segment or a whole path to a probe point: where it is,\n * its curve parameter, and how far away it lies.\n */\nimport { cubicEvalAt, elevateQuadraticToCubic } from './curve';\nimport { forEachSegment, PATH_M, PATH_L, PATH_Q, PATH_C, PATH_Z } from './commands';\n\n/** The point on one segment nearest a probe. */\nexport interface CurveNearest {\n x: number;\n y: number;\n /** Curve parameter of the point, in [0, 1]. */\n t: number;\n /** Euclidean distance from the probe. */\n dist: number;\n}\n\n/** The point on a path nearest a probe, and the command whose segment holds it. */\nexport interface PathNearest extends CurveNearest {\n /** Index of the segment's command in the command stream (`L`, `Q`, `C` or `Z`). */\n commandIndex: number;\n /** Offset of that command's first coord; for a `Z`, where its coords would begin. */\n coordIndex: number;\n}\n\n/** Nearest point on segment (x0,y0)-(x1,y1) to (px,py). */\nexport function nearestOnLine(\n px: number, py: number, x0: number, y0: number, x1: number, y1: number,\n): CurveNearest {\n const vx = x1 - x0, vy = y1 - y0;\n const vv = vx * vx + vy * vy;\n let t = vv === 0 ? 0 : ((px - x0) * vx + (py - y0) * vy) / vv;\n t = t < 0 ? 0 : t > 1 ? 1 : t;\n const x = t === 1 ? x1 : x0 + t * vx;\n const y = t === 1 ? y1 : y0 + t * vy;\n return { x, y, t, dist: Math.hypot(px - x, py - y) };\n}\n\n/** Coarse samples per cubic. Each local minimum among them is refined, so this\n * only has to separate the distance function's minima (a cubic has at most\n * three), not locate them. */\nconst CUBIC_SAMPLES = 32;\nconst REFINE_ITERS = 40;\nconst T_EPS = 1e-14;\n\n/**\n * Nearest point on the cubic (x0,y0)…(x3,y3) to (px,py). Samples the curve,\n * then refines every sampled local minimum with bracketed Newton on the\n * distance derivative, so a loop or cusp cannot capture it in the wrong basin.\n */\nexport function nearestOnCubic(\n px: number, py: number,\n x0: number, y0: number, x1: number, y1: number,\n x2: number, y2: number, x3: number, y3: number,\n): CurveNearest {\n // Power basis B(t) = a t³ + b t² + c t + p0, for the derivatives.\n const ax = -x0 + 3 * x1 - 3 * x2 + x3, ay = -y0 + 3 * y1 - 3 * y2 + y3;\n const bx = 3 * x0 - 6 * x1 + 3 * x2, by = 3 * y0 - 6 * y1 + 3 * y2;\n const cx = 3 * (x1 - x0), cy = 3 * (y1 - y0);\n\n const d2At = (t: number): number => {\n const [x, y] = cubicEvalAt(x0, y0, x1, y1, x2, y2, x3, y3, t);\n return (x - px) ** 2 + (y - py) ** 2;\n };\n\n const d2s: number[] = [];\n for (let k = 0; k <= CUBIC_SAMPLES; k++) d2s.push(d2At(k / CUBIC_SAMPLES));\n\n let bestT = 0, bestD2 = d2s[0];\n for (let k = 0; k <= CUBIC_SAMPLES; k++) {\n const d = d2s[k];\n const prev = k > 0 ? d2s[k - 1] : Infinity;\n const next = k < CUBIC_SAMPLES ? d2s[k + 1] : Infinity;\n if (!(d <= prev && d <= next)) continue;\n\n let lo = Math.max(0, (k - 1) / CUBIC_SAMPLES);\n let hi = Math.min(1, (k + 1) / CUBIC_SAMPLES);\n let t = k / CUBIC_SAMPLES;\n for (let i = 0; i < REFINE_ITERS; i++) {\n const t2 = t * t;\n const ex = ax * t2 * t + bx * t2 + cx * t + x0 - px;\n const ey = ay * t2 * t + by * t2 + cy * t + y0 - py;\n const dx = 3 * ax * t2 + 2 * bx * t + cx, dy = 3 * ay * t2 + 2 * by * t + cy;\n const ddx = 6 * ax * t + 2 * bx, ddy = 6 * ay * t + 2 * by;\n // g = ½ d/dt |B - P|², zero at a critical point; its sign says which side the minimum is on.\n const g = ex * dx + ey * dy;\n const gp = dx * dx + dy * dy + ex * ddx + ey * ddy;\n if (g > 0) hi = t; else if (g < 0) lo = t; else break;\n let tn = gp > 0 ? t - g / gp : NaN;\n if (!(tn > lo && tn < hi)) tn = (lo + hi) / 2;\n const step = Math.abs(tn - t);\n t = tn;\n if (step < T_EPS || hi - lo < T_EPS) break;\n }\n const refined = d2At(t);\n const [tk, dk] = refined <= d ? [t, refined] : [k / CUBIC_SAMPLES, d];\n if (dk < bestD2) { bestD2 = dk; bestT = tk; }\n }\n\n const [x, y] = cubicEvalAt(x0, y0, x1, y1, x2, y2, x3, y3, bestT);\n return { x, y, t: bestT, dist: Math.hypot(x - px, y - py) };\n}\n\n/** Nearest point on the quadratic (x0,y0)(x1,y1)(x2,y2) to (px,py). */\nexport function nearestOnQuadratic(\n px: number, py: number,\n x0: number, y0: number, x1: number, y1: number, x2: number, y2: number,\n): CurveNearest {\n // Degree elevation keeps the parameterization, so t carries over unchanged.\n const [c1x, c1y, c2x, c2y] = elevateQuadraticToCubic(x0, y0, x1, y1, x2, y2);\n return nearestOnCubic(px, py, x0, y0, c1x, c1y, c2x, c2y, x2, y2);\n}\n\n/**\n * Nearest point on a command-stream path to (px,py), over every `L`, `Q`, `C`\n * and the closing edge each `Z` draws. The earliest segment wins a tie.\n * Returns `null` when the path has no segment, and throws on a command code\n * `PATH_COMMANDS` does not declare.\n */\nexport function nearestOnPath(\n commands: ArrayLike<number>,\n coords: ArrayLike<number>,\n px: number,\n py: number,\n): PathNearest | null {\n let best: PathNearest | null = null;\n let startX = 0, startY = 0;\n forEachSegment(commands, coords, (cmd, ci, x0, y0, commandIndex) => {\n let hit: CurveNearest;\n if (cmd === PATH_M) {\n startX = coords[ci]; startY = coords[ci + 1];\n return;\n } else if (cmd === PATH_L) {\n hit = nearestOnLine(px, py, x0, y0, coords[ci], coords[ci + 1]);\n } else if (cmd === PATH_Q) {\n hit = nearestOnQuadratic(px, py, x0, y0, coords[ci], coords[ci + 1], coords[ci + 2], coords[ci + 3]);\n } else if (cmd === PATH_C) {\n hit = nearestOnCubic(\n px, py, x0, y0,\n coords[ci], coords[ci + 1], coords[ci + 2], coords[ci + 3], coords[ci + 4], coords[ci + 5],\n );\n } else if (cmd === PATH_Z) {\n hit = nearestOnLine(px, py, x0, y0, startX, startY);\n } else {\n throw new Error(`nearestOnPath: unknown command code ${cmd}`);\n }\n if (best === null || hit.dist < best.dist) best = { ...hit, commandIndex, coordIndex: ci };\n });\n return best;\n}\n","/**\n * The port-curve rule in the 2D kernel's currency: loose scalars, the way\n * `cubicEvalAt` and `applyToPoint` take them. The rule itself lives in\n * `./portCurve`, stated once over components, so this and `./3d` cannot drift.\n */\n\nimport { PORT_REACH, cubicAt as cubicAtN, portControls as portControlsN } from './portCurve';\n\nexport { PORT_REACH };\n\n/**\n * `[c1, c2]` for the cubic from `(ax, ay)` to `(bx, by)`.\n *\n * A null normal falls back to a lerp along the chord. See `./portCurve` for why\n * the two ends are not symmetric.\n */\nexport function portControls(\n ax: number,\n ay: number,\n bx: number,\n by: number,\n outNormal: readonly [number, number] | null | undefined,\n inNormal: readonly [number, number] | null | undefined,\n reach: number = PORT_REACH,\n): [[number, number], [number, number]] {\n const [c1, c2] = portControlsN([ax, ay], [bx, by], outNormal, inNormal, reach);\n return [\n [c1[0]!, c1[1]!],\n [c2[0]!, c2[1]!],\n ];\n}\n\n/** A port curve sampled into `samples` points, excluding its start. */\nexport function portCurvePoints(\n ax: number,\n ay: number,\n bx: number,\n by: number,\n outNormal: readonly [number, number] | null | undefined,\n inNormal: readonly [number, number] | null | undefined,\n samples: number,\n reach: number = PORT_REACH,\n): [number, number][] {\n const a = [ax, ay];\n const b = [bx, by];\n const [c1, c2] = portControlsN(a, b, outNormal, inNormal, reach);\n const out: [number, number][] = [];\n for (let s = 1; s <= samples; s++) {\n const p = cubicAtN(a, c1, c2, b, s / samples);\n out.push([p[0]!, p[1]!]);\n }\n return out;\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 { Mat3 } from './mat3';\n\n/**\n * Apply an affine to an interleaved coord stream, returning a fresh f64\n * buffer. Command codes are unaffected — for a Bezier the transformed control\n * points define the transformed curve exactly (affine invariance), so callers\n * pass `path.coords` straight through and keep `path.commands` as-is.\n */\nexport function transformCoords(coords: ArrayLike<number>, m: Mat3): Float64Array {\n const out = new Float64Array(coords.length);\n const a = m[0], b = m[1], c = m[2], d = m[3], e = m[4], f = m[5];\n for (let i = 0; i + 1 < coords.length; i += 2) {\n const x = coords[i], y = coords[i + 1];\n out[i] = a * x + c * y + e;\n out[i + 1] = b * x + d * y + f;\n }\n return out;\n}\n","import type { Rect } from './box';\n\n/** Which side of the anchor the overlay sits on. */\nexport type PlacementSide = 'top' | 'bottom' | 'left' | 'right';\n\n/** How the overlay lines up along the side it sits on. */\nexport type PlacementAlign = 'start' | 'center' | 'end';\n\n/** A side paired with an alignment along it. */\nexport interface Placement {\n side: PlacementSide;\n align: PlacementAlign;\n}\n\n/** Inputs to {@link placeRect}. All rects share one coordinate space. */\nexport interface PlaceRectOptions {\n anchor: Rect;\n overlay: { width: number; height: number };\n boundary: Rect;\n placement: Placement;\n /** Gap between anchor and overlay along the side axis. Default 0. */\n offset?: number;\n /** Shift along the alignment axis. Default 0. */\n crossOffset?: number;\n /** Minimum gap kept between the overlay and the boundary. Default 0. */\n padding?: number;\n /** Whether to try the opposite side when the preferred one lacks room. Default true. */\n flip?: boolean;\n}\n\n/** Where the overlay landed, and the placement that produced it. */\nexport interface PlacedRect {\n rect: Rect;\n placement: Placement;\n}\n\nfunction alignAlong(start: number, extent: number, size: number, align: PlacementAlign): number {\n if (align === 'start') return start;\n if (align === 'end') return start + extent - size;\n return start + (extent - size) / 2;\n}\n\nfunction positionOn(\n anchor: Rect,\n overlay: { width: number; height: number },\n placement: Placement,\n offset: number,\n crossOffset: number,\n): Rect {\n const { width, height } = overlay;\n const { side, align } = placement;\n if (side === 'top' || side === 'bottom') {\n const y = side === 'bottom' ? anchor.y + anchor.height + offset : anchor.y - offset - height;\n return { x: alignAlong(anchor.x, anchor.width, width, align) + crossOffset, y, width, height };\n }\n const x = side === 'right' ? anchor.x + anchor.width + offset : anchor.x - offset - width;\n return { x, y: alignAlong(anchor.y, anchor.height, height, align) + crossOffset, width, height };\n}\n\nfunction clampAxis(start: number, size: number, low: number, extent: number, padding: number): number {\n const min = low + padding;\n return Math.max(min, Math.min(start, min + extent - padding * 2 - size));\n}\n\n/**\n * Move `rect` the shortest distance that puts it inside `boundary`, keeping its\n * size. A rect too big to fit pins to the boundary's leading edge.\n */\nexport function clampRectWithin(rect: Rect, boundary: Rect, padding = 0): Rect {\n return {\n ...rect,\n x: clampAxis(rect.x, rect.width, boundary.x, boundary.width, padding),\n y: clampAxis(rect.y, rect.height, boundary.y, boundary.height, padding),\n };\n}\n\n/** Slide along the alignment axis until the overlay is inside. */\nfunction shiftAcross(rect: Rect, boundary: Rect, side: PlacementSide, padding: number): Rect {\n const vertical = side === 'top' || side === 'bottom';\n const size = vertical ? rect.width : rect.height;\n const low = (vertical ? boundary.x : boundary.y) + padding;\n const high = low + (vertical ? boundary.width : boundary.height) - padding * 2 - size;\n const placed = Math.max(low, Math.min(vertical ? rect.x : rect.y, high));\n return vertical ? { ...rect, x: placed } : { ...rect, y: placed };\n}\n\nconst OPPOSITE: Record<PlacementSide, PlacementSide> = {\n top: 'bottom',\n bottom: 'top',\n left: 'right',\n right: 'left',\n};\n\nfunction fitsAlongSide(rect: Rect, boundary: Rect, side: PlacementSide, padding: number): boolean {\n const vertical = side === 'top' || side === 'bottom';\n const start = vertical ? rect.y : rect.x;\n const end = start + (vertical ? rect.height : rect.width);\n const low = (vertical ? boundary.y : boundary.x) + padding;\n const high = low + (vertical ? boundary.height : boundary.width) - padding * 2;\n return start >= low && end <= high;\n}\n\nexport function placeRect(options: PlaceRectOptions): PlacedRect {\n const { anchor, overlay, boundary, placement, offset = 0, crossOffset = 0 } = options;\n const { padding = 0, flip = true } = options;\n\n let resolved = placement;\n let rect = positionOn(anchor, overlay, resolved, offset, crossOffset);\n\n if (flip && !fitsAlongSide(rect, boundary, resolved.side, padding)) {\n const opposite = { side: OPPOSITE[resolved.side], align: resolved.align };\n const flipped = positionOn(anchor, overlay, opposite, offset, crossOffset);\n if (fitsAlongSide(flipped, boundary, opposite.side, padding)) {\n resolved = opposite;\n rect = flipped;\n }\n }\n\n return { rect: shiftAcross(rect, boundary, resolved.side, padding), placement: resolved };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weasel-js/geom",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "Pure geometry kernel for @weasel-js/core: affine, box, curve, polyline in 2D. Dependency-free core; polygon booleans in the ./booleans subpath, vectors, quaternions, 4x4 matrices and ray intersection in ./3d.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands.ts","../src/curve.ts","../src/flatten.ts"],"names":[],"mappings":"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","file":"chunk-DQ6QRAWP.js","sourcesContent":["/**\n * SVG-style command-stream encoding — the kit's single declaration of the path\n * opcodes. `Path` in @weasel-js/core wraps this with `kind` + `fillRule`.\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. Derive, never restate.\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\nexport const PATH_M = PATH_COMMANDS.M.code;\nexport const PATH_L = PATH_COMMANDS.L.code;\nexport const PATH_C = PATH_COMMANDS.C.code;\nexport const PATH_Q = PATH_COMMANDS.Q.code;\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 receives\n * (cmd, coordIndex, penX, penY, commandIndex) and stops the walk by returning\n * `false`. The pen advances to the command's last coord pair afterward; `Z`\n * returns it to the subpath's opening `M`, so a command following a `Z`\n * without an intervening `M` starts where SVG says it does.\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 ) => void | boolean,\n): void {\n let ci = 0;\n let px = 0, py = 0;\n let startX = 0, startY = 0;\n for (let i = 0; i < commands.length; i++) {\n const cmd = commands[i];\n if (visit(cmd, ci, px, py, i) === false) return;\n const len = pathCommandCoordCount(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","import type { Box } from './box';\n\n/** Cubic Bezier point at parameter t (de Casteljau / Bernstein form). */\nexport function cubicEvalAt(\n x0: number, y0: number, x1: number, y1: number,\n x2: number, y2: number, x3: number, y3: number, t: number,\n): [number, number] {\n const u = 1 - t;\n const a = u * u * u, b = 3 * u * u * t, c = 3 * u * t * t, d = t * t * t;\n return [\n a * x0 + b * x1 + c * x2 + d * x3,\n a * y0 + b * y1 + c * y2 + d * y3,\n ];\n}\n\n/**\n * Degree-elevate a quadratic (q0, ctrl, q1) to a cubic. Returns the two\n * cubic control points [c1x, c1y, c2x, c2y]; the cubic endpoints equal the\n * quadratic endpoints. c1 = q0 + 2/3(ctrl-q0), c2 = q1 + 2/3(ctrl-q1).\n */\nexport function elevateQuadraticToCubic(\n q0x: number, q0y: number, cx: number, cy: number, q1x: number, q1y: number,\n): [number, number, number, number] {\n return [\n q0x + (2 / 3) * (cx - q0x),\n q0y + (2 / 3) * (cy - q0y),\n q1x + (2 / 3) * (cx - q1x),\n q1y + (2 / 3) * (cy - q1y),\n ];\n}\n\n/** Axis-aligned extrema parameters of one cubic component (the 0,1 ends plus\n * any derivative roots in (0,1)). Used by cubicBounds. */\nfunction componentExtremaTs(p0: number, p1: number, p2: number, p3: number): number[] {\n // B'(t)=0 → quadratic a t² + b t + c = 0 with:\n const a = -p0 + 3 * p1 - 3 * p2 + p3;\n const b = 2 * (p0 - 2 * p1 + p2);\n const c = -p0 + p1;\n const ts: number[] = [];\n const push = (t: number) => { if (t > 0 && t < 1) ts.push(t); };\n if (Math.abs(a) < 1e-12) {\n if (Math.abs(b) > 1e-12) push(-c / b);\n } else {\n const disc = b * b - 4 * a * c;\n if (disc >= 0) {\n const sq = Math.sqrt(disc);\n push((-b + sq) / (2 * a));\n push((-b - sq) / (2 * a));\n }\n }\n return ts;\n}\n\n/** Tight AABB of a cubic, evaluating only extrema that lie on the curve. */\nexport function cubicBounds(\n x0: number, y0: number, x1: number, y1: number,\n x2: number, y2: number, x3: number, y3: number,\n): Box {\n let minX = Math.min(x0, x3), maxX = Math.max(x0, x3);\n let minY = Math.min(y0, y3), maxY = Math.max(y0, y3);\n for (const t of componentExtremaTs(x0, x1, x2, x3)) {\n const [ex] = cubicEvalAt(x0, y0, x1, y1, x2, y2, x3, y3, t);\n if (ex < minX) minX = ex;\n if (ex > maxX) maxX = ex;\n }\n for (const t of componentExtremaTs(y0, y1, y2, y3)) {\n const [, ey] = cubicEvalAt(x0, y0, x1, y1, x2, y2, x3, y3, t);\n if (ey < minY) minY = ey;\n if (ey > maxY) maxY = ey;\n }\n return [minX, minY, maxX, maxY];\n}\n","/**\n * Bezier flattening — subdivide cubic and quadratic segments into polyline\n * approximations within a flatness tolerance. Used by hit-testing and\n * (eventually) any kernel that doesn't want to special-case curves.\n *\n * The flatness metric is the maximum perpendicular distance from any\n * control point to the chord between endpoints. When that distance falls\n * below `tolerance`, the segment is \"flat enough\" and emitted as a single\n * line segment.\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/** Distance from point P to line AB (perpendicular). */\nfunction distPointToLine(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 if (len2 === 0) {\n const ex = px - ax;\n const ey = py - ay;\n return Math.sqrt(ex * ex + ey * ey);\n }\n const cross = (px - ax) * dy - (py - ay) * dx;\n return Math.abs(cross) / 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 = distPointToLine(x1, y1, x0, y0, x3, y3);\n const d2 = distPointToLine(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 = distPointToLine(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, for each new flattened point, its\n * arc-length fraction `t` (relative to the polyline distance accumulated so\n * far inside this curve) to `arcOut`. Caller then post-processes the segment's\n * `arcOut` range by dividing each by the segment's total flattened arc length\n * to yield t ∈ (0, 1].\n *\n * The returned values are *cumulative distance from the segment start*, not\n * normalized fractions. Two-pass design (accumulate, then divide) keeps the\n * recursive splitter simple — it doesn't need to know the total length up\n * front.\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 = distPointToLine(x1, y1, x0, y0, x3, y3);\n const d2 = distPointToLine(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 = distPointToLine(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"]}