@weasel-js/geom 1.9.4 → 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.
@@ -5,32 +5,31 @@
5
5
  *
6
6
  * Storage: command codes in a `Uint8Array`, parameters in a `Float32Array`.
7
7
  * Each command consumes a fixed number of coords (`PATH_CMD_LENGTHS`); walkers
8
- * step both arrays in lockstep, which keeps hot loops monomorphic and GC
9
- * pressure low under heavy edits.
10
- *
11
- * `RectPath` is split out at the type level so common-case machinery
12
- * (selection AABBs, area-select, rect hit-testing) can short-circuit without
13
- * the polygon kernel. Polymorphic kernels take the `Path` union and dispatch
14
- * on `kind`.
8
+ * step both arrays in lockstep.
15
9
  */
16
10
  /** Fill rule used by polygon path hit-testing and `ctx.fill()`. */
17
11
  type PathFillRule = 'nonzero' | 'evenodd';
12
+ /** Whether a fill closes an open subpath with a straight edge back to its
13
+ * start, as SVG and canvas do (`'close'`), or leaves it unfilled (`'none'`). */
14
+ type PathOpenFill = 'close' | 'none';
18
15
  /**
19
16
  * Polygon path with arbitrary contours and optional bezier segments.
20
17
  * Multi-contour: each `M` opens a new subpath; `Z` closes the current one.
21
- * Open subpaths (no `Z`) render as polylines and don't contribute to fills.
18
+ * An open subpath (no `Z`) strokes as a polyline; `openFill` says whether it
19
+ * fills.
22
20
  */
23
21
  interface PolygonPath {
24
22
  kind: 'polygon';
25
23
  commands: Uint8Array;
26
24
  coords: Float32Array;
27
25
  fillRule: PathFillRule;
26
+ /** Absent, the engine default: see `setDefaultOpenFill`. */
27
+ openFill?: PathOpenFill;
28
28
  }
29
29
  /**
30
30
  * Axis-aligned rectangle. Fast path for the (very common) case where the
31
31
  * shape is just a rect — preserves O(1) bounds and hit-test, avoids the
32
- * polygon kernel entirely. Promote to `PolygonPath` only when the shape
33
- * grows beyond what a rect can express.
32
+ * polygon kernel entirely.
34
33
  */
35
34
  interface RectPath {
36
35
  kind: 'rect';
@@ -42,4 +41,4 @@ interface RectPath {
42
41
  /** Canonical path shape — either an axis-aligned rect (fast path) or a polygon command stream. */
43
42
  type Path = PolygonPath | RectPath;
44
43
 
45
- export type { Path as P, RectPath as R, PolygonPath as a, PathFillRule as b };
44
+ export type { PolygonPath as P, RectPath as R, Path as a, PathOpenFill as b, PathFillRule as c };
@@ -1,24 +1,20 @@
1
- import { P as Path } from '../path-D0CoudGM.js';
1
+ import { a as Path } from '../path-Bf9KeVxC.js';
2
2
 
3
3
  /**
4
4
  * A tessellated representation of a Path, ready to upload to GL.
5
5
  *
6
- * - `vertices` is interleaved x,y in path-local coordinates (`Float32Array`
7
- * of length `2 * vertexCount`).
8
- * - `indices` are triangle indices into `vertices` (`Uint32Array`, length
9
- * `3 * triangleCount`).
10
- * - `requiresStencil` is set for paths whose fillRule is `'evenodd'` and
11
- * whose triangulation is a *naive* per-contour fan rather than a clean
6
+ * - `vertices` is interleaved x,y in path-local coordinates.
7
+ * - `indices` are triangle indices into `vertices`.
8
+ * - `requiresStencil` is set for paths whose fillRule is `'evenodd'`, whose
9
+ * triangulation is a *naive* per-contour fan rather than a clean
12
10
  * inside/outside triangulation. The renderer must use a stencil
13
- * two-pass when this flag is true. Single-contour paths and `'nonzero'`
14
- * multi-contour paths leave it false.
11
+ * two-pass when this flag is true.
15
12
  * - `anchorA` / `anchorB` / `anchorT` parameterize each mesh vertex by
16
13
  * the two consecutive path anchors it lies between and the arc-length
17
14
  * fraction along that segment (0 = at A, 1 = at B). Vertices that fall
18
15
  * exactly on an anchor set A === B and t = 0. Used at draw time when
19
- * the DrawCommand supplies per-anchor colors so the renderer can lerp
20
- * per mesh vertex. Optional — emitted by the path tessellators; absent
21
- * on meshes built by other paths (e.g. text glyphs).
16
+ * the DrawCommand supplies per-anchor colors. Optional — emitted by the
17
+ * path tessellators.
22
18
  */
23
19
  interface Mesh {
24
20
  readonly vertices: Float32Array;
@@ -1,8 +1,8 @@
1
- import { rectToContour } from '../chunk-NL423YYZ.js';
2
- export { extractPolylines } from '../chunk-NL423YYZ.js';
3
- import { DEFAULT_FLATTEN_TOLERANCE, pointInPolygon, flattenCubicWithArcLen, flattenQuadraticWithArcLen } from '../chunk-X6GJRIQD.js';
4
- import '../chunk-N5SYTHMR.js';
5
- import { forEachSegment, PATH_Z, PATH_C, PATH_Q, PATH_L, PATH_M } from '../chunk-E4TJRGJD.js';
1
+ import { rectToContour } from '../chunk-MDT7F32A.js';
2
+ export { extractPolylines } from '../chunk-MDT7F32A.js';
3
+ import { DEFAULT_FLATTEN_TOLERANCE, pointInPolygon, fillsOpenSubpaths, flattenCubicWithArcLen, flattenQuadraticWithArcLen } from '../chunk-WQMYOCFB.js';
4
+ import '../chunk-755Y4YZS.js';
5
+ import { forEachSegment, PATH_Z, PATH_C, PATH_Q, PATH_L, PATH_M } from '../chunk-OXH3NOXC.js';
6
6
  import earcut from 'earcut';
7
7
 
8
8
  function tessellate(path, opts = {}) {
@@ -20,6 +20,22 @@ function tessellateRect(p) {
20
20
  };
21
21
  }
22
22
  function flattenPolygon(p, tolerance) {
23
+ const closed = /* @__PURE__ */ new Set();
24
+ const all = flattenContours(p, tolerance, closed);
25
+ if (fillsOpenSubpaths(p)) return all;
26
+ const kept = { coords: [], contourStarts: [], anchorA: [], anchorB: [], anchorT: [] };
27
+ all.contourStarts.forEach((start, c) => {
28
+ if (!closed.has(c)) return;
29
+ const end = c + 1 < all.contourStarts.length ? all.contourStarts[c + 1] : all.coords.length / 2;
30
+ kept.contourStarts.push(kept.coords.length / 2);
31
+ kept.coords.push(...all.coords.slice(start * 2, end * 2));
32
+ kept.anchorA.push(...all.anchorA.slice(start, end));
33
+ kept.anchorB.push(...all.anchorB.slice(start, end));
34
+ kept.anchorT.push(...all.anchorT.slice(start, end));
35
+ });
36
+ return kept;
37
+ }
38
+ function flattenContours(p, tolerance, closed) {
23
39
  const { commands, coords } = p;
24
40
  const out = [];
25
41
  const anchorA = [];
@@ -108,6 +124,7 @@ function flattenPolygon(p, tolerance) {
108
124
  break;
109
125
  }
110
126
  case PATH_Z:
127
+ closed.add(contourStarts.length - 1);
111
128
  prevAnchor = startAnchor;
112
129
  break;
113
130
  default:
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tessellate/tessellate.ts","../../src/tessellate/trim.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import earcut from 'earcut';\nimport { forEachSegment, PATH_M, PATH_L, PATH_Z, PATH_C, PATH_Q } from '../commands';\nimport { pointInPolygon } from '../polyline';\nimport { rectToContour } from '../box';\nimport type { Path, PolygonPath, RectPath } from '../path';\nimport {\n DEFAULT_FLATTEN_TOLERANCE,\n flattenCubicWithArcLen,\n flattenQuadraticWithArcLen,\n} from '../flatten';\nimport type { Mesh } from './mesh';\n\n/** Options for `tessellate`. A smaller tolerance means more triangles and\n * smoother curves; it is in path-local units, so callers rendering at a\n * larger scale should tighten it. */\nexport interface TessellateOptions {\n /** Flatness tolerance for bezier subdivision in path-local units. */\n flattenTolerance?: number;\n}\n\n/** Turn a path into a triangle mesh the renderer can draw: curves flattened to\n * line segments, then the resulting polygon triangulated. */\nexport function tessellate(path: Path, opts: TessellateOptions = {}): Mesh {\n if (path.kind === 'rect') return tessellateRect(path);\n return tessellatePolygon(path, opts);\n}\n\nfunction tessellateRect(p: RectPath): Mesh {\n const { x, y, width: w, height: h } = p;\n return {\n vertices: Float32Array.from(rectToContour(x, y, w, h)),\n indices: new Uint32Array([0, 1, 2, 0, 2, 3]),\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\ninterface FlattenedContours {\n coords: number[];\n contourStarts: number[];\n anchorA: number[];\n anchorB: number[];\n anchorT: number[];\n}\n\nfunction flattenPolygon(p: PolygonPath, tolerance: number): FlattenedContours {\n const { commands, coords } = p;\n const out: number[] = [];\n const anchorA: number[] = [];\n const anchorB: number[] = [];\n const anchorT: number[] = [];\n const contourStarts: number[] = [];\n let startAnchor = -1;\n let prevAnchor = -1;\n let anchorCounter = 0;\n\n // Anchor bookkeeping for the points a curve just appended: interior points\n // interpolate (prevAnchor → target); the last is pinned anchor-exact.\n const pushCurveAnchors = (anchorStart: number, arcAccum: number[], total: number, target: number): void => {\n for (let k = 0; k < arcAccum.length; k++) {\n anchorA.push(prevAnchor);\n anchorB.push(target);\n anchorT.push(total > 0 ? arcAccum[k] / total : 0);\n }\n const lastIdx = anchorStart + arcAccum.length - 1;\n anchorA[lastIdx] = target;\n anchorB[lastIdx] = target;\n anchorT[lastIdx] = 0;\n };\n\n forEachSegment(commands, coords, (cmd, coordIdx, prevX, prevY, _i, opensSubpath) => {\n if (opensSubpath) {\n const anchor = Math.max(startAnchor, 0);\n contourStarts.push(out.length / 2);\n out.push(prevX, prevY);\n anchorA.push(anchor);\n anchorB.push(anchor);\n anchorT.push(0);\n prevAnchor = anchor;\n }\n switch (cmd) {\n case PATH_M:\n case PATH_L: {\n if (cmd === PATH_M) {\n contourStarts.push(out.length / 2);\n startAnchor = anchorCounter;\n }\n out.push(coords[coordIdx], coords[coordIdx + 1]);\n anchorA.push(anchorCounter);\n anchorB.push(anchorCounter);\n anchorT.push(0);\n prevAnchor = anchorCounter;\n anchorCounter++;\n break;\n }\n case PATH_Q: {\n const target = anchorCounter;\n const arcAccum: number[] = [];\n const anchorStart = anchorA.length;\n const total = flattenQuadraticWithArcLen(\n prevX, prevY,\n coords[coordIdx], coords[coordIdx + 1],\n coords[coordIdx + 2], coords[coordIdx + 3],\n tolerance, out, arcAccum,\n );\n pushCurveAnchors(anchorStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_C: {\n const target = anchorCounter;\n const arcAccum: number[] = [];\n const anchorStart = anchorA.length;\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, out, arcAccum,\n );\n pushCurveAnchors(anchorStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_Z:\n // The pen returns to the subpath start (forEachSegment does that); the\n // anchor it carries has to follow, or a curve after the Z interpolates\n // from the wrong end.\n prevAnchor = startAnchor;\n break;\n default:\n throw new Error(`tessellate: unknown command code ${cmd}`);\n }\n });\n\n return { coords: out, contourStarts, anchorA, anchorB, anchorT };\n}\n\nfunction tessellatePolygon(p: PolygonPath, opts: TessellateOptions): Mesh {\n const tolerance = opts.flattenTolerance ?? DEFAULT_FLATTEN_TOLERANCE;\n const { coords, contourStarts, anchorA, anchorB, anchorT } = flattenPolygon(p, tolerance);\n\n if (p.fillRule === 'evenodd') {\n return tessellateEvenoddWithAnchors(coords, contourStarts, anchorA, anchorB, anchorT);\n }\n\n // nonzero compound-path tessellation:\n // - The first contour establishes the reference winding direction.\n // - Subsequent contours with the SAME winding as the first are positives\n // (filled, disjoint shapes).\n // - Subsequent contours with OPPOSITE winding are holes; each is grouped\n // with the smallest positive whose polygon contains its first vertex.\n // - Each (positive, [its holes]) group is earcut'd independently;\n // triangles concatenated.\n // Authors mostly write disjoint-positives-with-same-winding; the previous\n // implementation passed every subsequent contour as a hole, which broke\n // those (a duck with body+head+beak, a hamburglar with brim+crown+cape).\n // Using shoelace sign relative to the first contour avoids guessing about\n // screen-down vs math-up axis conventions.\n\n const totalVerts = coords.length / 2;\n const contourEnd = (i: number): number =>\n i + 1 < contourStarts.length ? contourStarts[i + 1] : totalVerts;\n\n if (contourStarts.length <= 1) {\n const tri = earcut(coords);\n return {\n vertices: new Float32Array(coords),\n indices: new Uint32Array(tri),\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n }\n\n const areas: number[] = contourStarts.map((s, i) => signedArea(coords, s, contourEnd(i)));\n const refSign = Math.sign(areas[0]) || 1;\n\n const positives: number[] = [];\n const negatives: number[] = [];\n for (let i = 0; i < contourStarts.length; i++) {\n if (areas[i] === 0) continue;\n if (Math.sign(areas[i]) === refSign) positives.push(i);\n else negatives.push(i);\n }\n\n if (positives.length === 1 && negatives.length > 0) {\n // Classic outer-with-holes pattern; pass directly to earcut.\n const holeIndices = contourStarts.slice(1);\n const tri = earcut(coords, holeIndices);\n return {\n vertices: new Float32Array(coords),\n indices: new Uint32Array(tri),\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n }\n\n // Group each opposite-wound contour with the smallest positive that\n // contains its first vertex. Orphans (opposite-wound but not inside any\n // positive) get promoted to independent positives — author probably\n // intended them as separate shapes with inconsistent winding.\n const holesByPositive = new Map<number, number[]>();\n const orphanPositives: number[] = [];\n for (const n of negatives) {\n const px = coords[contourStarts[n] * 2];\n const py = coords[contourStarts[n] * 2 + 1];\n let bestPos = -1;\n let bestAbsArea = Infinity;\n for (const pos of positives) {\n const absArea = Math.abs(areas[pos]);\n if (absArea < bestAbsArea && pointInPolygon(coords, px, py, contourStarts[pos], contourEnd(pos))) {\n bestAbsArea = absArea;\n bestPos = pos;\n }\n }\n if (bestPos >= 0) {\n const arr = holesByPositive.get(bestPos) ?? [];\n arr.push(n);\n holesByPositive.set(bestPos, arr);\n } else {\n orphanPositives.push(n);\n }\n }\n\n const allPositives = [...positives, ...orphanPositives];\n\n const finalCoords: number[] = [];\n const finalAnchorA: number[] = [];\n const finalAnchorB: number[] = [];\n const finalAnchorT: number[] = [];\n const finalIndices: number[] = [];\n for (const pos of allPositives) {\n const holes = holesByPositive.get(pos) ?? [];\n const offset = finalCoords.length / 2;\n const groupCoords: number[] = [];\n const groupStarts: number[] = [0];\n for (let i = contourStarts[pos]; i < contourEnd(pos); i++) {\n groupCoords.push(coords[i * 2], coords[i * 2 + 1]);\n finalAnchorA.push(anchorA[i]);\n finalAnchorB.push(anchorB[i]);\n finalAnchorT.push(anchorT[i]);\n }\n for (const h of holes) {\n groupStarts.push(groupCoords.length / 2);\n for (let i = contourStarts[h]; i < contourEnd(h); i++) {\n groupCoords.push(coords[i * 2], coords[i * 2 + 1]);\n finalAnchorA.push(anchorA[i]);\n finalAnchorB.push(anchorB[i]);\n finalAnchorT.push(anchorT[i]);\n }\n }\n const tri = earcut(groupCoords, groupStarts.length > 1 ? groupStarts.slice(1) : undefined);\n for (const v of groupCoords) finalCoords.push(v);\n for (const idx of tri) finalIndices.push(idx + offset);\n }\n\n return {\n vertices: new Float32Array(finalCoords),\n indices: new Uint32Array(finalIndices),\n anchorA: new Uint32Array(finalAnchorA),\n anchorB: new Uint32Array(finalAnchorB),\n anchorT: new Float32Array(finalAnchorT),\n };\n}\n\nfunction tessellateEvenoddWithAnchors(\n coords: number[],\n contourStarts: number[],\n anchorA: number[],\n anchorB: number[],\n anchorT: number[],\n): Mesh {\n const indices: number[] = [];\n const totalVerts = coords.length / 2;\n for (let c = 0; c < contourStarts.length; c++) {\n const start = contourStarts[c];\n const end = c + 1 < contourStarts.length ? contourStarts[c + 1] : totalVerts;\n for (let i = start + 1; i < end - 1; i++) {\n indices.push(start, i, i + 1);\n }\n }\n return {\n vertices: new Float32Array(coords),\n indices: new Uint32Array(indices),\n requiresStencil: true,\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n}\n\nfunction signedArea(coords: number[], start: number, end: number): number {\n let a = 0;\n for (let i = start; i < end; i++) {\n const j = i + 1 === end ? start : i + 1;\n a += coords[i * 2] * coords[j * 2 + 1] - coords[j * 2] * coords[i * 2 + 1];\n }\n return a * 0.5;\n}\n","/**\n * Shortening a flattened subpath so a filled marker is not speared by its own\n * line. SVG has no equivalent — it paints the marker over a full-length\n * stroke — so this is the one place our rendering deliberately differs.\n *\n * Runs before dash splitting, so a dash pattern fits the visible line rather\n * than running off under the head. The anchor-param interpolation matches\n * `splitForDash`'s rule for a boundary landing mid-segment.\n */\n\nimport type { Polyline } from './polyline';\n\nconst EPS = 1e-9;\n\ninterface Sample {\n x: number; y: number;\n a: number; b: number; t: number;\n w: number;\n /** Index of the first original point at or after this sample. */\n next: number;\n}\n\nfunction sampleAt(\n pl: Polyline, cum: Float64Array,\n A: Uint32Array, B: Uint32Array, T: Float32Array, W: Float32Array | undefined,\n dist: number,\n /** For a cut landing exactly on a vertex: whether the vertex belongs to the\n * run after the sample (a head) or before it (a tail), so it is kept once. */\n vertexFollows: boolean,\n): Sample {\n const n = cum.length;\n let i = 1;\n while (i < n - 1 && (vertexFollows ? cum[i] <= dist : cum[i] < dist)) i++;\n const segStart = cum[i - 1];\n const segLen = cum[i] - segStart;\n const f = segLen > EPS ? (dist - segStart) / segLen : 0;\n\n const px = pl.points[(i - 1) * 2], py = pl.points[(i - 1) * 2 + 1];\n const qx = pl.points[i * 2], qy = pl.points[i * 2 + 1];\n\n let a: number, b: number, t: number;\n if (A[i - 1] === A[i] && B[i - 1] === B[i]) {\n a = A[i - 1]; b = B[i - 1];\n t = T[i - 1] + (T[i] - T[i - 1]) * f;\n } else if (f < 0.5) {\n a = A[i - 1]; b = B[i - 1]; t = T[i - 1];\n } else {\n a = A[i]; b = B[i]; t = T[i];\n }\n\n const w = W ? W[i - 1] + (W[i] - W[i - 1]) * f : 0;\n return { x: px + (qx - px) * f, y: py + (qy - py) * f, a, b, t, w, next: i };\n}\n\n/**\n * Shorten `pl` by `startInset` from its first point and `endInset` from its\n * last, both in the same world units as the points.\n *\n * Returns `pl` itself when there is nothing to do (both insets zero, or the\n * subpath is closed and so has no free ends), and `null` when the insets\n * consume the whole run — a caller should then draw no ribbon at all.\n */\nexport function trimPolyline(\n pl: Polyline,\n startInset: number,\n endInset: number,\n): Polyline | null {\n const from = Math.max(0, startInset);\n const to = Math.max(0, endInset);\n if (from <= 0 && to <= 0) return pl;\n if (pl.closed) return pl;\n\n const n = pl.points.length / 2;\n if (n < 2) return null;\n\n const A = pl.anchorA ?? new Uint32Array(n);\n const B = pl.anchorB ?? new Uint32Array(n);\n const T = pl.anchorT ?? new Float32Array(n);\n const W = pl.widths;\n\n const cum = new Float64Array(n);\n for (let i = 1; i < n; i++) {\n const dx = pl.points[i * 2] - pl.points[(i - 1) * 2];\n const dy = pl.points[i * 2 + 1] - pl.points[(i - 1) * 2 + 1];\n cum[i] = cum[i - 1] + Math.hypot(dx, dy);\n }\n const total = cum[n - 1];\n const cutA = from;\n const cutB = total - to;\n if (cutB - cutA <= EPS) return null;\n\n const head = sampleAt(pl, cum, A, B, T, W, cutA, true);\n const tail = sampleAt(pl, cum, A, B, T, W, cutB, false);\n\n const points: number[] = [head.x, head.y];\n const aOut: number[] = [head.a];\n const bOut: number[] = [head.b];\n const tOut: number[] = [head.t];\n const wOut: number[] | undefined = W ? [head.w] : undefined;\n\n for (let i = head.next; i < tail.next; i++) {\n points.push(pl.points[i * 2], pl.points[i * 2 + 1]);\n aOut.push(A[i]); bOut.push(B[i]); tOut.push(T[i]);\n if (wOut) wOut.push(W![i]);\n }\n\n points.push(tail.x, tail.y);\n aOut.push(tail.a); bOut.push(tail.b); tOut.push(tail.t);\n if (wOut) wOut.push(tail.w);\n\n return {\n points,\n closed: false,\n anchorA: new Uint32Array(aOut),\n anchorB: new Uint32Array(bOut),\n anchorT: new Float32Array(tOut),\n ...(wOut ? { widths: new Float32Array(wOut) } : {}),\n };\n}\n"]}
1
+ {"version":3,"sources":["../../src/tessellate/tessellate.ts","../../src/tessellate/trim.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import earcut from 'earcut';\nimport { forEachSegment, PATH_M, PATH_L, PATH_Z, PATH_C, PATH_Q } from '../commands';\nimport { pointInPolygon } from '../polyline';\nimport { rectToContour } from '../box';\nimport type { Path, PolygonPath, RectPath } from '../path';\nimport { fillsOpenSubpaths } from '../openFill';\nimport {\n DEFAULT_FLATTEN_TOLERANCE,\n flattenCubicWithArcLen,\n flattenQuadraticWithArcLen,\n} from '../flatten';\nimport type { Mesh } from './mesh';\n\n/** Options for `tessellate`. A smaller tolerance means more triangles and\n * smoother curves; it is in path-local units, so callers rendering at a\n * larger scale should tighten it. */\nexport interface TessellateOptions {\n /** Flatness tolerance for bezier subdivision in path-local units. */\n flattenTolerance?: number;\n}\n\n/** Turn a path into a triangle mesh the renderer can draw: curves flattened to\n * line segments, then the resulting polygon triangulated. */\nexport function tessellate(path: Path, opts: TessellateOptions = {}): Mesh {\n if (path.kind === 'rect') return tessellateRect(path);\n return tessellatePolygon(path, opts);\n}\n\nfunction tessellateRect(p: RectPath): Mesh {\n const { x, y, width: w, height: h } = p;\n return {\n vertices: Float32Array.from(rectToContour(x, y, w, h)),\n indices: new Uint32Array([0, 1, 2, 0, 2, 3]),\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\ninterface FlattenedContours {\n coords: number[];\n contourStarts: number[];\n anchorA: number[];\n anchorB: number[];\n anchorT: number[];\n}\n\n/** The contours a fill covers: all of them, or only those a `Z` closed. */\nfunction flattenPolygon(p: PolygonPath, tolerance: number): FlattenedContours {\n const closed = new Set<number>();\n const all = flattenContours(p, tolerance, closed);\n if (fillsOpenSubpaths(p)) return all;\n const kept: FlattenedContours = { coords: [], contourStarts: [], anchorA: [], anchorB: [], anchorT: [] };\n all.contourStarts.forEach((start, c) => {\n if (!closed.has(c)) return;\n const end = c + 1 < all.contourStarts.length ? all.contourStarts[c + 1] : all.coords.length / 2;\n kept.contourStarts.push(kept.coords.length / 2);\n kept.coords.push(...all.coords.slice(start * 2, end * 2));\n kept.anchorA.push(...all.anchorA.slice(start, end));\n kept.anchorB.push(...all.anchorB.slice(start, end));\n kept.anchorT.push(...all.anchorT.slice(start, end));\n });\n return kept;\n}\n\n/** Flatten every contour, noting in `closed` the index of each one a `Z` ends. */\nfunction flattenContours(p: PolygonPath, tolerance: number, closed: Set<number>): FlattenedContours {\n const { commands, coords } = p;\n const out: number[] = [];\n const anchorA: number[] = [];\n const anchorB: number[] = [];\n const anchorT: number[] = [];\n const contourStarts: number[] = [];\n let startAnchor = -1;\n let prevAnchor = -1;\n let anchorCounter = 0;\n\n // Anchor bookkeeping for the points a curve just appended: interior points\n // interpolate (prevAnchor → target); the last is pinned anchor-exact.\n const pushCurveAnchors = (anchorStart: number, arcAccum: number[], total: number, target: number): void => {\n for (let k = 0; k < arcAccum.length; k++) {\n anchorA.push(prevAnchor);\n anchorB.push(target);\n anchorT.push(total > 0 ? arcAccum[k] / total : 0);\n }\n const lastIdx = anchorStart + arcAccum.length - 1;\n anchorA[lastIdx] = target;\n anchorB[lastIdx] = target;\n anchorT[lastIdx] = 0;\n };\n\n forEachSegment(commands, coords, (cmd, coordIdx, prevX, prevY, _i, opensSubpath) => {\n if (opensSubpath) {\n const anchor = Math.max(startAnchor, 0);\n contourStarts.push(out.length / 2);\n out.push(prevX, prevY);\n anchorA.push(anchor);\n anchorB.push(anchor);\n anchorT.push(0);\n prevAnchor = anchor;\n }\n switch (cmd) {\n case PATH_M:\n case PATH_L: {\n if (cmd === PATH_M) {\n contourStarts.push(out.length / 2);\n startAnchor = anchorCounter;\n }\n out.push(coords[coordIdx], coords[coordIdx + 1]);\n anchorA.push(anchorCounter);\n anchorB.push(anchorCounter);\n anchorT.push(0);\n prevAnchor = anchorCounter;\n anchorCounter++;\n break;\n }\n case PATH_Q: {\n const target = anchorCounter;\n const arcAccum: number[] = [];\n const anchorStart = anchorA.length;\n const total = flattenQuadraticWithArcLen(\n prevX, prevY,\n coords[coordIdx], coords[coordIdx + 1],\n coords[coordIdx + 2], coords[coordIdx + 3],\n tolerance, out, arcAccum,\n );\n pushCurveAnchors(anchorStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_C: {\n const target = anchorCounter;\n const arcAccum: number[] = [];\n const anchorStart = anchorA.length;\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, out, arcAccum,\n );\n pushCurveAnchors(anchorStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_Z:\n closed.add(contourStarts.length - 1);\n // The pen returns to the subpath start (forEachSegment does that); the\n // anchor it carries has to follow, or a curve after the Z interpolates\n // from the wrong end.\n prevAnchor = startAnchor;\n break;\n default:\n throw new Error(`tessellate: unknown command code ${cmd}`);\n }\n });\n\n return { coords: out, contourStarts, anchorA, anchorB, anchorT };\n}\n\nfunction tessellatePolygon(p: PolygonPath, opts: TessellateOptions): Mesh {\n const tolerance = opts.flattenTolerance ?? DEFAULT_FLATTEN_TOLERANCE;\n const { coords, contourStarts, anchorA, anchorB, anchorT } = flattenPolygon(p, tolerance);\n\n if (p.fillRule === 'evenodd') {\n return tessellateEvenoddWithAnchors(coords, contourStarts, anchorA, anchorB, anchorT);\n }\n\n // nonzero compound-path tessellation:\n // - The first contour establishes the reference winding direction.\n // - Subsequent contours with the SAME winding as the first are positives\n // (filled, disjoint shapes).\n // - Subsequent contours with OPPOSITE winding are holes; each is grouped\n // with the smallest positive whose polygon contains its first vertex.\n // - Each (positive, [its holes]) group is earcut'd independently;\n // triangles concatenated.\n // Using shoelace sign relative to the first contour avoids guessing about\n // screen-down vs math-up axis conventions.\n\n const totalVerts = coords.length / 2;\n const contourEnd = (i: number): number =>\n i + 1 < contourStarts.length ? contourStarts[i + 1] : totalVerts;\n\n if (contourStarts.length <= 1) {\n const tri = earcut(coords);\n return {\n vertices: new Float32Array(coords),\n indices: new Uint32Array(tri),\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n }\n\n const areas: number[] = contourStarts.map((s, i) => signedArea(coords, s, contourEnd(i)));\n const refSign = Math.sign(areas[0]) || 1;\n\n const positives: number[] = [];\n const negatives: number[] = [];\n for (let i = 0; i < contourStarts.length; i++) {\n if (areas[i] === 0) continue;\n if (Math.sign(areas[i]) === refSign) positives.push(i);\n else negatives.push(i);\n }\n\n if (positives.length === 1 && negatives.length > 0) {\n // Classic outer-with-holes pattern; pass directly to earcut.\n const holeIndices = contourStarts.slice(1);\n const tri = earcut(coords, holeIndices);\n return {\n vertices: new Float32Array(coords),\n indices: new Uint32Array(tri),\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n }\n\n // Orphans (opposite-wound but not inside any positive) get promoted to\n // independent positives — author probably intended them as separate shapes\n // with inconsistent winding.\n const holesByPositive = new Map<number, number[]>();\n const orphanPositives: number[] = [];\n for (const n of negatives) {\n const px = coords[contourStarts[n] * 2];\n const py = coords[contourStarts[n] * 2 + 1];\n let bestPos = -1;\n let bestAbsArea = Infinity;\n for (const pos of positives) {\n const absArea = Math.abs(areas[pos]);\n if (absArea < bestAbsArea && pointInPolygon(coords, px, py, contourStarts[pos], contourEnd(pos))) {\n bestAbsArea = absArea;\n bestPos = pos;\n }\n }\n if (bestPos >= 0) {\n const arr = holesByPositive.get(bestPos) ?? [];\n arr.push(n);\n holesByPositive.set(bestPos, arr);\n } else {\n orphanPositives.push(n);\n }\n }\n\n const allPositives = [...positives, ...orphanPositives];\n\n const finalCoords: number[] = [];\n const finalAnchorA: number[] = [];\n const finalAnchorB: number[] = [];\n const finalAnchorT: number[] = [];\n const finalIndices: number[] = [];\n for (const pos of allPositives) {\n const holes = holesByPositive.get(pos) ?? [];\n const offset = finalCoords.length / 2;\n const groupCoords: number[] = [];\n const groupStarts: number[] = [0];\n for (let i = contourStarts[pos]; i < contourEnd(pos); i++) {\n groupCoords.push(coords[i * 2], coords[i * 2 + 1]);\n finalAnchorA.push(anchorA[i]);\n finalAnchorB.push(anchorB[i]);\n finalAnchorT.push(anchorT[i]);\n }\n for (const h of holes) {\n groupStarts.push(groupCoords.length / 2);\n for (let i = contourStarts[h]; i < contourEnd(h); i++) {\n groupCoords.push(coords[i * 2], coords[i * 2 + 1]);\n finalAnchorA.push(anchorA[i]);\n finalAnchorB.push(anchorB[i]);\n finalAnchorT.push(anchorT[i]);\n }\n }\n const tri = earcut(groupCoords, groupStarts.length > 1 ? groupStarts.slice(1) : undefined);\n for (const v of groupCoords) finalCoords.push(v);\n for (const idx of tri) finalIndices.push(idx + offset);\n }\n\n return {\n vertices: new Float32Array(finalCoords),\n indices: new Uint32Array(finalIndices),\n anchorA: new Uint32Array(finalAnchorA),\n anchorB: new Uint32Array(finalAnchorB),\n anchorT: new Float32Array(finalAnchorT),\n };\n}\n\nfunction tessellateEvenoddWithAnchors(\n coords: number[],\n contourStarts: number[],\n anchorA: number[],\n anchorB: number[],\n anchorT: number[],\n): Mesh {\n const indices: number[] = [];\n const totalVerts = coords.length / 2;\n for (let c = 0; c < contourStarts.length; c++) {\n const start = contourStarts[c];\n const end = c + 1 < contourStarts.length ? contourStarts[c + 1] : totalVerts;\n for (let i = start + 1; i < end - 1; i++) {\n indices.push(start, i, i + 1);\n }\n }\n return {\n vertices: new Float32Array(coords),\n indices: new Uint32Array(indices),\n requiresStencil: true,\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n}\n\nfunction signedArea(coords: number[], start: number, end: number): number {\n let a = 0;\n for (let i = start; i < end; i++) {\n const j = i + 1 === end ? start : i + 1;\n a += coords[i * 2] * coords[j * 2 + 1] - coords[j * 2] * coords[i * 2 + 1];\n }\n return a * 0.5;\n}\n","/**\n * Shortening a flattened subpath so a filled marker is not speared by its own\n * line. SVG has no equivalent — it paints the marker over a full-length\n * stroke — so this is the one place our rendering deliberately differs.\n *\n * Runs before dash splitting, so a dash pattern fits the visible line rather\n * than running off under the head. The anchor-param interpolation matches\n * `splitForDash`'s rule for a boundary landing mid-segment.\n */\n\nimport type { Polyline } from './polyline';\n\nconst EPS = 1e-9;\n\ninterface Sample {\n x: number; y: number;\n a: number; b: number; t: number;\n w: number;\n /** Index of the first original point at or after this sample. */\n next: number;\n}\n\nfunction sampleAt(\n pl: Polyline, cum: Float64Array,\n A: Uint32Array, B: Uint32Array, T: Float32Array, W: Float32Array | undefined,\n dist: number,\n /** For a cut landing exactly on a vertex: whether the vertex belongs to the\n * run after the sample (a head) or before it (a tail), so it is kept once. */\n vertexFollows: boolean,\n): Sample {\n const n = cum.length;\n let i = 1;\n while (i < n - 1 && (vertexFollows ? cum[i] <= dist : cum[i] < dist)) i++;\n const segStart = cum[i - 1];\n const segLen = cum[i] - segStart;\n const f = segLen > EPS ? (dist - segStart) / segLen : 0;\n\n const px = pl.points[(i - 1) * 2], py = pl.points[(i - 1) * 2 + 1];\n const qx = pl.points[i * 2], qy = pl.points[i * 2 + 1];\n\n let a: number, b: number, t: number;\n if (A[i - 1] === A[i] && B[i - 1] === B[i]) {\n a = A[i - 1]; b = B[i - 1];\n t = T[i - 1] + (T[i] - T[i - 1]) * f;\n } else if (f < 0.5) {\n a = A[i - 1]; b = B[i - 1]; t = T[i - 1];\n } else {\n a = A[i]; b = B[i]; t = T[i];\n }\n\n const w = W ? W[i - 1] + (W[i] - W[i - 1]) * f : 0;\n return { x: px + (qx - px) * f, y: py + (qy - py) * f, a, b, t, w, next: i };\n}\n\n/**\n * Shorten `pl` by `startInset` from its first point and `endInset` from its\n * last, both in the same world units as the points.\n *\n * Returns `pl` itself when there is nothing to do (both insets zero, or the\n * subpath is closed and so has no free ends), and `null` when the insets\n * consume the whole run — a caller should then draw no ribbon at all.\n */\nexport function trimPolyline(\n pl: Polyline,\n startInset: number,\n endInset: number,\n): Polyline | null {\n const from = Math.max(0, startInset);\n const to = Math.max(0, endInset);\n if (from <= 0 && to <= 0) return pl;\n if (pl.closed) return pl;\n\n const n = pl.points.length / 2;\n if (n < 2) return null;\n\n const A = pl.anchorA ?? new Uint32Array(n);\n const B = pl.anchorB ?? new Uint32Array(n);\n const T = pl.anchorT ?? new Float32Array(n);\n const W = pl.widths;\n\n const cum = new Float64Array(n);\n for (let i = 1; i < n; i++) {\n const dx = pl.points[i * 2] - pl.points[(i - 1) * 2];\n const dy = pl.points[i * 2 + 1] - pl.points[(i - 1) * 2 + 1];\n cum[i] = cum[i - 1] + Math.hypot(dx, dy);\n }\n const total = cum[n - 1];\n const cutA = from;\n const cutB = total - to;\n if (cutB - cutA <= EPS) return null;\n\n const head = sampleAt(pl, cum, A, B, T, W, cutA, true);\n const tail = sampleAt(pl, cum, A, B, T, W, cutB, false);\n\n const points: number[] = [head.x, head.y];\n const aOut: number[] = [head.a];\n const bOut: number[] = [head.b];\n const tOut: number[] = [head.t];\n const wOut: number[] | undefined = W ? [head.w] : undefined;\n\n for (let i = head.next; i < tail.next; i++) {\n points.push(pl.points[i * 2], pl.points[i * 2 + 1]);\n aOut.push(A[i]); bOut.push(B[i]); tOut.push(T[i]);\n if (wOut) wOut.push(W![i]);\n }\n\n points.push(tail.x, tail.y);\n aOut.push(tail.a); bOut.push(tail.b); tOut.push(tail.t);\n if (wOut) wOut.push(tail.w);\n\n return {\n points,\n closed: false,\n anchorA: new Uint32Array(aOut),\n anchorB: new Uint32Array(bOut),\n anchorT: new Float32Array(tOut),\n ...(wOut ? { widths: new Float32Array(wOut) } : {}),\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weasel-js/geom",
3
- "version": "1.9.4",
3
+ "version": "1.10.0",
4
4
  "description": "Pure geometry kernel for @weasel-js/core: affine, box, curve, polyline, the Path command stream and its math, and easing curves in 2D. Dependency-free core; curve representations in ./curves, tessellation in ./tessellate (earcut), polygon booleans and path splitting in ./booleans (polygon-clipping), 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"],"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;AAiBO,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-E4TJRGJD.js","sourcesContent":["/**\n * SVG-style command-stream encoding — the kit's single declaration of the path\n * opcodes. `Path` (`./path`) 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\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 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 * Such a command opens a new subpath at the pen, as does a drawing command\n * no `M` precedes at all. The visitor is told with `opensSubpath`, and has to\n * start its contour at `(penX, penY)` 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 * 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 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 +0,0 @@
1
- {"version":3,"sources":["../src/paths/cubicMath.ts"],"names":[],"mappings":"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","file":"chunk-HPVINMOM.js","sourcesContent":["import { cubicEvalAt, splitCubicAt, type CubicCoords } from '../curve';\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\ninterface AnchorRef {\n x: number; y: number;\n inHandle?: Point;\n outHandle?: Point;\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: AnchorRef,\n next: AnchorRef,\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: AnchorRef,\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"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/scalar.ts"],"names":[],"mappings":";AAUO,IAAM,GAAA,GAAM;AAKZ,IAAM,cAAA,GAAiB;AAGvB,SAAS,KAAA,CAAM,CAAA,EAAW,EAAA,EAAY,EAAA,EAAoB;AAC/D,EAAA,OAAO,CAAA,GAAI,EAAA,GAAK,EAAA,GAAK,CAAA,GAAI,KAAK,EAAA,GAAK,CAAA;AACrC;AAGO,SAAS,KAAA,CAAM,EAAA,EAAY,EAAA,EAAY,EAAA,EAAY,EAAA,EAAoB;AAC5E,EAAA,OAAO,EAAA,GAAK,KAAK,EAAA,GAAK,EAAA;AACxB;AAGO,SAAS,GAAA,CAAI,EAAA,EAAY,EAAA,EAAY,EAAA,EAAY,EAAA,EAAoB;AAC1E,EAAA,OAAO,EAAA,GAAK,KAAK,EAAA,GAAK,EAAA;AACxB;AAGO,SAAS,GAAA,CAAI,EAAA,EAAY,EAAA,EAAY,EAAA,EAAY,EAAA,EAA8B;AACpF,EAAA,OAAO,CAAC,EAAA,GAAK,EAAA,EAAI,EAAA,GAAK,EAAE,CAAA;AAC1B;AAGO,SAAS,IAAA,CAAK,GAAW,CAAA,EAAmB;AACjD,EAAA,OAAO,CAAA,GAAI,IAAI,CAAA,GAAI,CAAA;AACrB;AAGO,SAAS,KAAK,CAAA,EAAuB;AAC1C,EAAA,OAAO,CAAA,GAAI,CAAA,GAAI,CAAA,GAAI,CAAA,GAAI,IAAI,EAAA,GAAK,CAAA;AAClC;AAcO,SAAS,QAAA,CAAS,CAAA,EAAW,CAAA,EAAW,GAAA,GAAc,GAAA,EAAc;AACzE,EAAA,IAAI,CAAA,KAAM,GAAG,OAAO,IAAA;AACpB,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,CAAC,CAAA;AAG3B,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,IAAI,GAAG,OAAO,KAAA;AACnC,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAC,CAAC,CAAA;AAClD,EAAA,OAAO,QAAQ,GAAA,GAAM,KAAA;AACvB","file":"chunk-N5SYTHMR.js","sourcesContent":["/**\n * Scalar / 2-vector primitives and the kernel-wide epsilon policy.\n *\n * Points are scalar pairs (px, py); there is no point struct. All math is\n * f64 (JS-native). Epsilons are f32-SCALE and magnitude-relative, because\n * stored coords are quantized to Float32 (~7 significant digits) — see the\n * geometry-kernel spec.\n */\n\n/** Base relative epsilon, sized for Float32 storage (~1 part in 1e-6). */\nexport const EPS = 1e-6;\n\n/** A determinant at or below this fraction of its matrix's own scale counts as\n * singular. Dimensionless, so a uniformly tiny matrix still inverts while a\n * large one whose determinant is only rounding does not. */\nexport const SINGULAR_RATIO = 1e-12;\n\n/** `v` held to `lo`..`hi`. `lo` wins when the bounds cross; `NaN` passes through. */\nexport function clamp(v: number, lo: number, hi: number): number {\n return v < lo ? lo : v > hi ? hi : v;\n}\n\n/** 2D cross (wedge) product of vectors (ax,ay) and (bx,by). */\nexport function cross(ax: number, ay: number, bx: number, by: number): number {\n return ax * by - ay * bx;\n}\n\n/** 2D dot product. */\nexport function dot(ax: number, ay: number, bx: number, by: number): number {\n return ax * bx + ay * by;\n}\n\n/** Component difference (ax-bx, ay-by) as a tuple. Cold-path use only. */\nexport function sub(ax: number, ay: number, bx: number, by: number): [number, number] {\n return [ax - bx, ay - by];\n}\n\n/** Squared length of (x,y). Avoids the sqrt; compare against squared thresholds. */\nexport function len2(x: number, y: number): number {\n return x * x + y * y;\n}\n\n/** Three-valued sign. */\nexport function sign(n: number): -1 | 0 | 1 {\n return n > 0 ? 1 : n < 0 ? -1 : 0;\n}\n\n/**\n * Magnitude-scaled approximate equality. Two values are equal when their\n * absolute difference is within EPS scaled by the larger magnitude. Every\n * comparison of two *computed coordinates* goes through this — never `===`,\n * never an f64-tight literal.\n *\n * The exception is a guard against an exact algebraic value that a formula\n * produces bit-for-bit: a homogeneous `w === 1`, a ray's `d === 0`. Those are\n * testing a branch, not comparing coordinates, and `geom/3d` has two of them\n * (`mat4.ts`, `ray3.ts`). Widening one to `approxEq` would change which branch\n * runs, not how precisely it runs.\n */\nexport function approxEq(a: number, b: number, eps: number = EPS): boolean {\n if (a === b) return true; // also the only way two infinities compare equal\n const diff = Math.abs(a - b);\n // Infinity/Infinity is 1, so an unguarded relative test calls every finite\n // number equal to an infinity.\n if (!Number.isFinite(diff)) return false;\n const scale = Math.max(1, Math.abs(a), Math.abs(b));\n return diff <= eps * scale;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/flatten.ts","../src/polyline.ts"],"names":["len2"],"mappings":"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","file":"chunk-X6GJRIQD.js","sourcesContent":["/**\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/**\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, 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 = 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"]}
@@ -1,37 +0,0 @@
1
- /** A 2D point, the shape the point-taking path helpers read and return. */
2
- interface Point {
3
- x: number;
4
- y: number;
5
- }
6
- /** Point on the cubic Bezier (p0, p1, p2, p3) at parameter t. The point-shaped
7
- * face of geom's `cubicEvalAt`. */
8
- declare function cubicPointAt(p0: Point, p1: Point, p2: Point, p3: Point, t: number): Point;
9
- interface AnchorRef {
10
- x: number;
11
- y: number;
12
- inHandle?: Point;
13
- outHandle?: Point;
14
- }
15
- /** De Casteljau subdivision of a cubic at parameter t. The point-shaped face
16
- * of geom's `splitCubicAt`; `left[3]` and `right[0]` are the point at t. */
17
- declare function splitCubicAtT(p0: Point, p1: Point, p2: Point, p3: Point, t: number): {
18
- left: [Point, Point, Point, Point];
19
- right: [Point, Point, Point, Point];
20
- };
21
- /**
22
- * When an interior anchor is deleted, the two flanking segments fuse into one
23
- * cubic. We pick controls c1 and c2 that:
24
- * - lie along prev's outHandle direction (if present)
25
- * - lie along next's inHandle direction (if present)
26
- * - are placed at roughly 1/3 and 2/3 of the prev→next distance
27
- * Fallbacks: missing handles use prev→next as the direction.
28
- *
29
- * This is an approximate fit — the new curve will shift slightly from the
30
- * original two-segment path. Acceptable per spec.
31
- */
32
- declare function fitCubicThroughDeletion(prev: AnchorRef, next: AnchorRef): {
33
- c1: Point;
34
- c2: Point;
35
- };
36
-
37
- export { type Point as P, cubicPointAt as c, fitCubicThroughDeletion as f, splitCubicAtT as s };