@weasel-js/geom 1.11.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/booleans/index.d.ts +3 -1
- package/dist/booleans/index.js +138 -11
- package/dist/booleans/index.js.map +1 -1
- package/dist/{chunk-J2O2B54M.js → chunk-2PKPKU4P.js} +178 -174
- package/dist/chunk-2PKPKU4P.js.map +1 -0
- package/dist/{chunk-HGF5OVEN.js → chunk-STGSBIOL.js} +29 -6
- package/dist/chunk-STGSBIOL.js.map +1 -0
- package/dist/{chunk-SASMXDBE.js → chunk-UGE57OTX.js} +83 -35
- package/dist/chunk-UGE57OTX.js.map +1 -0
- package/dist/{chunk-6XSJY3TC.js → chunk-VHXOCDZ2.js} +3 -3
- package/dist/{chunk-6XSJY3TC.js.map → chunk-VHXOCDZ2.js.map} +1 -1
- package/dist/{chunk-7KLJZFBY.js → chunk-YPWFGFQX.js} +3 -3
- package/dist/{chunk-7KLJZFBY.js.map → chunk-YPWFGFQX.js.map} +1 -1
- package/dist/index.d.ts +261 -42
- package/dist/index.js +786 -124
- package/dist/index.js.map +1 -1
- package/dist/nd/index.d.ts +2 -1
- package/dist/nd/index.js +44 -29
- package/dist/nd/index.js.map +1 -1
- package/dist/tessellate/index.js +3 -3
- package/dist/warp/index.d.ts +7 -5
- package/dist/warp/index.js +145 -13
- package/dist/warp/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-HGF5OVEN.js.map +0 -1
- package/dist/chunk-J2O2B54M.js.map +0 -1
- package/dist/chunk-SASMXDBE.js.map +0 -1
package/dist/nd/index.d.ts
CHANGED
|
@@ -64,7 +64,8 @@ interface SnapProblem<M> {
|
|
|
64
64
|
candidates: readonly SnapCandidate<M>[];
|
|
65
65
|
/** World to screen pixels. A non-finite result puts that position out of reach. */
|
|
66
66
|
toScreen(world: Vec): Vec;
|
|
67
|
-
/** Candidates kept per probe, nearest first
|
|
67
|
+
/** Candidates kept per probe, nearest first, besides the required ones,
|
|
68
|
+
* which are all kept. Default 24. */
|
|
68
69
|
poolSize?: number;
|
|
69
70
|
/** World-space tolerance for "on the locus". Default 1e-6. */
|
|
70
71
|
eps?: number;
|
package/dist/nd/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export { PORT_REACH, cubicAt, portControls, portCurvePoints } from '../chunk-YQADYJJ7.js';
|
|
2
2
|
|
|
3
3
|
// src/snap/flat.ts
|
|
4
|
-
var RANK_TOL = 1e-
|
|
5
|
-
var PIVOT_TOL = 1e-12;
|
|
4
|
+
var RANK_TOL = 1e-6;
|
|
6
5
|
function dotv(a, b) {
|
|
7
6
|
let s = 0;
|
|
8
7
|
for (let i = 0; i < a.length; i++) s += a[i] * b[i];
|
|
@@ -55,29 +54,22 @@ function closestOnFlat(f, p) {
|
|
|
55
54
|
function solveLeastSquares(cols, rhs) {
|
|
56
55
|
const k = cols.length;
|
|
57
56
|
const m = cols.map((a) => [...cols.map((b) => dotv(a, b)), dotv(a, rhs)]);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
for (let r = row + 1; r < k; r++) if (Math.abs(m[r][col]) > Math.abs(m[best][col])) best = r;
|
|
66
|
-
if (!(Math.abs(m[best][col]) > tol)) continue;
|
|
67
|
-
[m[row], m[best]] = [m[best], m[row]];
|
|
68
|
-
for (let r = row + 1; r < k; r++) {
|
|
69
|
-
const f = m[r][col] / m[row][col];
|
|
70
|
-
for (let c = col; c <= k; c++) m[r][c] -= f * m[row][c];
|
|
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];
|
|
71
64
|
}
|
|
72
|
-
|
|
73
|
-
row++;
|
|
65
|
+
kept.push(col);
|
|
74
66
|
}
|
|
75
67
|
const x = new Array(k).fill(0);
|
|
76
|
-
for (let p =
|
|
77
|
-
const
|
|
78
|
-
let s = m[
|
|
79
|
-
for (let c = col + 1; c < k; c++) s -= m[
|
|
80
|
-
x[col] = s / m[
|
|
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];
|
|
81
73
|
}
|
|
82
74
|
return x;
|
|
83
75
|
}
|
|
@@ -149,7 +141,7 @@ function liveCandidates(problem, m) {
|
|
|
149
141
|
const live = [];
|
|
150
142
|
for (const c of problem.candidates) {
|
|
151
143
|
const probe = probes.get(c.probe);
|
|
152
|
-
if (!probe || !isFiniteVec2(probe) || !isFiniteVec2(c.locus.at)) continue;
|
|
144
|
+
if (!probe || !isFiniteVec2(probe) || !isFiniteVec2(c.locus.at) || !c.locus.dirs.every(isFiniteVec2)) continue;
|
|
153
145
|
const within = intersectFlats(problem.input, { at: minus(c.locus.at, probe), dirs: c.locus.dirs }, m.eps);
|
|
154
146
|
if (!within) continue;
|
|
155
147
|
const px = meets(m, c, probe, closestOnFlat(within, problem.delta0));
|
|
@@ -167,7 +159,7 @@ function pool(live, size) {
|
|
|
167
159
|
const out = [];
|
|
168
160
|
for (const list of byProbe.values()) {
|
|
169
161
|
list.sort((a, b) => Math.abs(a.px - b.px) > SAME_PX ? a.px - b.px : a.c.order - b.c.order);
|
|
170
|
-
out.push(...list.
|
|
162
|
+
out.push(...list.filter((l, i) => i < size || l.c.required));
|
|
171
163
|
}
|
|
172
164
|
return out;
|
|
173
165
|
}
|
|
@@ -183,7 +175,8 @@ function compareCombos(a, b) {
|
|
|
183
175
|
if (Math.abs(a.px - b.px) > SAME_PX) return a.px - b.px;
|
|
184
176
|
return compareOrders(a.members, b.members);
|
|
185
177
|
}
|
|
186
|
-
function extend(parent, l,
|
|
178
|
+
function extend(parent, l, input, delta0, m) {
|
|
179
|
+
const hDim = flatDim(input);
|
|
187
180
|
const flat = intersectFlats(parent.flat, l.within, m.eps);
|
|
188
181
|
if (!flat) return null;
|
|
189
182
|
const dim = flatDim(flat);
|
|
@@ -191,15 +184,17 @@ function extend(parent, l, hDim, delta0, m) {
|
|
|
191
184
|
const delta = closestOnFlat(flat, delta0);
|
|
192
185
|
if (!isFiniteVec2(delta)) return null;
|
|
193
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);
|
|
194
190
|
let px = 0;
|
|
195
|
-
for (const mem of
|
|
191
|
+
for (const mem of kept) {
|
|
196
192
|
const p = meets(m, mem.c, mem.probe, delta);
|
|
197
193
|
if (p === null) return null;
|
|
198
194
|
px = Math.max(px, p);
|
|
199
195
|
}
|
|
200
|
-
const targetFlat = l.c.tier === "target" ? intersectFlats(parent.targetFlat, l.within, m.eps) ?? flat : parent.targetFlat;
|
|
201
196
|
return {
|
|
202
|
-
members,
|
|
197
|
+
members: kept,
|
|
203
198
|
flat,
|
|
204
199
|
dim,
|
|
205
200
|
targetFlat,
|
|
@@ -209,6 +204,26 @@ function extend(parent, l, hDim, delta0, m) {
|
|
|
209
204
|
targetCodim: hDim - flatDim(targetFlat)
|
|
210
205
|
};
|
|
211
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
|
+
}
|
|
212
227
|
function search(candidates, root, delta0, m) {
|
|
213
228
|
const best = { any: root, required: null };
|
|
214
229
|
const consider = (c) => {
|
|
@@ -219,7 +234,7 @@ function search(candidates, root, delta0, m) {
|
|
|
219
234
|
};
|
|
220
235
|
const visit = (start, parent) => {
|
|
221
236
|
for (let i = start; i < candidates.length; i++) {
|
|
222
|
-
const next = extend(parent, candidates[i], root.
|
|
237
|
+
const next = extend(parent, candidates[i], root.flat, delta0, m);
|
|
223
238
|
if (!next) continue;
|
|
224
239
|
consider(next);
|
|
225
240
|
if (next.dim > 0) visit(i + 1, next);
|
package/dist/nd/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/snap/flat.ts","../../src/snap/resolve.ts","../../src/snap/stepLine.ts"],"names":["isFiniteVec"],"mappings":";;;AAcA,IAAM,QAAA,GAAW,IAAA;AAEjB,IAAM,SAAA,GAAY,KAAA;AAElB,SAAS,IAAA,CAAK,GAAQ,CAAA,EAAgB;AACpC,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,CAAE,MAAA,EAAQ,CAAA,EAAA,EAAK,CAAA,IAAK,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA;AAClD,EAAA,OAAO,CAAA;AACT;AAEA,SAAS,MAAM,CAAA,EAAgB;AAC7B,EAAA,OAAO,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,CAAA,EAAG,CAAC,CAAC,CAAA;AAC7B;AAEA,SAAS,YAAY,CAAA,EAAiB;AACpC,EAAA,OAAO,CAAA,CAAE,KAAA,CAAM,MAAA,CAAO,QAAQ,CAAA;AAChC;AAIO,SAAS,cAAA,CAAe,IAAA,EAAsB,KAAA,GAAwB,EAAC,EAAe;AAC3F,EAAA,MAAM,QAAoB,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,CAAA;AACpD,EAAA,MAAM,MAAkB,EAAC;AACzB,EAAA,KAAA,MAAW,KAAK,IAAA,EAAM;AACpB,IAAA,MAAM,EAAA,GAAK,MAAM,CAAC,CAAA;AAClB,IAAA,IAAI,EAAE,EAAA,GAAK,CAAA,CAAA,IAAM,CAAC,WAAA,CAAY,CAAC,CAAA,EAAG;AAClC,IAAA,MAAM,CAAA,GAAI,EAAE,KAAA,EAAM;AAClB,IAAA,KAAA,IAAS,IAAA,GAAO,CAAA,EAAG,IAAA,GAAO,CAAA,EAAG,IAAA,EAAA,EAAQ;AACnC,MAAA,KAAA,MAAW,KAAK,KAAA,EAAO;AACrB,QAAA,MAAM,CAAA,GAAI,IAAA,CAAK,CAAA,EAAG,CAAC,CAAA;AACnB,QAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,CAAE,MAAA,EAAQ,CAAA,EAAA,EAAK,CAAA,CAAE,CAAC,CAAA,IAAK,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA;AAAA,MACpD;AAAA,IACF;AACA,IAAA,MAAM,CAAA,GAAI,MAAM,CAAC,CAAA;AACjB,IAAA,IAAI,CAAA,IAAK,WAAW,EAAA,EAAI;AACxB,IAAA,KAAA,IAAS,CAAA,GAAI,GAAG,CAAA,GAAI,CAAA,CAAE,QAAQ,CAAA,EAAA,EAAK,CAAA,CAAE,CAAC,CAAA,IAAK,CAAA;AAC3C,IAAA,KAAA,CAAM,KAAK,CAAC,CAAA;AACZ,IAAA,GAAA,CAAI,KAAK,CAAC,CAAA;AAAA,EACZ;AACA,EAAA,OAAO,GAAA;AACT;AAGA,SAAS,UAAA,CAAW,OAAuB,CAAA,EAAuB;AAChE,EAAA,MAAM,OAAmB,EAAC;AAC1B,EAAA,KAAA,IAAS,CAAA,GAAI,GAAG,CAAA,GAAI,CAAA,EAAG,KAAK,IAAA,CAAK,IAAA,CAAK,MAAM,IAAA,CAAK,EAAE,QAAQ,CAAA,EAAE,EAAG,CAAC,CAAA,EAAG,CAAA,KAAO,MAAM,CAAA,GAAI,CAAA,GAAI,CAAE,CAAC,CAAA;AAC5F,EAAA,OAAO,cAAA,CAAe,MAAM,KAAK,CAAA;AACnC;AAGO,SAAS,QAAQ,CAAA,EAAiB;AACvC,EAAA,OAAO,cAAA,CAAe,CAAA,CAAE,IAAI,CAAA,CAAE,MAAA;AAChC;AAGO,SAAS,aAAA,CAAc,GAAS,CAAA,EAAa;AAClD,EAAA,MAAM,GAAA,GAAM,CAAA,CAAE,EAAA,CAAG,KAAA,EAAM;AACvB,EAAA,KAAA,MAAW,CAAA,IAAK,cAAA,CAAe,CAAA,CAAE,IAAI,CAAA,EAAG;AACtC,IAAA,IAAI,CAAA,GAAI,CAAA;AACR,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,CAAE,QAAQ,CAAA,EAAA,EAAK,CAAA,IAAK,CAAA,CAAE,CAAC,KAAK,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,GAAG,CAAC,CAAA,CAAA;AAC7D,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,MAAA,EAAQ,CAAA,EAAA,EAAK,GAAA,CAAI,CAAC,CAAA,IAAK,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA;AAAA,EACxD;AACA,EAAA,OAAO,GAAA;AACT;AAOO,SAAS,iBAAA,CAAkB,MAAsB,GAAA,EAAoB;AAC1E,EAAA,MAAM,IAAI,IAAA,CAAK,MAAA;AACf,EAAA,MAAM,CAAA,GAAI,KAAK,GAAA,CAAI,CAAC,MAAM,CAAC,GAAG,KAAK,GAAA,CAAI,CAAC,MAAM,IAAA,CAAK,CAAA,EAAG,CAAC,CAAC,CAAA,EAAG,KAAK,CAAA,EAAG,GAAG,CAAC,CAAC,CAAA;AACxE,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAA,YAAe,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,IAAA,CAAK,IAAI,CAAA,CAAE,CAAC,CAAA,CAAE,CAAC,CAAC,CAAC,CAAA;AACzE,EAAA,MAAM,GAAA,GAAM,aAAa,OAAA,IAAW,CAAA,CAAA;AACpC,EAAA,MAAM,SAAuC,EAAC;AAC9C,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,KAAA,IAAS,MAAM,CAAA,EAAG,GAAA,GAAM,CAAA,IAAK,GAAA,GAAM,GAAG,GAAA,EAAA,EAAO;AAC3C,IAAA,IAAI,IAAA,GAAO,GAAA;AACX,IAAA,KAAA,IAAS,CAAA,GAAI,MAAM,CAAA,EAAG,CAAA,GAAI,GAAG,CAAA,EAAA,EAAK,IAAI,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,CAAC,EAAE,GAAG,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,IAAI,CAAA,CAAE,GAAG,CAAC,CAAA,EAAG,IAAA,GAAO,CAAA;AAC3F,IAAA,IAAI,EAAE,KAAK,GAAA,CAAI,CAAA,CAAE,IAAI,CAAA,CAAE,GAAG,CAAC,CAAA,GAAI,GAAA,CAAA,EAAM;AACrC,IAAA,CAAC,CAAA,CAAE,GAAG,CAAA,EAAG,CAAA,CAAE,IAAI,CAAC,CAAA,GAAI,CAAC,CAAA,CAAE,IAAI,CAAA,EAAG,CAAA,CAAE,GAAG,CAAC,CAAA;AACpC,IAAA,KAAA,IAAS,CAAA,GAAI,GAAA,GAAM,CAAA,EAAG,CAAA,GAAI,GAAG,CAAA,EAAA,EAAK;AAChC,MAAA,MAAM,CAAA,GAAI,EAAE,CAAC,CAAA,CAAE,GAAG,CAAA,GAAI,CAAA,CAAE,GAAG,CAAA,CAAE,GAAG,CAAA;AAChC,MAAA,KAAA,IAAS,CAAA,GAAI,GAAA,EAAK,CAAA,IAAK,CAAA,EAAG,KAAK,CAAA,CAAE,CAAC,CAAA,CAAE,CAAC,CAAA,IAAK,CAAA,GAAI,CAAA,CAAE,GAAG,EAAE,CAAC,CAAA;AAAA,IACxD;AACA,IAAA,MAAA,CAAO,IAAA,CAAK,CAAC,GAAA,EAAK,GAAG,CAAC,CAAA;AACtB,IAAA,GAAA,EAAA;AAAA,EACF;AACA,EAAA,MAAM,IAAI,IAAI,KAAA,CAAc,CAAC,CAAA,CAAE,KAAK,CAAC,CAAA;AACrC,EAAA,KAAA,IAAS,IAAI,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,CAAA,IAAK,GAAG,CAAA,EAAA,EAAK;AAC3C,IAAA,MAAM,CAAC,CAAA,EAAG,GAAG,CAAA,GAAI,OAAO,CAAC,CAAA;AACzB,IAAA,IAAI,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA,CAAE,CAAC,CAAA;AACd,IAAA,KAAA,IAAS,CAAA,GAAI,GAAA,GAAM,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAA,EAAK,CAAA,IAAK,CAAA,CAAE,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,EAAE,CAAC,CAAA;AACpD,IAAA,CAAA,CAAE,GAAG,CAAA,GAAI,CAAA,GAAI,CAAA,CAAE,CAAC,EAAE,GAAG,CAAA;AAAA,EACvB;AACA,EAAA,OAAO,CAAA;AACT;AAIO,SAAS,mBAAA,CAAoB,GAAS,CAAA,EAAiC;AAC5E,EAAA,MAAM,EAAA,GAAK,cAAA,CAAe,CAAA,CAAE,IAAI,CAAA;AAChC,EAAA,MAAM,EAAA,GAAK,cAAA,CAAe,CAAA,CAAE,IAAI,CAAA;AAChC,EAAA,MAAM,CAAA,GAAI,CAAA,CAAE,EAAA,CAAG,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAA,CAAE,EAAA,CAAG,CAAC,CAAC,CAAA;AACxC,EAAA,MAAM,IAAI,iBAAA,CAAkB,CAAC,GAAG,EAAA,EAAI,GAAG,GAAG,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;AAC1E,EAAA,MAAM,GAAA,GAAM,CAAA,CAAE,EAAA,CAAG,KAAA,EAAM;AACvB,EAAA,MAAM,GAAA,GAAM,CAAA,CAAE,EAAA,CAAG,KAAA,EAAM;AACvB,EAAA,EAAA,CAAG,OAAA,CAAQ,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,OAAA,CAAQ,CAAC,GAAG,CAAA,KAAM;AAAE,IAAA,GAAA,CAAI,CAAC,CAAA,IAAK,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA;AAAA,EAAG,CAAC,CAAC,CAAA;AACjE,EAAA,EAAA,CAAG,OAAA,CAAQ,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,OAAA,CAAQ,CAAC,GAAG,CAAA,KAAM;AAAE,IAAA,GAAA,CAAI,CAAC,CAAA,IAAK,CAAA,CAAE,EAAA,CAAG,MAAA,GAAS,CAAC,CAAA,GAAI,CAAA;AAAA,EAAG,CAAC,CAAC,CAAA;AAC7E,EAAA,OAAO,EAAE,KAAK,GAAA,EAAI;AACpB;AAGO,SAAS,cAAA,CAAe,CAAA,EAAS,CAAA,EAAS,GAAA,GAAM,IAAA,EAAmB;AACxE,EAAA,MAAM,EAAE,GAAA,EAAK,GAAA,EAAI,GAAI,mBAAA,CAAoB,GAAG,CAAC,CAAA;AAC7C,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,MAAA,EAAQ,CAAA,EAAA,EAAK,IAAA,IAAA,CAAS,GAAA,CAAI,CAAC,CAAA,GAAI,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA;AAClE,EAAA,IAAI,EAAE,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA,IAAK,QAAQ,CAAC,WAAA,CAAY,GAAG,CAAA,EAAG,OAAO,IAAA;AAC3D,EAAA,MAAM,CAAA,GAAI,EAAE,EAAA,CAAG,MAAA;AACf,EAAA,MAAM,UAAU,cAAA,CAAe;AAAA,IAC7B,GAAG,UAAA,CAAW,cAAA,CAAe,CAAA,CAAE,IAAI,GAAG,CAAC,CAAA;AAAA,IACvC,GAAG,UAAA,CAAW,cAAA,CAAe,CAAA,CAAE,IAAI,GAAG,CAAC;AAAA,GACxC,CAAA;AACD,EAAA,OAAO,EAAE,EAAA,EAAI,GAAA,EAAK,MAAM,UAAA,CAAW,OAAA,EAAS,CAAC,CAAA,EAAE;AACjD;;;ACzDA,IAAM,YAAA,GAAe,EAAA;AACrB,IAAM,WAAA,GAAc,IAAA;AAEpB,IAAM,OAAA,GAAU,IAAA;AAEhB,IAAM,IAAA,GAAO,CAAC,CAAA,EAAQ,CAAA,KAAgB,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAA,CAAE,CAAC,CAAC,CAAA;AAC9D,IAAM,KAAA,GAAQ,CAAC,CAAA,EAAQ,CAAA,KAAgB,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAA,CAAE,CAAC,CAAC,CAAA;AAC/D,IAAMA,eAAc,CAAC,CAAA,KAAoB,CAAA,CAAE,KAAA,CAAM,OAAO,QAAQ,CAAA;AAEhE,SAAS,QAAA,CAAS,GAAQ,CAAA,EAAgB;AACxC,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,CAAE,MAAA,EAAQ,CAAA,EAAA,EAAK,CAAA,IAAA,CAAM,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA,KAAM,CAAA;AACzD,EAAA,OAAO,IAAA,CAAK,KAAK,CAAC,CAAA;AACpB;AAUA,SAAS,WAAA,CAAe,OAAA,EAAyB,IAAA,EAAW,GAAA,EAAsB;AAChF,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAiB;AAClC,EAAA,OAAO;AAAA,IACL,GAAA;AAAA,IACA,IAAA,CAAK,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO;AAC1B,MAAA,IAAI,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA;AACxB,MAAA,IAAI,CAAC,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,OAAA,EAAU,CAAA,GAAI,OAAA,CAAQ,QAAA,CAAS,IAAA,CAAK,KAAA,EAAO,IAAI,CAAC,CAAE,CAAA;AACnE,MAAA,MAAM,CAAA,GAAI,SAAS,OAAA,CAAQ,QAAA,CAAS,KAAK,KAAA,EAAO,KAAK,CAAC,CAAA,EAAG,CAAC,CAAA;AAC1D,MAAA,OAAO,MAAA,CAAO,QAAA,CAAS,CAAC,CAAA,GAAI,CAAA,GAAI,GAAA;AAAA,IAClC;AAAA,GACF;AACF;AAEA,SAAS,SAAA,CAAa,CAAA,EAAqB,KAAA,EAAY,GAAA,EAAsB;AAC3E,EAAA,IAAI,CAAC,CAAA,CAAE,IAAA,EAAM,OAAO,IAAA;AACpB,EAAA,MAAM,CAAA,GAAI,iBAAA,CAAkB,CAAA,CAAE,KAAA,CAAM,IAAA,EAAM,MAAM,KAAA,EAAO,CAAA,CAAE,KAAA,CAAM,EAAE,CAAC,CAAA;AAClE,EAAA,OAAO,EAAE,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,EAAA,EAAI,EAAE,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,CAAC,KAAK,EAAA,GAAK,GAAA,IAAO,EAAE,CAAC,CAAA,IAAK,KAAK,GAAG,CAAA;AAC3E;AAGA,SAAS,KAAA,CAAS,CAAA,EAAY,CAAA,EAAqB,KAAA,EAAY,KAAA,EAA2B;AACxF,EAAA,MAAM,WAAW,CAAA,CAAE,IAAA,CAAK,CAAA,CAAE,KAAA,EAAO,OAAO,KAAK,CAAA;AAC7C,EAAA,IAAI,CAAC,CAAA,CAAE,QAAA,KAAa,MAAA,CAAO,KAAA,CAAM,QAAQ,CAAA,IAAK,EAAE,QAAA,IAAY,CAAA,CAAE,OAAA,CAAA,CAAA,EAAW,OAAO,IAAA;AAChF,EAAA,MAAM,EAAA,GAAK,MAAA,CAAO,KAAA,CAAM,QAAQ,IAAI,QAAA,GAAW,QAAA;AAC/C,EAAA,OAAO,SAAA,CAAU,GAAG,IAAA,CAAK,KAAA,EAAO,KAAK,CAAA,EAAG,CAAA,CAAE,GAAG,CAAA,GAAI,EAAA,GAAK,IAAA;AACxD;AAEA,SAAS,cAAA,CAAkB,SAAyB,CAAA,EAAuB;AACzE,EAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,OAAA,CAAQ,OAAO,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,EAAA,EAAI,CAAA,CAAE,EAAE,CAAC,CAAC,CAAA;AAC9D,EAAA,MAAM,OAAkB,EAAC;AACzB,EAAA,KAAA,MAAW,CAAA,IAAK,QAAQ,UAAA,EAAY;AAClC,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,KAAK,CAAA;AAChC,IAAA,IAAI,CAAC,KAAA,IAAS,CAACA,YAAAA,CAAY,KAAK,CAAA,IAAK,CAACA,YAAAA,CAAY,CAAA,CAAE,KAAA,CAAM,EAAE,CAAA,EAAG;AAC/D,IAAA,MAAM,SAAS,cAAA,CAAe,OAAA,CAAQ,OAAO,EAAE,EAAA,EAAI,MAAM,CAAA,CAAE,KAAA,CAAM,EAAA,EAAI,KAAK,GAAG,IAAA,EAAM,CAAA,CAAE,MAAM,IAAA,EAAK,EAAG,EAAE,GAAG,CAAA;AACxG,IAAA,IAAI,CAAC,MAAA,EAAQ;AACb,IAAA,MAAM,EAAA,GAAK,MAAM,CAAA,EAAG,CAAA,EAAG,OAAO,aAAA,CAAc,MAAA,EAAQ,OAAA,CAAQ,MAAM,CAAC,CAAA;AACnE,IAAA,IAAI,EAAA,KAAO,MAAM,IAAA,CAAK,IAAA,CAAK,EAAE,CAAA,EAAG,KAAA,EAAO,MAAA,EAAQ,EAAA,EAAI,CAAA;AAAA,EACrD;AACA,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,IAAA,CAAQ,MAAiB,IAAA,EAAyB;AACzD,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAuB;AAC3C,EAAA,KAAA,MAAW,KAAK,IAAA,EAAM;AACpB,IAAA,MAAM,OAAO,OAAA,CAAQ,GAAA,CAAI,EAAE,CAAA,CAAE,KAAK,KAAK,EAAC;AACxC,IAAA,IAAA,CAAK,KAAK,CAAC,CAAA;AACX,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAE,CAAA,CAAE,KAAA,EAAO,IAAI,CAAA;AAAA,EAC7B;AACA,EAAA,MAAM,MAAiB,EAAC;AACxB,EAAA,KAAA,MAAW,IAAA,IAAQ,OAAA,CAAQ,MAAA,EAAO,EAAG;AACnC,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAO,KAAK,GAAA,CAAI,CAAA,CAAE,KAAK,CAAA,CAAE,EAAE,IAAI,OAAA,GAAU,CAAA,CAAE,KAAK,CAAA,CAAE,EAAA,GAAK,EAAE,CAAA,CAAE,KAAA,GAAQ,CAAA,CAAE,CAAA,CAAE,KAAM,CAAA;AAC3F,IAAA,GAAA,CAAI,KAAK,GAAG,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,IAAI,CAAC,CAAA;AAAA,EACjC;AACA,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,aAAA,CAAiB,GAAc,CAAA,EAAsB;AAC5D,EAAA,MAAM,EAAA,GAAK,CAAA,CAAE,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,CAAA,CAAE,KAAK,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,IAAI,CAAC,CAAA;AACvD,EAAA,MAAM,EAAA,GAAK,CAAA,CAAE,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,CAAA,CAAE,KAAK,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,IAAI,CAAC,CAAA;AACvD,EAAA,KAAA,IAAS,CAAA,GAAI,GAAG,CAAA,GAAI,IAAA,CAAK,IAAI,EAAA,CAAG,MAAA,EAAQ,EAAA,CAAG,MAAM,CAAA,EAAG,CAAA,EAAA,MAAS,EAAA,CAAG,CAAC,CAAA,KAAM,EAAA,CAAG,CAAC,CAAA,SAAU,EAAA,CAAG,CAAC,CAAA,GAAI,EAAA,CAAG,CAAC,CAAA;AACjG,EAAA,OAAO,EAAA,CAAG,SAAS,EAAA,CAAG,MAAA;AACxB;AAGA,SAAS,aAAA,CAAiB,GAAa,CAAA,EAAqB;AAC1D,EAAA,IAAI,EAAE,KAAA,KAAU,CAAA,CAAE,OAAO,OAAO,CAAA,CAAE,QAAQ,CAAA,CAAE,KAAA;AAC5C,EAAA,IAAI,EAAE,WAAA,KAAgB,CAAA,CAAE,aAAa,OAAO,CAAA,CAAE,cAAc,CAAA,CAAE,WAAA;AAC9D,EAAA,IAAI,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,EAAA,GAAK,CAAA,CAAE,EAAE,CAAA,GAAI,OAAA,EAAS,OAAO,CAAA,CAAE,EAAA,GAAK,CAAA,CAAE,EAAA;AACrD,EAAA,OAAO,aAAA,CAAc,CAAA,CAAE,OAAA,EAAS,CAAA,CAAE,OAAO,CAAA;AAC3C;AAGA,SAAS,MAAA,CAAU,MAAA,EAAkB,CAAA,EAAY,IAAA,EAAc,QAAa,CAAA,EAA6B;AACvG,EAAA,MAAM,OAAO,cAAA,CAAe,MAAA,CAAO,MAAM,CAAA,CAAE,MAAA,EAAQ,EAAE,GAAG,CAAA;AACxD,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,EAAA,MAAM,GAAA,GAAM,QAAQ,IAAI,CAAA;AACxB,EAAA,IAAI,GAAA,IAAO,MAAA,CAAO,GAAA,EAAK,OAAO,IAAA;AAC9B,EAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,IAAA,EAAM,MAAM,CAAA;AACxC,EAAA,IAAI,CAACA,YAAAA,CAAY,KAAK,CAAA,EAAG,OAAO,IAAA;AAChC,EAAA,MAAM,OAAA,GAAU,CAAC,GAAG,MAAA,CAAO,SAAS,CAAC,CAAA;AACrC,EAAA,IAAI,EAAA,GAAK,CAAA;AACT,EAAA,KAAA,MAAW,OAAO,OAAA,EAAS;AACzB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,EAAG,IAAI,CAAA,EAAG,GAAA,CAAI,OAAO,KAAK,CAAA;AAC1C,IAAA,IAAI,CAAA,KAAM,MAAM,OAAO,IAAA;AACvB,IAAA,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,CAAC,CAAA;AAAA,EACrB;AACA,EAAA,MAAM,UAAA,GAAa,CAAA,CAAE,CAAA,CAAE,IAAA,KAAS,WAC5B,cAAA,CAAe,MAAA,CAAO,UAAA,EAAY,CAAA,CAAE,MAAA,EAAQ,CAAA,CAAE,GAAG,CAAA,IAAK,OACtD,MAAA,CAAO,UAAA;AACX,EAAA,OAAO;AAAA,IACL,OAAA;AAAA,IAAS,IAAA;AAAA,IAAM,GAAA;AAAA,IAAK,UAAA;AAAA,IAAY,KAAA;AAAA,IAAO,EAAA;AAAA,IACvC,OAAO,IAAA,GAAO,GAAA;AAAA,IACd,WAAA,EAAa,IAAA,GAAO,OAAA,CAAQ,UAAU;AAAA,GACxC;AACF;AAGA,SAAS,MAAA,CAAU,UAAA,EAAuB,IAAA,EAAgB,MAAA,EAAa,CAAA,EAAsB;AAC3F,EAAA,MAAM,IAAA,GAAqD,EAAE,GAAA,EAAK,IAAA,EAAM,UAAU,IAAA,EAAK;AACvF,EAAA,MAAM,QAAA,GAAW,CAAC,CAAA,KAAgB;AAChC,IAAA,IAAI,cAAc,CAAA,EAAG,IAAA,CAAK,GAAG,CAAA,GAAI,CAAA,OAAQ,GAAA,GAAM,CAAA;AAC/C,IAAA,IAAI,EAAE,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,EAAE,CAAA,CAAE,QAAQ,CAAA,KAAM,CAAC,KAAK,QAAA,IAAY,aAAA,CAAc,GAAG,IAAA,CAAK,QAAQ,IAAI,CAAA,CAAA,EAAI;AAClG,MAAA,IAAA,CAAK,QAAA,GAAW,CAAA;AAAA,IAClB;AAAA,EACF,CAAA;AACA,EAAA,MAAM,KAAA,GAAQ,CAAC,KAAA,EAAe,MAAA,KAAqB;AACjD,IAAA,KAAA,IAAS,CAAA,GAAI,KAAA,EAAO,CAAA,GAAI,UAAA,CAAW,QAAQ,CAAA,EAAA,EAAK;AAC9C,MAAA,MAAM,IAAA,GAAO,OAAO,MAAA,EAAQ,UAAA,CAAW,CAAC,CAAA,EAAG,IAAA,CAAK,GAAA,EAAK,MAAA,EAAQ,CAAC,CAAA;AAC9D,MAAA,IAAI,CAAC,IAAA,EAAM;AACX,MAAA,QAAA,CAAS,IAAI,CAAA;AACb,MAAA,IAAI,KAAK,GAAA,GAAM,CAAA,EAAG,KAAA,CAAM,CAAA,GAAI,GAAG,IAAI,CAAA;AAAA,IACrC;AAAA,EACF,CAAA;AACA,EAAA,KAAA,CAAM,GAAG,IAAI,CAAA;AACb,EAAA,OAAO,IAAA,CAAK,YAAY,IAAA,CAAK,GAAA;AAC/B;AAEA,SAAS,WAAA,CAAe,OAAA,EAAyB,KAAA,EAAY,CAAA,EAAgC;AAC3F,EAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,OAAA,CAAQ,OAAO,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,EAAA,EAAI,CAAA,CAAE,EAAE,CAAC,CAAC,CAAA;AAC9D,EAAA,OAAO,OAAA,CAAQ,UAAA,CAAW,MAAA,CAAO,CAAC,CAAA,KAAM;AACtC,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,KAAK,CAAA;AAChC,IAAA,IAAI,CAAC,OAAO,OAAO,KAAA;AACnB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,EAAO,KAAK,CAAA;AAC/B,IAAA,IAAI,EAAE,QAAA,CAAS,aAAA,CAAc,CAAA,CAAE,KAAA,EAAO,KAAK,CAAA,EAAG,KAAK,CAAA,IAAK,CAAA,CAAE,GAAA,CAAA,EAAM,OAAO,KAAA;AACvE,IAAA,OAAO,KAAA,CAAM,CAAA,EAAG,CAAA,EAAG,KAAA,EAAO,KAAK,CAAA,KAAM,IAAA;AAAA,EACvC,CAAC,CAAA;AACH;AAIO,SAAS,YAAe,OAAA,EAA4C;AACzE,EAAA,MAAM,EAAE,KAAA,EAAO,MAAA,EAAO,GAAI,OAAA;AAC1B,EAAA,IAAI,IAAA,GAAO,aAAA,CAAc,KAAA,EAAO,MAAM,CAAA;AACtC,EAAA,IAAI,CAACA,YAAAA,CAAY,IAAI,CAAA,SAAUA,YAAAA,CAAY,KAAA,CAAM,EAAE,CAAA,GAAI,MAAM,EAAA,GAAK,KAAA,CAAM,EAAA,CAAG,GAAA,CAAI,MAAM,CAAC,CAAA;AACtF,EAAA,MAAM,IAAI,WAAA,CAAY,OAAA,EAAS,IAAA,EAAM,OAAA,CAAQ,OAAO,WAAW,CAAA;AAC/D,EAAA,MAAM,IAAA,GAAO,QAAQ,KAAK,CAAA;AAC1B,EAAA,MAAM,IAAA,GAAiB;AAAA,IACrB,SAAS,EAAC;AAAA,IAAG,IAAA,EAAM,KAAA;AAAA,IAAO,GAAA,EAAK,IAAA;AAAA,IAAM,UAAA,EAAY,KAAA;AAAA,IAAO,KAAA,EAAO,IAAA;AAAA,IAAM,KAAA,EAAO,CAAA;AAAA,IAAG,WAAA,EAAa,CAAA;AAAA,IAAG,EAAA,EAAI;AAAA,GACrG;AACA,EAAA,MAAM,IAAA,GAAO,KAAK,cAAA,CAAe,OAAA,EAAS,CAAC,CAAA,EAAG,OAAA,CAAQ,YAAY,YAAY,CAAA;AAC9E,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,IAAA,EAAM,IAAA,EAAM,QAAQ,CAAC,CAAA;AACxC,EAAA,OAAO;AAAA,IACL,OAAO,GAAA,CAAI,KAAA;AAAA,IACX,SAAS,GAAA,CAAI,OAAA,CAAQ,IAAI,CAAC,CAAA,KAAM,EAAE,CAAC,CAAA;AAAA,IACnC,SAAA,EAAW,WAAA,CAAY,OAAA,EAAS,GAAA,CAAI,OAAO,CAAC,CAAA;AAAA,IAC5C,OAAO,GAAA,CAAI;AAAA,GACb;AACF;;;ACrPO,SAAS,QAAA,CAAS,KAAA,EAAY,MAAA,EAAa,KAAA,EAA4B,IAAA,EAAoB;AAChG,EAAA,MAAM,CAAC,CAAA,EAAG,CAAC,CAAA,GAAI,KAAA;AACf,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,MAAM,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA,GAAI,MAAM,CAAC,CAAA;AAC7B,IAAA,CAAA,IAAK,CAAA,GAAI,EAAE,CAAC,CAAA;AACZ,IAAA,CAAA,IAAK,CAAA,GAAI,EAAE,CAAC,CAAA;AAAA,EACd;AACA,EAAA,MAAM,KAAA,GAAQ,CAAA,KAAM,CAAA,IAAK,CAAA,KAAM,IAAI,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,GAAI,IAAI,CAAA,GAAI,IAAA;AAC7E,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA;AACxB,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA;AACxB,EAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,IAAA,EAAM,CAAC,EAAE,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,KAAM,IAAI,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA,GAAI,CAAC,CAAC,CAAA,EAAE;AAChE","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. */\nconst RANK_TOL = 1e-9;\n/** Pivots below this fraction of the largest diagonal entry count as zero. */\nconst PIVOT_TOL = 1e-12;\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 rank-deficient system has many minimizers; this returns the one whose\n * free unknowns are 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 let maxDiag = 0;\n for (let i = 0; i < k; i++) maxDiag = Math.max(maxDiag, Math.abs(m[i][i]));\n const tol = PIVOT_TOL * (maxDiag || 1);\n const pivots: [row: number, col: number][] = [];\n let row = 0;\n for (let col = 0; col < k && row < k; col++) {\n let best = row;\n for (let r = row + 1; r < k; r++) if (Math.abs(m[r][col]) > Math.abs(m[best][col])) best = r;\n if (!(Math.abs(m[best][col]) > tol)) continue;\n [m[row], m[best]] = [m[best], m[row]];\n for (let r = row + 1; r < k; r++) {\n const f = m[r][col] / m[row][col];\n for (let c = col; c <= k; c++) m[r][c] -= f * m[row][c];\n }\n pivots.push([row, col]);\n row++;\n }\n const x = new Array<number>(k).fill(0);\n for (let p = pivots.length - 1; p >= 0; p--) {\n const [r, col] = pivots[p];\n let s = m[r][k];\n for (let c = col + 1; c < k; c++) s -= m[r][c] * x[c];\n x[col] = s / m[r][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. 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)) 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.slice(0, size));\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>, hDim: number, delta0: Vec, m: Measure): Combo<M> | null {\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 let px = 0;\n for (const mem of members) {\n const p = meets(m, mem.c, mem.probe, delta);\n if (p === null) return null;\n px = Math.max(px, p);\n }\n const targetFlat = l.c.tier === 'target'\n ? intersectFlats(parent.targetFlat, l.within, m.eps) ?? flat\n : parent.targetFlat;\n return {\n members, flat, dim, targetFlat, delta, px,\n codim: hDim - dim,\n targetCodim: hDim - flatDim(targetFlat),\n };\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.dim, 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"]}
|
|
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"]}
|
package/dist/tessellate/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { extractPolylines } from '../chunk-
|
|
2
|
-
export { tessellate } from '../chunk-
|
|
3
|
-
import '../chunk-
|
|
1
|
+
export { extractPolylines } from '../chunk-VHXOCDZ2.js';
|
|
2
|
+
export { tessellate } from '../chunk-UGE57OTX.js';
|
|
3
|
+
import '../chunk-2PKPKU4P.js';
|
|
4
4
|
import '../chunk-755Y4YZS.js';
|
|
5
5
|
import '../chunk-B53BERKG.js';
|
|
6
6
|
|
package/dist/warp/index.d.ts
CHANGED
|
@@ -137,7 +137,9 @@ declare function puppetMesh(path: PolygonPath, pins: readonly Point[], opts?: Pu
|
|
|
137
137
|
* between them moved as rigidly as the pins allow. The shape's fill is
|
|
138
138
|
* triangulated (`puppetMesh`) and deformed as-rigid-as-possible (`arap`), so
|
|
139
139
|
* the pull of a pin travels through the shape: two limbs that nearly touch
|
|
140
|
-
* share no triangle and move apart. A point
|
|
140
|
+
* share no triangle and move apart. A point is carried by a smooth
|
|
141
|
+
* (Clough–Tocher) interpolation of the deformed mesh, so a bend has no kink
|
|
142
|
+
* where two triangles meet.
|
|
141
143
|
*/
|
|
142
144
|
|
|
143
145
|
/** A pin: where it was placed on the unwarped shape, and where it is now. */
|
|
@@ -146,11 +148,11 @@ interface PuppetPin {
|
|
|
146
148
|
to: Point;
|
|
147
149
|
}
|
|
148
150
|
/**
|
|
149
|
-
* The map `pins` make of `source`'s fill:
|
|
150
|
-
*
|
|
151
|
+
* The map `pins` make of `source`'s fill: smooth across the deformed mesh,
|
|
152
|
+
* through every pin, and carried on past the outline for a point off the
|
|
151
153
|
* shape. The mesh and its solve are set up once per source and pin set, so
|
|
152
|
-
* moving pins only re-solves. No pins is the identity, and
|
|
153
|
-
* whole shape with it.
|
|
154
|
+
* moving pins only re-solves. No pins, or none moved, is the identity, and
|
|
155
|
+
* one pin moves the whole shape with it.
|
|
154
156
|
*/
|
|
155
157
|
declare function puppetMap(source: PolygonPath, pins: readonly PuppetPin[]): (p: Point) => Point;
|
|
156
158
|
/**
|
package/dist/warp/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { boundsOfPath, keepCorner, fitPointRun } from '../chunk-
|
|
1
|
+
import { boundsOfPath, keepCorner, fitPointRun } from '../chunk-STGSBIOL.js';
|
|
2
2
|
import { pathToAnchors, anchorsToPath } from '../chunk-Q66NA2FU.js';
|
|
3
3
|
import '../chunk-CE7IY7TB.js';
|
|
4
|
-
import { nestRings, flattenPolygon, resolveCrossings } from '../chunk-
|
|
5
|
-
import { pointInPolygon } from '../chunk-
|
|
4
|
+
import { nestRings, flattenPolygon, resolveCrossings } from '../chunk-UGE57OTX.js';
|
|
5
|
+
import { pointInPolygon } from '../chunk-2PKPKU4P.js';
|
|
6
6
|
import '../chunk-755Y4YZS.js';
|
|
7
7
|
import { cubicPointAt } from '../chunk-B53BERKG.js';
|
|
8
8
|
import earcut from 'earcut';
|
|
@@ -697,6 +697,144 @@ function createArapSolver(mesh, pinned) {
|
|
|
697
697
|
};
|
|
698
698
|
}
|
|
699
699
|
|
|
700
|
+
// src/warp/cloughTocher.ts
|
|
701
|
+
function restFrames2(mesh) {
|
|
702
|
+
const V = mesh.vertices, T = mesh.triangles;
|
|
703
|
+
const nt = T.length / 3;
|
|
704
|
+
const inverse = new Float64Array(4 * nt);
|
|
705
|
+
const area = new Float64Array(nt);
|
|
706
|
+
for (let t = 0; t < nt; t++) {
|
|
707
|
+
const a = T[3 * t], b = T[3 * t + 1], c = T[3 * t + 2];
|
|
708
|
+
const ux = V[2 * b] - V[2 * a], uy = V[2 * b + 1] - V[2 * a + 1];
|
|
709
|
+
const vx = V[2 * c] - V[2 * a], vy = V[2 * c + 1] - V[2 * a + 1];
|
|
710
|
+
const det = ux * vy - uy * vx;
|
|
711
|
+
if (det === 0) continue;
|
|
712
|
+
inverse.set([vy / det, -vx / det, -uy / det, ux / det], 4 * t);
|
|
713
|
+
area[t] = Math.abs(det) / 2;
|
|
714
|
+
}
|
|
715
|
+
return { inverse, area };
|
|
716
|
+
}
|
|
717
|
+
function vertexDerivatives(mesh, frames, at) {
|
|
718
|
+
const T = mesh.triangles;
|
|
719
|
+
const nv = mesh.vertices.length / 2;
|
|
720
|
+
const J = new Float64Array(4 * nv);
|
|
721
|
+
const weight = new Float64Array(nv);
|
|
722
|
+
for (let t = 0; t < T.length / 3; t++) {
|
|
723
|
+
const w = frames.area[t];
|
|
724
|
+
if (w === 0) continue;
|
|
725
|
+
const a = T[3 * t], b = T[3 * t + 1], c = T[3 * t + 2];
|
|
726
|
+
const ux = at[2 * b] - at[2 * a], uy = at[2 * b + 1] - at[2 * a + 1];
|
|
727
|
+
const vx = at[2 * c] - at[2 * a], vy = at[2 * c + 1] - at[2 * a + 1];
|
|
728
|
+
const i = frames.inverse;
|
|
729
|
+
const m0 = ux * i[4 * t] + vx * i[4 * t + 2], m1 = ux * i[4 * t + 1] + vx * i[4 * t + 3];
|
|
730
|
+
const m2 = uy * i[4 * t] + vy * i[4 * t + 2], m3 = uy * i[4 * t + 1] + vy * i[4 * t + 3];
|
|
731
|
+
for (const v of [a, b, c]) {
|
|
732
|
+
J[4 * v] += w * m0;
|
|
733
|
+
J[4 * v + 1] += w * m1;
|
|
734
|
+
J[4 * v + 2] += w * m2;
|
|
735
|
+
J[4 * v + 3] += w * m3;
|
|
736
|
+
weight[v] += w;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
for (let v = 0; v < nv; v++) {
|
|
740
|
+
if (weight[v] === 0) {
|
|
741
|
+
J[4 * v] = 1;
|
|
742
|
+
J[4 * v + 3] = 1;
|
|
743
|
+
continue;
|
|
744
|
+
}
|
|
745
|
+
for (let k = 0; k < 4; k++) J[4 * v + k] /= weight[v];
|
|
746
|
+
}
|
|
747
|
+
return J;
|
|
748
|
+
}
|
|
749
|
+
var F = 0;
|
|
750
|
+
var S = 3;
|
|
751
|
+
var I = 6;
|
|
752
|
+
var N = 9;
|
|
753
|
+
var P = 12;
|
|
754
|
+
var M = 15;
|
|
755
|
+
var C = 18;
|
|
756
|
+
var ORDINATES = 19;
|
|
757
|
+
function buildOrdinates(V, T, at, J, t, out) {
|
|
758
|
+
const vx = [0, 0, 0], vy = [0, 0, 0], v = [0, 0, 0];
|
|
759
|
+
for (let k = 0; k < 3; k++) {
|
|
760
|
+
v[k] = T[3 * t + k];
|
|
761
|
+
vx[k] = V[2 * v[k]];
|
|
762
|
+
vy[k] = V[2 * v[k] + 1];
|
|
763
|
+
}
|
|
764
|
+
const sx = (vx[0] + vx[1] + vx[2]) / 3, sy = (vy[0] + vy[1] + vy[2]) / 3;
|
|
765
|
+
const set = (o, x2, y2) => {
|
|
766
|
+
out[2 * o] = x2;
|
|
767
|
+
out[2 * o + 1] = y2;
|
|
768
|
+
};
|
|
769
|
+
const x = (o) => out[2 * o], y = (o) => out[2 * o + 1];
|
|
770
|
+
const toward = (o, k, px, py) => {
|
|
771
|
+
const dx = (px - vx[k]) / 3, dy = (py - vy[k]) / 3, j = 4 * v[k];
|
|
772
|
+
set(o, at[2 * v[k]] + J[j] * dx + J[j + 1] * dy, at[2 * v[k] + 1] + J[j + 2] * dx + J[j + 3] * dy);
|
|
773
|
+
};
|
|
774
|
+
for (let k = 0; k < 3; k++) {
|
|
775
|
+
const n = (k + 1) % 3, p = (k + 2) % 3;
|
|
776
|
+
set(F + k, at[2 * v[k]], at[2 * v[k] + 1]);
|
|
777
|
+
toward(S + k, k, sx, sy);
|
|
778
|
+
toward(N + k, k, vx[n], vy[n]);
|
|
779
|
+
toward(P + k, k, vx[p], vy[p]);
|
|
780
|
+
}
|
|
781
|
+
for (let k = 0; k < 3; k++) {
|
|
782
|
+
const a = (k + 1) % 3, b = (k + 2) % 3;
|
|
783
|
+
const ex = vx[b] - vx[a], ey = vy[b] - vy[a];
|
|
784
|
+
const lb = ((sx - vx[a]) * ex + (sy - vy[a]) * ey) / (ex * ex + ey * ey), la = 1 - lb;
|
|
785
|
+
const mid = (c) => la * c(N + a) + lb * c(P + b) + 0.5 * (c(S + a) - la * c(F + a) - lb * c(N + a) + c(S + b) - la * c(P + b) - lb * c(F + b));
|
|
786
|
+
set(M + k, mid(x), mid(y));
|
|
787
|
+
}
|
|
788
|
+
for (let k = 0; k < 3; k++) {
|
|
789
|
+
const e1 = M + (k + 1) % 3, e2 = M + (k + 2) % 3;
|
|
790
|
+
set(I + k, (x(S + k) + x(e1) + x(e2)) / 3, (y(S + k) + y(e1) + y(e2)) / 3);
|
|
791
|
+
}
|
|
792
|
+
set(C, (x(I) + x(I + 1) + x(I + 2)) / 3, (y(I) + y(I + 1) + y(I + 2)) / 3);
|
|
793
|
+
}
|
|
794
|
+
var PIECES = [0, 1, 2].map((k) => {
|
|
795
|
+
const a = (k + 1) % 3, b = (k + 2) % 3;
|
|
796
|
+
return Int32Array.from([F + a, F + b, C, N + a, P + b, S + a, I + a, S + b, I + b, M + k], (o) => 2 * o);
|
|
797
|
+
});
|
|
798
|
+
function evaluate(o, base, w, d = [0, 0, 0]) {
|
|
799
|
+
const k = w[0] <= w[1] && w[0] <= w[2] ? 0 : w[1] <= w[2] ? 1 : 2;
|
|
800
|
+
const a = (k + 1) % 3, b = (k + 2) % 3;
|
|
801
|
+
const u = w[a] - w[k], v = w[b] - w[k], s = 3 * w[k];
|
|
802
|
+
const du = d[a] - d[k], dv = d[b] - d[k], ds = 3 * d[k];
|
|
803
|
+
const c0 = u * u * u + 3 * u * u * du;
|
|
804
|
+
const c1 = v * v * v + 3 * v * v * dv;
|
|
805
|
+
const c2 = s * s * s + 3 * s * s * ds;
|
|
806
|
+
const c3 = 3 * (u * u * v + 2 * u * v * du + u * u * dv);
|
|
807
|
+
const c4 = 3 * (u * v * v + v * v * du + 2 * u * v * dv);
|
|
808
|
+
const c5 = 3 * (u * u * s + 2 * u * s * du + u * u * ds);
|
|
809
|
+
const c6 = 3 * (u * s * s + s * s * du + 2 * u * s * ds);
|
|
810
|
+
const c7 = 3 * (v * v * s + 2 * v * s * dv + v * v * ds);
|
|
811
|
+
const c8 = 3 * (v * s * s + s * s * dv + 2 * v * s * ds);
|
|
812
|
+
const c9 = 6 * (u * v * s + v * s * du + u * s * dv + u * v * ds);
|
|
813
|
+
const q = PIECES[k];
|
|
814
|
+
const sum = (c) => c0 * o[base + q[0] + c] + c1 * o[base + q[1] + c] + c2 * o[base + q[2] + c] + c3 * o[base + q[3] + c] + c4 * o[base + q[4] + c] + c5 * o[base + q[5] + c] + c6 * o[base + q[6] + c] + c7 * o[base + q[7] + c] + c8 * o[base + q[8] + c] + c9 * o[base + q[9] + c];
|
|
815
|
+
return { x: sum(0), y: sum(1) };
|
|
816
|
+
}
|
|
817
|
+
function cloughTocherMap(mesh, frames, at) {
|
|
818
|
+
const V = mesh.vertices, T = mesh.triangles;
|
|
819
|
+
const J = vertexDerivatives(mesh, frames, at);
|
|
820
|
+
const ordinates = new Float64Array(2 * ORDINATES * (T.length / 3));
|
|
821
|
+
const built = new Uint8Array(T.length / 3);
|
|
822
|
+
return (spot) => {
|
|
823
|
+
const t = spot.tri;
|
|
824
|
+
if (!built[t]) {
|
|
825
|
+
buildOrdinates(V, T, at, J, t, ordinates.subarray(2 * ORDINATES * t, 2 * ORDINATES * (t + 1)));
|
|
826
|
+
built[t] = 1;
|
|
827
|
+
}
|
|
828
|
+
const base = 2 * ORDINATES * t;
|
|
829
|
+
const w = [spot.w0, spot.w1, spot.w2];
|
|
830
|
+
if (w[0] >= 0 && w[1] >= 0 && w[2] >= 0) return evaluate(ordinates, base, w);
|
|
831
|
+
const clamped = w.map((v) => Math.max(0, v));
|
|
832
|
+
const sum = clamped[0] + clamped[1] + clamped[2];
|
|
833
|
+
const near = clamped.map((v) => v / sum);
|
|
834
|
+
return evaluate(ordinates, base, near, w.map((v, i) => v - near[i]));
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
|
|
700
838
|
// src/warp/meshMap.ts
|
|
701
839
|
var EPS = 1e-9;
|
|
702
840
|
function weights(V, T, t, x, y) {
|
|
@@ -766,13 +904,6 @@ function meshLocator(mesh) {
|
|
|
766
904
|
return best;
|
|
767
905
|
};
|
|
768
906
|
}
|
|
769
|
-
function placeSpot(T, at, s) {
|
|
770
|
-
const a = T[3 * s.tri], b = T[3 * s.tri + 1], c = T[3 * s.tri + 2];
|
|
771
|
-
return {
|
|
772
|
-
x: s.w0 * at[2 * a] + s.w1 * at[2 * b] + s.w2 * at[2 * c],
|
|
773
|
-
y: s.w0 * at[2 * a + 1] + s.w1 * at[2 * b + 1] + s.w2 * at[2 * c + 1]
|
|
774
|
-
};
|
|
775
|
-
}
|
|
776
907
|
|
|
777
908
|
// src/warp/refine.ts
|
|
778
909
|
function orient(V, a, b, c) {
|
|
@@ -1112,21 +1243,22 @@ function rigFor(source, pins) {
|
|
|
1112
1243
|
if (held?.key === key) return held;
|
|
1113
1244
|
const mesh = puppetMesh(source, pins.map((p) => p.from));
|
|
1114
1245
|
const pinned = [...new Set(Array.from(mesh.pinVertex).filter((v) => v >= 0))];
|
|
1115
|
-
const rig = { key, mesh, solver: createArapSolver(mesh, pinned), locate: meshLocator(mesh), spots: /* @__PURE__ */ new Map(), remembered: 0 };
|
|
1246
|
+
const rig = { key, mesh, frames: restFrames2(mesh), solver: createArapSolver(mesh, pinned), locate: meshLocator(mesh), spots: /* @__PURE__ */ new Map(), remembered: 0 };
|
|
1116
1247
|
rigs.set(source, rig);
|
|
1117
1248
|
return rig;
|
|
1118
1249
|
}
|
|
1119
1250
|
function puppetMap(source, pins) {
|
|
1120
|
-
if (pins.
|
|
1251
|
+
if (pins.every((p) => p.to.x === p.from.x && p.to.y === p.from.y)) return (p) => ({ x: p.x, y: p.y });
|
|
1121
1252
|
const rig = rigFor(source, pins);
|
|
1122
1253
|
const at = solveRig(rig, pins);
|
|
1123
1254
|
if (!at) {
|
|
1124
1255
|
const dx = pins[0].to.x - pins[0].from.x, dy = pins[0].to.y - pins[0].from.y;
|
|
1125
1256
|
return (p) => ({ x: p.x + dx, y: p.y + dy });
|
|
1126
1257
|
}
|
|
1258
|
+
const place = cloughTocherMap(rig.mesh, rig.frames, at);
|
|
1127
1259
|
return (p) => {
|
|
1128
1260
|
const spot = spotOf(rig, p);
|
|
1129
|
-
return spot ?
|
|
1261
|
+
return spot ? place(spot) : { x: p.x, y: p.y };
|
|
1130
1262
|
};
|
|
1131
1263
|
}
|
|
1132
1264
|
function solveRig(rig, pins, opts) {
|