@weasel-js/geom 1.10.1 → 1.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +9 -1
  2. package/dist/3d/index.d.ts +29 -2
  3. package/dist/3d/index.js +49 -1
  4. package/dist/3d/index.js.map +1 -1
  5. package/dist/booleans/index.d.ts +18 -11
  6. package/dist/booleans/index.js +432 -352
  7. package/dist/booleans/index.js.map +1 -1
  8. package/dist/chunk-4Y67BZL5.js +573 -0
  9. package/dist/chunk-4Y67BZL5.js.map +1 -0
  10. package/dist/chunk-6FGQML7D.js +152 -0
  11. package/dist/chunk-6FGQML7D.js.map +1 -0
  12. package/dist/{chunk-7WFFCHRL.js → chunk-7F66PQCJ.js} +6 -37
  13. package/dist/chunk-7F66PQCJ.js.map +1 -0
  14. package/dist/chunk-B53BERKG.js +386 -0
  15. package/dist/chunk-B53BERKG.js.map +1 -0
  16. package/dist/chunk-CE7IY7TB.js +104 -0
  17. package/dist/chunk-CE7IY7TB.js.map +1 -0
  18. package/dist/chunk-EAKE3N7W.js +804 -0
  19. package/dist/chunk-EAKE3N7W.js.map +1 -0
  20. package/dist/chunk-LRVPK7HI.js +491 -0
  21. package/dist/chunk-LRVPK7HI.js.map +1 -0
  22. package/dist/chunk-Q66NA2FU.js +174 -0
  23. package/dist/chunk-Q66NA2FU.js.map +1 -0
  24. package/dist/chunk-UI3FUWXM.js +533 -0
  25. package/dist/chunk-UI3FUWXM.js.map +1 -0
  26. package/dist/curvature-PkoLduGc.d.ts +454 -0
  27. package/dist/curves/index.d.ts +14 -5
  28. package/dist/curves/index.js +33 -111
  29. package/dist/curves/index.js.map +1 -1
  30. package/dist/index.d.ts +1511 -283
  31. package/dist/index.js +5755 -2674
  32. package/dist/index.js.map +1 -1
  33. package/dist/nd/index.d.ts +92 -27
  34. package/dist/nd/index.js +297 -0
  35. package/dist/nd/index.js.map +1 -1
  36. package/dist/path-BW8d_2RY.d.ts +157 -0
  37. package/dist/portCurve-C5HDWuuV.d.ts +30 -0
  38. package/dist/tessellate/index.d.ts +15 -4
  39. package/dist/tessellate/index.js +21 -277
  40. package/dist/tessellate/index.js.map +1 -1
  41. package/dist/warp/index.d.ts +254 -0
  42. package/dist/warp/index.js +1448 -0
  43. package/dist/warp/index.js.map +1 -0
  44. package/package.json +5 -1
  45. package/dist/chunk-7WFFCHRL.js.map +0 -1
  46. package/dist/chunk-IDXY2NCA.js +0 -177
  47. package/dist/chunk-IDXY2NCA.js.map +0 -1
  48. package/dist/chunk-NJ3IGAKR.js +0 -16
  49. package/dist/chunk-NJ3IGAKR.js.map +0 -1
  50. package/dist/chunk-OXH3NOXC.js +0 -62
  51. package/dist/chunk-OXH3NOXC.js.map +0 -1
  52. package/dist/chunk-URQMDR6Q.js +0 -80
  53. package/dist/chunk-URQMDR6Q.js.map +0 -1
  54. package/dist/cubicMath-BW-HJrCE.d.ts +0 -16
  55. package/dist/path-ljHxobyu.d.ts +0 -44
@@ -1,30 +1,95 @@
1
+ export { P as PORT_REACH, c as cubicAt, p as portControls, a as portCurvePoints } from '../portCurve-C5HDWuuV.js';
2
+
3
+ /** Affine subspaces ("flats") over plain number arrays, in any dimension:
4
+ * the points, lines and planes a snap resolves against. */
5
+ type Vec = readonly number[];
6
+ /** The affine subspace `at + span(dirs)`. `dirs` need not be orthonormal or
7
+ * independent; a zero or repeated direction adds nothing. */
8
+ interface Flat {
9
+ at: Vec;
10
+ dirs: readonly Vec[];
11
+ }
12
+ /** The flat's dimension: the rank of its directions. */
13
+ declare function flatDim(f: Flat): number;
14
+ /** The point of `f` nearest `p`. */
15
+ declare function closestOnFlat(f: Flat, p: Vec): Vec;
16
+ /** The nearest pair of points, one on each flat. Parallel flats have many
17
+ * such pairs; this returns one of them. */
18
+ declare function closestBetweenFlats(a: Flat, b: Flat): {
19
+ onA: Vec;
20
+ onB: Vec;
21
+ };
22
+ /** `a ∩ b`, or null when they miss each other by more than `eps`. */
23
+ declare function intersectFlats(a: Flat, b: Flat, eps?: number): Flat | null;
24
+
25
+ /** The snap resolver: every gesture's snap, in any dimension, as one search
26
+ * over affine constraints on the move `δ`. */
27
+
28
+ /** A `fallback` candidate holds only the axes no `target` claims. */
29
+ type SnapTier = 'target' | 'fallback';
30
+ /** What a probe stands for on the subject; sources match probes by role. */
31
+ type ProbeRole = 'origin' | 'box' | 'geometry' | 'pointer';
32
+ /** A point on the subject that should land on a locus. `role` says which
33
+ * sources may match it. */
34
+ interface SnapProbe {
35
+ id: string;
36
+ at: Vec;
37
+ role: ProbeRole;
38
+ }
39
+ /** One probe paired with one locus. `M` is the mark payload, opaque here. */
40
+ interface SnapCandidate<M> {
41
+ /** `SnapProbe.id`. */
42
+ probe: string;
43
+ locus: Flat;
44
+ /** One interval per locus dir, in multiples of that dir. A solution
45
+ * outside it fails the candidate. */
46
+ span?: readonly (readonly [number, number])[];
47
+ source: string;
48
+ /** Stable tiebreak: lower wins when everything else is equal. */
49
+ order: number;
50
+ tier: SnapTier;
51
+ reachPx: number;
52
+ /** When any required candidate exists, the result includes one of them,
53
+ * whatever its reach. */
54
+ required?: boolean;
55
+ mark?: M;
56
+ }
57
+ /** One frame's snap: the probes, the input subspace, the raw move, and the candidates. */
58
+ interface SnapProblem<M> {
59
+ probes: readonly SnapProbe[];
60
+ /** `H`, the subspace of δ-space the result stays inside. */
61
+ input: Flat;
62
+ /** The unsnapped move. */
63
+ delta0: Vec;
64
+ candidates: readonly SnapCandidate<M>[];
65
+ /** World to screen pixels. A non-finite result puts that position out of reach. */
66
+ toScreen(world: Vec): Vec;
67
+ /** Candidates kept per probe, nearest first, besides the required ones,
68
+ * which are all kept. Default 24. */
69
+ poolSize?: number;
70
+ /** World-space tolerance for "on the locus". Default 1e-6. */
71
+ eps?: number;
72
+ }
73
+ /** The move `resolveSnap` chose and the candidates it meets. */
74
+ interface SnapResolution<M> {
75
+ /** `closestOnFlat(input, delta0)` when nothing snaps. */
76
+ delta: Vec;
77
+ members: readonly SnapCandidate<M>[];
78
+ /** Every in-reach candidate the result meets: the ones whose marks show. */
79
+ satisfied: readonly SnapCandidate<M>[];
80
+ /** How many dimensions of `H` the result pins. */
81
+ codim: number;
82
+ }
83
+ /** The move nearest `delta0` within `H` that meets the best-ranked set of
84
+ * candidates in reach, or `delta0` projected into `H` when none is. */
85
+ declare function resolveSnap<M>(problem: SnapProblem<M>): SnapResolution<M>;
86
+
1
87
  /**
2
- * The cubic control points that make a curve leave a port along its normal and
3
- * arrive at the next against that port's normal — what makes a routed edge read
4
- * as plugged into a box rather than aimed at it.
5
- *
6
- * The rule is stated once, over loose components, and published as is from
7
- * `./nd`; the 2D barrel and `./3d` each wrap it in their own currency. Every
8
- * operation here is closed on the plane z = 0, so a planar problem answered
9
- * through the 3D wrapper returns the same numbers as through the 2D one, not an
10
- * approximation of them.
11
- */
12
- /** How far a control point reaches toward the other end, as a fraction of the
13
- * straight-line distance between the two. */
14
- declare const PORT_REACH = 0.4;
15
- /**
16
- * `[c1, c2]` for the cubic from `a` to `b`.
17
- *
18
- * A null normal falls back to a plain lerp along the chord, which is what makes
19
- * an unported waypoint curve smoothly instead of kinking. The two ends are not
20
- * symmetric: `outNormal` points the way the curve departs, while `inNormal`
21
- * points out of the receiving port, so `c2` is pushed *along* it to arrive
22
- * against it.
88
+ * The line through `about` whose direction, measured in the plane `basis`
89
+ * spans (as an angle from `basis[0]` toward `basis[1]`), is the multiple of
90
+ * `step` nearest the direction from `about` to `toward`: a constrained
91
+ * gesture's input subspace, in any dimension. `basis` is orthonormal.
23
92
  */
24
- declare function portControls(a: readonly number[], b: readonly number[], outNormal: readonly number[] | null | undefined, inNormal: readonly number[] | null | undefined, reach?: number): [number[], number[]];
25
- /** A port curve sampled into `samples` points, excluding its start. */
26
- declare function portCurvePoints(a: readonly number[], b: readonly number[], outNormal: readonly number[] | null | undefined, inNormal: readonly number[] | null | undefined, samples: number, reach?: number): number[][];
27
- /** A cubic evaluated at `t`, component-wise, in whatever dimension it was given. */
28
- declare function cubicAt(p0: readonly number[], p1: readonly number[], p2: readonly number[], p3: readonly number[], t: number): number[];
93
+ declare function stepLine(about: Vec, toward: Vec, basis: readonly [Vec, Vec], step: number): Flat;
29
94
 
30
- export { PORT_REACH, cubicAt, portControls, portCurvePoints };
95
+ export { type Flat, type ProbeRole, type SnapCandidate, type SnapProbe, type SnapProblem, type SnapResolution, type SnapTier, type Vec, closestBetweenFlats, closestOnFlat, flatDim, intersectFlats, resolveSnap, stepLine };
package/dist/nd/index.js CHANGED
@@ -1,3 +1,300 @@
1
1
  export { PORT_REACH, cubicAt, portControls, portCurvePoints } from '../chunk-YQADYJJ7.js';
2
+
3
+ // src/snap/flat.ts
4
+ var RANK_TOL = 1e-6;
5
+ function dotv(a, b) {
6
+ let s = 0;
7
+ for (let i = 0; i < a.length; i++) s += a[i] * b[i];
8
+ return s;
9
+ }
10
+ function normv(a) {
11
+ return Math.sqrt(dotv(a, a));
12
+ }
13
+ function isFiniteVec(a) {
14
+ return a.every(Number.isFinite);
15
+ }
16
+ function orthonormalize(vecs, start = []) {
17
+ const basis = start.map((q) => q.slice());
18
+ const out = [];
19
+ for (const d of vecs) {
20
+ const n0 = normv(d);
21
+ if (!(n0 > 0) || !isFiniteVec(d)) continue;
22
+ const v = d.slice();
23
+ for (let pass = 0; pass < 2; pass++) {
24
+ for (const q of basis) {
25
+ const k = dotv(v, q);
26
+ for (let i = 0; i < v.length; i++) v[i] -= k * q[i];
27
+ }
28
+ }
29
+ const n = normv(v);
30
+ if (n <= RANK_TOL * n0) continue;
31
+ for (let i = 0; i < v.length; i++) v[i] /= n;
32
+ basis.push(v);
33
+ out.push(v);
34
+ }
35
+ return out;
36
+ }
37
+ function complement(basis, n) {
38
+ const axes = [];
39
+ for (let i = 0; i < n; i++) axes.push(Array.from({ length: n }, (_, j) => i === j ? 1 : 0));
40
+ return orthonormalize(axes, basis);
41
+ }
42
+ function flatDim(f) {
43
+ return orthonormalize(f.dirs).length;
44
+ }
45
+ function closestOnFlat(f, p) {
46
+ const out = f.at.slice();
47
+ for (const q of orthonormalize(f.dirs)) {
48
+ let k = 0;
49
+ for (let i = 0; i < q.length; i++) k += q[i] * (p[i] - f.at[i]);
50
+ for (let i = 0; i < out.length; i++) out[i] += k * q[i];
51
+ }
52
+ return out;
53
+ }
54
+ function solveLeastSquares(cols, rhs) {
55
+ const k = cols.length;
56
+ const m = cols.map((a) => [...cols.map((b) => dotv(a, b)), dotv(a, rhs)]);
57
+ const len2 = m.map((r, i) => r[i]);
58
+ const kept = [];
59
+ for (let col = 0; col < k; col++) {
60
+ if (!(m[col][col] > RANK_TOL * RANK_TOL * len2[col])) continue;
61
+ for (let r = col + 1; r < k; r++) {
62
+ const f = m[r][col] / m[col][col];
63
+ for (let c = col; c <= k; c++) m[r][c] -= f * m[col][c];
64
+ }
65
+ kept.push(col);
66
+ }
67
+ const x = new Array(k).fill(0);
68
+ for (let p = kept.length - 1; p >= 0; p--) {
69
+ const col = kept[p];
70
+ let s = m[col][k];
71
+ for (let c = col + 1; c < k; c++) s -= m[col][c] * x[c];
72
+ x[col] = s / m[col][col];
73
+ }
74
+ return x;
75
+ }
76
+ function closestBetweenFlats(a, b) {
77
+ const qa = orthonormalize(a.dirs);
78
+ const qb = orthonormalize(b.dirs);
79
+ const d = b.at.map((v, i) => v - a.at[i]);
80
+ const x = solveLeastSquares([...qa, ...qb.map((q) => q.map((v) => -v))], d);
81
+ const onA = a.at.slice();
82
+ const onB = b.at.slice();
83
+ qa.forEach((q, j) => q.forEach((v, i) => {
84
+ onA[i] += x[j] * v;
85
+ }));
86
+ qb.forEach((q, j) => q.forEach((v, i) => {
87
+ onB[i] += x[qa.length + j] * v;
88
+ }));
89
+ return { onA, onB };
90
+ }
91
+ function intersectFlats(a, b, eps = 1e-6) {
92
+ const { onA, onB } = closestBetweenFlats(a, b);
93
+ let gap2 = 0;
94
+ for (let i = 0; i < onA.length; i++) gap2 += (onA[i] - onB[i]) ** 2;
95
+ if (!(Math.sqrt(gap2) <= eps) || !isFiniteVec(onA)) return null;
96
+ const n = a.at.length;
97
+ const normals = orthonormalize([
98
+ ...complement(orthonormalize(a.dirs), n),
99
+ ...complement(orthonormalize(b.dirs), n)
100
+ ]);
101
+ return { at: onA, dirs: complement(normals, n) };
102
+ }
103
+
104
+ // src/snap/resolve.ts
105
+ var DEFAULT_POOL = 24;
106
+ var DEFAULT_EPS = 1e-6;
107
+ var SAME_PX = 1e-9;
108
+ var plus = (a, b) => a.map((v, i) => v + b[i]);
109
+ var minus = (a, b) => a.map((v, i) => v - b[i]);
110
+ var isFiniteVec2 = (a) => a.every(Number.isFinite);
111
+ function distance(a, b) {
112
+ let s = 0;
113
+ for (let i = 0; i < a.length; i++) s += (a[i] - b[i]) ** 2;
114
+ return Math.sqrt(s);
115
+ }
116
+ function makeMeasure(problem, base, eps) {
117
+ const home = /* @__PURE__ */ new Map();
118
+ return {
119
+ eps,
120
+ move(probeId, probe, delta) {
121
+ let h = home.get(probeId);
122
+ if (!h) home.set(probeId, h = problem.toScreen(plus(probe, base)));
123
+ const d = distance(problem.toScreen(plus(probe, delta)), h);
124
+ return Number.isFinite(d) ? d : NaN;
125
+ }
126
+ };
127
+ }
128
+ function spanHolds(c, world, eps) {
129
+ if (!c.span) return true;
130
+ const u = solveLeastSquares(c.locus.dirs, minus(world, c.locus.at));
131
+ return c.span.every(([lo, hi], i) => u[i] >= lo - eps && u[i] <= hi + eps);
132
+ }
133
+ function meets(m, c, probe, delta) {
134
+ const measured = m.move(c.probe, probe, delta);
135
+ if (!c.required && (Number.isNaN(measured) || !(measured <= c.reachPx))) return null;
136
+ const px = Number.isNaN(measured) ? Infinity : measured;
137
+ return spanHolds(c, plus(probe, delta), m.eps) ? px : null;
138
+ }
139
+ function liveCandidates(problem, m) {
140
+ const probes = new Map(problem.probes.map((p) => [p.id, p.at]));
141
+ const live = [];
142
+ for (const c of problem.candidates) {
143
+ const probe = probes.get(c.probe);
144
+ if (!probe || !isFiniteVec2(probe) || !isFiniteVec2(c.locus.at) || !c.locus.dirs.every(isFiniteVec2)) continue;
145
+ const within = intersectFlats(problem.input, { at: minus(c.locus.at, probe), dirs: c.locus.dirs }, m.eps);
146
+ if (!within) continue;
147
+ const px = meets(m, c, probe, closestOnFlat(within, problem.delta0));
148
+ if (px !== null) live.push({ c, probe, within, px });
149
+ }
150
+ return live;
151
+ }
152
+ function pool(live, size) {
153
+ const byProbe = /* @__PURE__ */ new Map();
154
+ for (const l of live) {
155
+ const list = byProbe.get(l.c.probe) ?? [];
156
+ list.push(l);
157
+ byProbe.set(l.c.probe, list);
158
+ }
159
+ const out = [];
160
+ for (const list of byProbe.values()) {
161
+ list.sort((a, b) => Math.abs(a.px - b.px) > SAME_PX ? a.px - b.px : a.c.order - b.c.order);
162
+ out.push(...list.filter((l, i) => i < size || l.c.required));
163
+ }
164
+ return out;
165
+ }
166
+ function compareOrders(a, b) {
167
+ const oa = a.map((l) => l.c.order).sort((x, y) => x - y);
168
+ const ob = b.map((l) => l.c.order).sort((x, y) => x - y);
169
+ for (let i = 0; i < Math.min(oa.length, ob.length); i++) if (oa[i] !== ob[i]) return oa[i] - ob[i];
170
+ return oa.length - ob.length;
171
+ }
172
+ function compareCombos(a, b) {
173
+ if (a.codim !== b.codim) return b.codim - a.codim;
174
+ if (a.targetCodim !== b.targetCodim) return b.targetCodim - a.targetCodim;
175
+ if (Math.abs(a.px - b.px) > SAME_PX) return a.px - b.px;
176
+ return compareOrders(a.members, b.members);
177
+ }
178
+ function extend(parent, l, input, delta0, m) {
179
+ const hDim = flatDim(input);
180
+ const flat = intersectFlats(parent.flat, l.within, m.eps);
181
+ if (!flat) return null;
182
+ const dim = flatDim(flat);
183
+ if (dim >= parent.dim) return null;
184
+ const delta = closestOnFlat(flat, delta0);
185
+ if (!isFiniteVec2(delta)) return null;
186
+ const members = [...parent.members, l];
187
+ for (const mem of members) if (meets(m, mem.c, mem.probe, delta) === null) return null;
188
+ const targetFlat = l.c.tier === "target" ? intersectFlats(parent.targetFlat, l.within, m.eps) ?? flat : parent.targetFlat;
189
+ const kept = prune(members, input, dim, flatDim(targetFlat), m.eps);
190
+ let px = 0;
191
+ for (const mem of kept) {
192
+ const p = meets(m, mem.c, mem.probe, delta);
193
+ if (p === null) return null;
194
+ px = Math.max(px, p);
195
+ }
196
+ return {
197
+ members: kept,
198
+ flat,
199
+ dim,
200
+ targetFlat,
201
+ delta,
202
+ px,
203
+ codim: hDim - dim,
204
+ targetCodim: hDim - flatDim(targetFlat)
205
+ };
206
+ }
207
+ function flatsOf(members, input, eps) {
208
+ let flat = input;
209
+ let target = input;
210
+ for (const mem of members) {
211
+ flat = intersectFlats(flat, mem.within, eps);
212
+ if (!flat) return null;
213
+ if (mem.c.tier === "target") target = intersectFlats(target, mem.within, eps) ?? flat;
214
+ }
215
+ return { dim: flatDim(flat), targetDim: flatDim(target) };
216
+ }
217
+ function prune(members, input, dim, targetDim, eps) {
218
+ let kept = members;
219
+ for (let i = 0; i < kept.length && kept.length > 1; ) {
220
+ const rest = kept.filter((_, j) => j !== i);
221
+ const f = flatsOf(rest, input, eps);
222
+ if (f && f.dim === dim && f.targetDim === targetDim) kept = rest;
223
+ else i++;
224
+ }
225
+ return kept;
226
+ }
227
+ function search(candidates, root, delta0, m) {
228
+ const best = { any: root, required: null };
229
+ const consider = (c) => {
230
+ if (compareCombos(c, best.any) < 0) best.any = c;
231
+ if (c.members.some((l) => l.c.required) && (!best.required || compareCombos(c, best.required) < 0)) {
232
+ best.required = c;
233
+ }
234
+ };
235
+ const visit = (start, parent) => {
236
+ for (let i = start; i < candidates.length; i++) {
237
+ const next = extend(parent, candidates[i], root.flat, delta0, m);
238
+ if (!next) continue;
239
+ consider(next);
240
+ if (next.dim > 0) visit(i + 1, next);
241
+ }
242
+ };
243
+ visit(0, root);
244
+ return best.required ?? best.any;
245
+ }
246
+ function satisfiedBy(problem, delta, m) {
247
+ const probes = new Map(problem.probes.map((p) => [p.id, p.at]));
248
+ return problem.candidates.filter((c) => {
249
+ const probe = probes.get(c.probe);
250
+ if (!probe) return false;
251
+ const world = plus(probe, delta);
252
+ if (!(distance(closestOnFlat(c.locus, world), world) <= m.eps)) return false;
253
+ return meets(m, c, probe, delta) !== null;
254
+ });
255
+ }
256
+ function resolveSnap(problem) {
257
+ const { input, delta0 } = problem;
258
+ let base = closestOnFlat(input, delta0);
259
+ if (!isFiniteVec2(base)) base = isFiniteVec2(input.at) ? input.at : input.at.map(() => 0);
260
+ const m = makeMeasure(problem, base, problem.eps ?? DEFAULT_EPS);
261
+ const hDim = flatDim(input);
262
+ const root = {
263
+ members: [],
264
+ flat: input,
265
+ dim: hDim,
266
+ targetFlat: input,
267
+ delta: base,
268
+ codim: 0,
269
+ targetCodim: 0,
270
+ px: 0
271
+ };
272
+ const live = pool(liveCandidates(problem, m), problem.poolSize ?? DEFAULT_POOL);
273
+ const win = search(live, root, delta0, m);
274
+ return {
275
+ delta: win.delta,
276
+ members: win.members.map((l) => l.c),
277
+ satisfied: satisfiedBy(problem, win.delta, m),
278
+ codim: win.codim
279
+ };
280
+ }
281
+
282
+ // src/snap/stepLine.ts
283
+ function stepLine(about, toward, basis, step) {
284
+ const [u, v] = basis;
285
+ let a = 0;
286
+ let b = 0;
287
+ for (let i = 0; i < about.length; i++) {
288
+ const d = toward[i] - about[i];
289
+ a += d * u[i];
290
+ b += d * v[i];
291
+ }
292
+ const theta = a === 0 && b === 0 ? 0 : Math.round(Math.atan2(b, a) / step) * step;
293
+ const c = Math.cos(theta);
294
+ const s = Math.sin(theta);
295
+ return { at: about, dirs: [u.map((x, i) => x * c + v[i] * s)] };
296
+ }
297
+
298
+ export { closestBetweenFlats, closestOnFlat, flatDim, intersectFlats, resolveSnap, stepLine };
2
299
  //# sourceMappingURL=index.js.map
3
300
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
1
+ {"version":3,"sources":["../../src/snap/flat.ts","../../src/snap/resolve.ts","../../src/snap/stepLine.ts"],"names":["isFiniteVec"],"mappings":"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","file":"index.js","sourcesContent":["/** Affine subspaces (\"flats\") over plain number arrays, in any dimension:\n * the points, lines and planes a snap resolves against. */\n\nexport type Vec = readonly number[];\n\n/** The affine subspace `at + span(dirs)`. `dirs` need not be orthonormal or\n * independent; a zero or repeated direction adds nothing. */\nexport interface Flat {\n at: Vec;\n dirs: readonly Vec[];\n}\n\n/** A direction left with less than this fraction of its length after the\n * ones before it are taken out counts as dependent on them. The solve's\n * pivots are those leftover lengths squared, so it shares this one value.\n * Squaring loses angles below about 1e-8 rad to rounding; at 1e-8 the two\n * verdicts part, so this sits two decades clear. */\nconst RANK_TOL = 1e-6;\n\nfunction dotv(a: Vec, b: Vec): number {\n let s = 0;\n for (let i = 0; i < a.length; i++) s += a[i] * b[i];\n return s;\n}\n\nfunction normv(a: Vec): number {\n return Math.sqrt(dotv(a, a));\n}\n\nfunction isFiniteVec(a: Vec): boolean {\n return a.every(Number.isFinite);\n}\n\n/** An orthonormal basis of `span(vecs)`, built by Gram-Schmidt with a second\n * pass for stability. Non-finite and dependent vectors are dropped. */\nexport function orthonormalize(vecs: readonly Vec[], start: readonly Vec[] = []): number[][] {\n const basis: number[][] = start.map((q) => q.slice());\n const out: number[][] = [];\n for (const d of vecs) {\n const n0 = normv(d);\n if (!(n0 > 0) || !isFiniteVec(d)) continue;\n const v = d.slice();\n for (let pass = 0; pass < 2; pass++) {\n for (const q of basis) {\n const k = dotv(v, q);\n for (let i = 0; i < v.length; i++) v[i] -= k * q[i];\n }\n }\n const n = normv(v);\n if (n <= RANK_TOL * n0) continue;\n for (let i = 0; i < v.length; i++) v[i] /= n;\n basis.push(v);\n out.push(v);\n }\n return out;\n}\n\n/** An orthonormal basis of the orthogonal complement of the orthonormal `basis` in R^n. */\nfunction complement(basis: readonly Vec[], n: number): number[][] {\n const axes: number[][] = [];\n for (let i = 0; i < n; i++) axes.push(Array.from({ length: n }, (_, j) => (i === j ? 1 : 0)));\n return orthonormalize(axes, basis);\n}\n\n/** The flat's dimension: the rank of its directions. */\nexport function flatDim(f: Flat): number {\n return orthonormalize(f.dirs).length;\n}\n\n/** The point of `f` nearest `p`. */\nexport function closestOnFlat(f: Flat, p: Vec): Vec {\n const out = f.at.slice();\n for (const q of orthonormalize(f.dirs)) {\n let k = 0;\n for (let i = 0; i < q.length; i++) k += q[i] * (p[i] - f.at[i]);\n for (let i = 0; i < out.length; i++) out[i] += k * q[i];\n }\n return out;\n}\n\n/**\n * The `x` minimizing `|Σ x_j cols_j − rhs|`, through the normal equations.\n * A column within `RANK_TOL` of the span of the kept ones before it is\n * dropped, the same verdict `orthonormalize` reaches, and its unknown is zero.\n */\nexport function solveLeastSquares(cols: readonly Vec[], rhs: Vec): number[] {\n const k = cols.length;\n const m = cols.map((a) => [...cols.map((b) => dotv(a, b)), dotv(a, rhs)]);\n const len2 = m.map((r, i) => r[i]);\n const kept: number[] = [];\n for (let col = 0; col < k; col++) {\n if (!(m[col][col] > RANK_TOL * RANK_TOL * len2[col])) continue;\n for (let r = col + 1; r < k; r++) {\n const f = m[r][col] / m[col][col];\n for (let c = col; c <= k; c++) m[r][c] -= f * m[col][c];\n }\n kept.push(col);\n }\n const x = new Array<number>(k).fill(0);\n for (let p = kept.length - 1; p >= 0; p--) {\n const col = kept[p];\n let s = m[col][k];\n for (let c = col + 1; c < k; c++) s -= m[col][c] * x[c];\n x[col] = s / m[col][col];\n }\n return x;\n}\n\n/** The nearest pair of points, one on each flat. Parallel flats have many\n * such pairs; this returns one of them. */\nexport function closestBetweenFlats(a: Flat, b: Flat): { onA: Vec; onB: Vec } {\n const qa = orthonormalize(a.dirs);\n const qb = orthonormalize(b.dirs);\n const d = b.at.map((v, i) => v - a.at[i]);\n const x = solveLeastSquares([...qa, ...qb.map((q) => q.map((v) => -v))], d);\n const onA = a.at.slice();\n const onB = b.at.slice();\n qa.forEach((q, j) => q.forEach((v, i) => { onA[i] += x[j] * v; }));\n qb.forEach((q, j) => q.forEach((v, i) => { onB[i] += x[qa.length + j] * v; }));\n return { onA, onB };\n}\n\n/** `a ∩ b`, or null when they miss each other by more than `eps`. */\nexport function intersectFlats(a: Flat, b: Flat, eps = 1e-6): Flat | null {\n const { onA, onB } = closestBetweenFlats(a, b);\n let gap2 = 0;\n for (let i = 0; i < onA.length; i++) gap2 += (onA[i] - onB[i]) ** 2;\n if (!(Math.sqrt(gap2) <= eps) || !isFiniteVec(onA)) return null;\n const n = a.at.length;\n const normals = orthonormalize([\n ...complement(orthonormalize(a.dirs), n),\n ...complement(orthonormalize(b.dirs), n),\n ]);\n return { at: onA, dirs: complement(normals, n) };\n}\n","/** The snap resolver: every gesture's snap, in any dimension, as one search\n * over affine constraints on the move `δ`. */\n\nimport { closestOnFlat, flatDim, intersectFlats, solveLeastSquares, type Flat, type Vec } from './flat';\n\n/** A `fallback` candidate holds only the axes no `target` claims. */\nexport type SnapTier = 'target' | 'fallback';\n/** What a probe stands for on the subject; sources match probes by role. */\nexport type ProbeRole = 'origin' | 'box' | 'geometry' | 'pointer';\n\n/** A point on the subject that should land on a locus. `role` says which\n * sources may match it. */\nexport interface SnapProbe {\n id: string;\n at: Vec;\n role: ProbeRole;\n}\n\n/** One probe paired with one locus. `M` is the mark payload, opaque here. */\nexport interface SnapCandidate<M> {\n /** `SnapProbe.id`. */\n probe: string;\n locus: Flat;\n /** One interval per locus dir, in multiples of that dir. A solution\n * outside it fails the candidate. */\n span?: readonly (readonly [number, number])[];\n source: string;\n /** Stable tiebreak: lower wins when everything else is equal. */\n order: number;\n tier: SnapTier;\n reachPx: number;\n /** When any required candidate exists, the result includes one of them,\n * whatever its reach. */\n required?: boolean;\n mark?: M;\n}\n\n/** One frame's snap: the probes, the input subspace, the raw move, and the candidates. */\nexport interface SnapProblem<M> {\n probes: readonly SnapProbe[];\n /** `H`, the subspace of δ-space the result stays inside. */\n input: Flat;\n /** The unsnapped move. */\n delta0: Vec;\n candidates: readonly SnapCandidate<M>[];\n /** World to screen pixels. A non-finite result puts that position out of reach. */\n toScreen(world: Vec): Vec;\n /** Candidates kept per probe, nearest first, besides the required ones,\n * which are all kept. Default 24. */\n poolSize?: number;\n /** World-space tolerance for \"on the locus\". Default 1e-6. */\n eps?: number;\n}\n\n/** The move `resolveSnap` chose and the candidates it meets. */\nexport interface SnapResolution<M> {\n /** `closestOnFlat(input, delta0)` when nothing snaps. */\n delta: Vec;\n members: readonly SnapCandidate<M>[];\n /** Every in-reach candidate the result meets: the ones whose marks show. */\n satisfied: readonly SnapCandidate<M>[];\n /** How many dimensions of `H` the result pins. */\n codim: number;\n}\n\n/** A candidate that can be met on its own: its probe, and `H ∩ C` in δ-space. */\ninterface Live<M> {\n c: SnapCandidate<M>;\n probe: Vec;\n within: Flat;\n px: number;\n}\n\ninterface Combo<M> {\n members: Live<M>[];\n flat: Flat;\n dim: number;\n targetFlat: Flat;\n delta: Vec;\n codim: number;\n targetCodim: number;\n px: number;\n}\n\nconst DEFAULT_POOL = 24;\nconst DEFAULT_EPS = 1e-6;\n/** Screen displacements closer than this rank as equal, so order decides. */\nconst SAME_PX = 1e-9;\n\nconst plus = (a: Vec, b: Vec): Vec => a.map((v, i) => v + b[i]);\nconst minus = (a: Vec, b: Vec): Vec => a.map((v, i) => v - b[i]);\nconst isFiniteVec = (a: Vec): boolean => a.every(Number.isFinite);\n\nfunction distance(a: Vec, b: Vec): number {\n let s = 0;\n for (let i = 0; i < a.length; i++) s += (a[i] - b[i]) ** 2;\n return Math.sqrt(s);\n}\n\n/** What the resolver needs to measure a candidate against a trial δ. */\ninterface Measure {\n /** Screen pixels the probe moves going from δ0 (projected into `H`) to\n * `delta`; NaN when either end has no finite screen position. */\n move(probeId: string, probe: Vec, delta: Vec): number;\n eps: number;\n}\n\nfunction makeMeasure<M>(problem: SnapProblem<M>, base: Vec, eps: number): Measure {\n const home = new Map<string, Vec>();\n return {\n eps,\n move(probeId, probe, delta) {\n let h = home.get(probeId);\n if (!h) home.set(probeId, (h = problem.toScreen(plus(probe, base))));\n const d = distance(problem.toScreen(plus(probe, delta)), h);\n return Number.isFinite(d) ? d : NaN;\n },\n };\n}\n\nfunction spanHolds<M>(c: SnapCandidate<M>, world: Vec, eps: number): boolean {\n if (!c.span) return true;\n const u = solveLeastSquares(c.locus.dirs, minus(world, c.locus.at));\n return c.span.every(([lo, hi], i) => u[i] >= lo - eps && u[i] <= hi + eps);\n}\n\n/** The probe's screen move under `delta`, or null when it is out of reach or off the span. */\nfunction meets<M>(m: Measure, c: SnapCandidate<M>, probe: Vec, delta: Vec): number | null {\n const measured = m.move(c.probe, probe, delta);\n if (!c.required && (Number.isNaN(measured) || !(measured <= c.reachPx))) return null;\n const px = Number.isNaN(measured) ? Infinity : measured;\n return spanHolds(c, plus(probe, delta), m.eps) ? px : null;\n}\n\nfunction liveCandidates<M>(problem: SnapProblem<M>, m: Measure): Live<M>[] {\n const probes = new Map(problem.probes.map((p) => [p.id, p.at]));\n const live: Live<M>[] = [];\n for (const c of problem.candidates) {\n const probe = probes.get(c.probe);\n if (!probe || !isFiniteVec(probe) || !isFiniteVec(c.locus.at) || !c.locus.dirs.every(isFiniteVec)) continue;\n const within = intersectFlats(problem.input, { at: minus(c.locus.at, probe), dirs: c.locus.dirs }, m.eps);\n if (!within) continue;\n const px = meets(m, c, probe, closestOnFlat(within, problem.delta0));\n if (px !== null) live.push({ c, probe, within, px });\n }\n return live;\n}\n\nfunction pool<M>(live: Live<M>[], size: number): Live<M>[] {\n const byProbe = new Map<string, Live<M>[]>();\n for (const l of live) {\n const list = byProbe.get(l.c.probe) ?? [];\n list.push(l);\n byProbe.set(l.c.probe, list);\n }\n const out: Live<M>[] = [];\n for (const list of byProbe.values()) {\n list.sort((a, b) => (Math.abs(a.px - b.px) > SAME_PX ? a.px - b.px : a.c.order - b.c.order));\n out.push(...list.filter((l, i) => i < size || l.c.required));\n }\n return out;\n}\n\nfunction compareOrders<M>(a: Live<M>[], b: Live<M>[]): number {\n const oa = a.map((l) => l.c.order).sort((x, y) => x - y);\n const ob = b.map((l) => l.c.order).sort((x, y) => x - y);\n for (let i = 0; i < Math.min(oa.length, ob.length); i++) if (oa[i] !== ob[i]) return oa[i] - ob[i];\n return oa.length - ob.length;\n}\n\n/** Negative when `a` ranks ahead of `b`. */\nfunction compareCombos<M>(a: Combo<M>, b: Combo<M>): number {\n if (a.codim !== b.codim) return b.codim - a.codim;\n if (a.targetCodim !== b.targetCodim) return b.targetCodim - a.targetCodim;\n if (Math.abs(a.px - b.px) > SAME_PX) return a.px - b.px;\n return compareOrders(a.members, b.members);\n}\n\n/** `parent` plus `l`, or null when `l` adds no constraint or breaks a member's reach or span. */\nfunction extend<M>(parent: Combo<M>, l: Live<M>, input: Flat, delta0: Vec, m: Measure): Combo<M> | null {\n const hDim = flatDim(input);\n const flat = intersectFlats(parent.flat, l.within, m.eps);\n if (!flat) return null;\n const dim = flatDim(flat);\n if (dim >= parent.dim) return null;\n const delta = closestOnFlat(flat, delta0);\n if (!isFiniteVec(delta)) return null;\n const members = [...parent.members, l];\n for (const mem of members) if (meets(m, mem.c, mem.probe, delta) === null) return null;\n const targetFlat = l.c.tier === 'target'\n ? intersectFlats(parent.targetFlat, l.within, m.eps) ?? flat\n : parent.targetFlat;\n const kept = prune(members, input, dim, flatDim(targetFlat), m.eps);\n let px = 0;\n for (const mem of kept) {\n const p = meets(m, mem.c, mem.probe, delta);\n if (p === null) return null;\n px = Math.max(px, p);\n }\n return {\n members: kept, flat, dim, targetFlat, delta, px,\n codim: hDim - dim,\n targetCodim: hDim - flatDim(targetFlat),\n };\n}\n\n/** The flat `members` pin inside `input`, and the one their target-tier members pin. */\nfunction flatsOf<M>(members: readonly Live<M>[], input: Flat, eps: number): { dim: number; targetDim: number } | null {\n let flat: Flat | null = input;\n let target: Flat = input;\n for (const mem of members) {\n flat = intersectFlats(flat, mem.within, eps);\n if (!flat) return null;\n if (mem.c.tier === 'target') target = intersectFlats(target, mem.within, eps) ?? flat;\n }\n return { dim: flatDim(flat), targetDim: flatDim(target) };\n}\n\n/** `members` less every one the rest already imply, oldest first, so a\n * redundant member neither shows in `members` nor decides a tie on order. */\nfunction prune<M>(members: Live<M>[], input: Flat, dim: number, targetDim: number, eps: number): Live<M>[] {\n let kept = members;\n for (let i = 0; i < kept.length && kept.length > 1;) {\n const rest = kept.filter((_, j) => j !== i);\n const f = flatsOf(rest, input, eps);\n if (f && f.dim === dim && f.targetDim === targetDim) kept = rest;\n else i++;\n }\n return kept;\n}\n\n/** The best combination; when any can include a required candidate, the best of those. */\nfunction search<M>(candidates: Live<M>[], root: Combo<M>, delta0: Vec, m: Measure): Combo<M> {\n const best: { any: Combo<M>; required: Combo<M> | null } = { any: root, required: null };\n const consider = (c: Combo<M>) => {\n if (compareCombos(c, best.any) < 0) best.any = c;\n if (c.members.some((l) => l.c.required) && (!best.required || compareCombos(c, best.required) < 0)) {\n best.required = c;\n }\n };\n const visit = (start: number, parent: Combo<M>) => {\n for (let i = start; i < candidates.length; i++) {\n const next = extend(parent, candidates[i], root.flat, delta0, m);\n if (!next) continue;\n consider(next);\n if (next.dim > 0) visit(i + 1, next);\n }\n };\n visit(0, root);\n return best.required ?? best.any;\n}\n\nfunction satisfiedBy<M>(problem: SnapProblem<M>, delta: Vec, m: Measure): SnapCandidate<M>[] {\n const probes = new Map(problem.probes.map((p) => [p.id, p.at]));\n return problem.candidates.filter((c) => {\n const probe = probes.get(c.probe);\n if (!probe) return false;\n const world = plus(probe, delta);\n if (!(distance(closestOnFlat(c.locus, world), world) <= m.eps)) return false;\n return meets(m, c, probe, delta) !== null;\n });\n}\n\n/** The move nearest `delta0` within `H` that meets the best-ranked set of\n * candidates in reach, or `delta0` projected into `H` when none is. */\nexport function resolveSnap<M>(problem: SnapProblem<M>): SnapResolution<M> {\n const { input, delta0 } = problem;\n let base = closestOnFlat(input, delta0);\n if (!isFiniteVec(base)) base = isFiniteVec(input.at) ? input.at : input.at.map(() => 0);\n const m = makeMeasure(problem, base, problem.eps ?? DEFAULT_EPS);\n const hDim = flatDim(input);\n const root: Combo<M> = {\n members: [], flat: input, dim: hDim, targetFlat: input, delta: base, codim: 0, targetCodim: 0, px: 0,\n };\n const live = pool(liveCandidates(problem, m), problem.poolSize ?? DEFAULT_POOL);\n const win = search(live, root, delta0, m);\n return {\n delta: win.delta,\n members: win.members.map((l) => l.c),\n satisfied: satisfiedBy(problem, win.delta, m),\n codim: win.codim,\n };\n}\n","import type { Flat, Vec } from './flat';\n\n/**\n * The line through `about` whose direction, measured in the plane `basis`\n * spans (as an angle from `basis[0]` toward `basis[1]`), is the multiple of\n * `step` nearest the direction from `about` to `toward`: a constrained\n * gesture's input subspace, in any dimension. `basis` is orthonormal.\n */\nexport function stepLine(about: Vec, toward: Vec, basis: readonly [Vec, Vec], step: number): Flat {\n const [u, v] = basis;\n let a = 0;\n let b = 0;\n for (let i = 0; i < about.length; i++) {\n const d = toward[i] - about[i];\n a += d * u[i];\n b += d * v[i];\n }\n const theta = a === 0 && b === 0 ? 0 : Math.round(Math.atan2(b, a) / step) * step;\n const c = Math.cos(theta);\n const s = Math.sin(theta);\n return { at: about, dirs: [u.map((x, i) => x * c + v[i] * s)] };\n}\n"]}
@@ -0,0 +1,157 @@
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
+ /** De Casteljau subdivision of a cubic at parameter t. The point-shaped face
10
+ * of geom's `splitCubicAt`; `left[3]` and `right[0]` are the point at t. */
11
+ declare function splitCubicAtT(p0: Point, p1: Point, p2: Point, p3: Point, t: number): {
12
+ left: [Point, Point, Point, Point];
13
+ right: [Point, Point, Point, Point];
14
+ };
15
+
16
+ /** The six `corner-shape` keywords, from most convex to most concave. */
17
+ type CornerKeyword = 'square' | 'squircle' | 'round' | 'bevel' | 'scoop' | 'notch';
18
+ /** A corner's shape: a keyword, or a finite `superellipse()` parameter. */
19
+ type CornerShape = CornerKeyword | number;
20
+ /** The keywords in the order cycling through them steps. */
21
+ declare const CORNER_KEYWORDS: readonly CornerKeyword[];
22
+ /** The `superellipse()` parameter of `shape`. */
23
+ declare function cornerShapeK(shape: CornerShape): number;
24
+ /** The keyword whose parameter is exactly `k`, or null. */
25
+ declare function cornerKeywordOf(k: number): CornerKeyword | null;
26
+ /** Whether `v` is a keyword or a finite number. */
27
+ declare function isCornerShape(v: unknown): v is CornerShape;
28
+ /** The keyword after `shape` in {@link CORNER_KEYWORDS}, wrapping; from a
29
+ * number, the first keyword less convex than it. */
30
+ declare function nextCornerShape(shape: CornerShape): CornerKeyword;
31
+ /** Largest distance, in units of the corner's setback, the fitted cubics may
32
+ * stray from the true superellipse. */
33
+ declare const CORNER_FIT_TOLERANCE = 0.001;
34
+ /** The cut a corner shape spans: from `start` to `end`, the two points where
35
+ * it leaves the edges, around `outer`, the corner the edges meet at. */
36
+ interface CornerShapeFrame {
37
+ start: Point;
38
+ end: Point;
39
+ outer: Point;
40
+ }
41
+ /** One piece of a corner's outline, continuing from where the last ended. */
42
+ type CornerPiece = {
43
+ kind: 'line';
44
+ to: Point;
45
+ } | {
46
+ kind: 'cubic';
47
+ c1: Point;
48
+ c2: Point;
49
+ to: Point;
50
+ };
51
+ /** The center the convex curves are spanned from: across the cut from `outer`. */
52
+ declare function cornerCenter(frame: CornerShapeFrame): Point;
53
+ /**
54
+ * The outline of a corner of parameter `k` across `frame`, from its start to
55
+ * its end. Exact at `k = 0` (a line), `±1` (the cubic quarter arc the kit
56
+ * draws circles with) and `±∞` (two lines, through the outer corner or the
57
+ * center); fitted with cubics within `tolerance` of the setback elsewhere.
58
+ */
59
+ declare function cornerShapePieces(k: number, frame: CornerShapeFrame, tolerance?: number): CornerPiece[];
60
+ /** The point on the true curve of parameter `k` across `frame` at `s`, from
61
+ * 0 at its start to 1 at its end. Finite `k` only. */
62
+ declare function cornerShapePoint(k: number, frame: CornerShapeFrame, s: number): Point;
63
+
64
+ /**
65
+ * Per-anchor corner specs: the stored half of corner shapes. A path carries
66
+ * them in `PolygonPath.corners`, indexed by flat anchor index, and every
67
+ * reader of its geometry sees them expanded (`resolveCorners`).
68
+ */
69
+
70
+ /** The corner at one anchor: its shape, and its setback, how far along each
71
+ * edge from the anchor the cut starts. A `round` corner between edges at a
72
+ * right angle is a circle of that radius. */
73
+ interface CornerSpec {
74
+ shape: CornerShape;
75
+ radius: number;
76
+ }
77
+ /** The corner cut at flat anchor `index`, or null. A zero radius cuts nothing. */
78
+ declare function cornerAt(path: PolygonPath, index: number): CornerSpec | null;
79
+ /** The spec stored at flat anchor `index`, radius zero included: a shape
80
+ * picked before any radius is dragged out. */
81
+ declare function cornerSpecAt(path: PolygonPath, index: number): CornerSpec | null;
82
+ /** Whether any anchor of `path` carries a corner with a radius. */
83
+ declare function hasCorners(path: {
84
+ kind: string;
85
+ corners?: PolygonPath['corners'];
86
+ }): boolean;
87
+ /** `corners` without trailing empty slots, or undefined when none is left. */
88
+ declare function compactCorners(corners: readonly (CornerSpec | null | undefined)[]): (CornerSpec | null)[] | undefined;
89
+ /** `path` without its corner specs: the bare anchors the specs decorate. */
90
+ declare function withoutCorners(path: PolygonPath): PolygonPath;
91
+ /** `path` with the corner at flat anchor `index` set to `spec`, or cleared
92
+ * when `spec` is null. A zero radius keeps the shape and cuts nothing.
93
+ * Never mutates `path`. */
94
+ declare function withCorner(path: PolygonPath, index: number, spec: CornerSpec | null): PolygonPath;
95
+ /** `path` with every corner radius multiplied by `factor`, as a uniform
96
+ * scale of its geometry would carry them. */
97
+ declare function scaleCorners(path: PolygonPath, factor: number): PolygonPath;
98
+ /**
99
+ * The corners of a path `t` of the way from `a` to `b`, which share their
100
+ * anchors. A corner whose shape both ends agree on, or that one end leaves
101
+ * sharp, grows its radius between them; one whose shape changes takes the
102
+ * nearer end's.
103
+ */
104
+ declare function lerpCorners(a: PolygonPath['corners'], b: PolygonPath['corners'], t: number): (CornerSpec | null)[] | undefined;
105
+
106
+ /**
107
+ * Path data model: the vector-graphics primitive every weasel package uses as
108
+ * its canonical shape. An SVG-style command stream covers lines, polygons,
109
+ * beziers and multi-contour shapes (the inner hole of an "O") under one type.
110
+ *
111
+ * Storage: command codes in a `Uint8Array`, parameters in a `Float32Array`.
112
+ * Each command consumes a fixed number of coords (`PATH_CMD_LENGTHS`); walkers
113
+ * step both arrays in lockstep.
114
+ */
115
+
116
+ /** Fill rule used by polygon path hit-testing and `ctx.fill()`. */
117
+ type PathFillRule = 'nonzero' | 'evenodd';
118
+ /** Whether a fill closes an open subpath with a straight edge back to its
119
+ * start, as SVG and canvas do (`'close'`), or leaves it unfilled (`'none'`). */
120
+ type PathOpenFill = 'close' | 'none';
121
+ /**
122
+ * Polygon path with arbitrary contours and optional bezier segments.
123
+ * Multi-contour: each `M` opens a new subpath; `Z` closes the current one.
124
+ * An open subpath (no `Z`) strokes as a polyline; `openFill` says whether it
125
+ * fills.
126
+ */
127
+ interface PolygonPath {
128
+ kind: 'polygon';
129
+ commands: Uint8Array;
130
+ coords: Float32Array;
131
+ fillRule: PathFillRule;
132
+ /** Absent, the engine default: see `setDefaultOpenFill`. */
133
+ openFill?: PathOpenFill;
134
+ /**
135
+ * Corner shapes, indexed by flat anchor index (`enumerateAnchors` order):
136
+ * the anchor at each non-null slot is cut in a `corner-shape`
137
+ * (`cornerShape.ts`). The commands and coords hold the bare anchors; `resolveCorners`
138
+ * expands the specs into the geometry everything draws, hits, and bounds.
139
+ */
140
+ corners?: readonly (CornerSpec | null)[];
141
+ }
142
+ /**
143
+ * Axis-aligned rectangle. Fast path for the (very common) case where the
144
+ * shape is just a rect — preserves O(1) bounds and hit-test, avoids the
145
+ * polygon kernel entirely.
146
+ */
147
+ interface RectPath {
148
+ kind: 'rect';
149
+ x: number;
150
+ y: number;
151
+ width: number;
152
+ height: number;
153
+ }
154
+ /** Canonical path shape — either an axis-aligned rect (fast path) or a polygon command stream. */
155
+ type Path = PolygonPath | RectPath;
156
+
157
+ export { withoutCorners as A, type CornerSpec as C, type PolygonPath as P, type RectPath as R, type Path as a, type Point as b, type PathOpenFill as c, type PathFillRule as d, type CornerPiece as e, CORNER_FIT_TOLERANCE as f, CORNER_KEYWORDS as g, type CornerKeyword as h, type CornerShape as i, type CornerShapeFrame as j, compactCorners as k, cornerAt as l, cornerCenter as m, cornerKeywordOf as n, cornerShapeK as o, cornerShapePieces as p, cornerShapePoint as q, cornerSpecAt as r, cubicPointAt as s, hasCorners as t, isCornerShape as u, lerpCorners as v, nextCornerShape as w, scaleCorners as x, splitCubicAtT as y, withCorner as z };