@weasel-js/geom 1.10.0 → 1.11.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/README.md +140 -16
- package/dist/3d/index.d.ts +29 -2
- package/dist/3d/index.js +49 -1
- package/dist/3d/index.js.map +1 -1
- package/dist/booleans/index.d.ts +34 -10
- package/dist/booleans/index.js +344 -352
- package/dist/booleans/index.js.map +1 -1
- package/dist/{chunk-MDT7F32A.js → chunk-6XSJY3TC.js} +10 -39
- package/dist/chunk-6XSJY3TC.js.map +1 -0
- package/dist/chunk-7KLJZFBY.js +573 -0
- package/dist/chunk-7KLJZFBY.js.map +1 -0
- package/dist/chunk-B53BERKG.js +386 -0
- package/dist/chunk-B53BERKG.js.map +1 -0
- package/dist/chunk-CE7IY7TB.js +104 -0
- package/dist/chunk-CE7IY7TB.js.map +1 -0
- package/dist/chunk-HGF5OVEN.js +129 -0
- package/dist/chunk-HGF5OVEN.js.map +1 -0
- package/dist/chunk-J2O2B54M.js +800 -0
- package/dist/chunk-J2O2B54M.js.map +1 -0
- package/dist/chunk-Q66NA2FU.js +174 -0
- package/dist/chunk-Q66NA2FU.js.map +1 -0
- package/dist/chunk-SASMXDBE.js +443 -0
- package/dist/chunk-SASMXDBE.js.map +1 -0
- package/dist/chunk-UI3FUWXM.js +533 -0
- package/dist/chunk-UI3FUWXM.js.map +1 -0
- package/dist/curvature-PkoLduGc.d.ts +454 -0
- package/dist/curves/index.d.ts +14 -5
- package/dist/curves/index.js +33 -111
- package/dist/curves/index.js.map +1 -1
- package/dist/index.d.ts +1697 -205
- package/dist/index.js +4729 -1308
- package/dist/index.js.map +1 -1
- package/dist/nd/index.d.ts +91 -27
- package/dist/nd/index.js +282 -0
- package/dist/nd/index.js.map +1 -1
- package/dist/path-BW8d_2RY.d.ts +157 -0
- package/dist/portCurve-C5HDWuuV.d.ts +30 -0
- package/dist/tessellate/index.d.ts +18 -4
- package/dist/tessellate/index.js +21 -277
- package/dist/tessellate/index.js.map +1 -1
- package/dist/warp/index.d.ts +252 -0
- package/dist/warp/index.js +1316 -0
- package/dist/warp/index.js.map +1 -0
- package/package.json +5 -1
- package/dist/chunk-MDT7F32A.js.map +0 -1
- package/dist/chunk-OXH3NOXC.js +0 -62
- package/dist/chunk-OXH3NOXC.js.map +0 -1
- package/dist/chunk-URQMDR6Q.js +0 -80
- package/dist/chunk-URQMDR6Q.js.map +0 -1
- package/dist/chunk-WQMYOCFB.js +0 -167
- package/dist/chunk-WQMYOCFB.js.map +0 -1
- package/dist/chunk-XS6ERH3X.js +0 -34
- package/dist/chunk-XS6ERH3X.js.map +0 -1
- package/dist/cubicMath-CFXbq6vp.d.ts +0 -116
- package/dist/path-Bf9KeVxC.d.ts +0 -44
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
import { pointInPolygon, resolveCorners, fillsOpenSubpaths, flattenCubicWithArcLen, flattenQuadraticWithArcLen, DEFAULT_FLATTEN_TOLERANCE } from './chunk-J2O2B54M.js';
|
|
2
|
+
import { rectToContour, forEachSegment, PATH_Z, PATH_C, PATH_Q, PATH_L, PATH_M } from './chunk-B53BERKG.js';
|
|
3
|
+
import earcut from 'earcut';
|
|
4
|
+
|
|
5
|
+
// src/tessellate/crossings.ts
|
|
6
|
+
var keyOf = (n) => `${n.x},${n.y}`;
|
|
7
|
+
function resolveCrossings(flat, always = false) {
|
|
8
|
+
const edges = edgesOf(flat);
|
|
9
|
+
if (!cutAtCrossings(edges) && !always) return null;
|
|
10
|
+
const pieces = boundaryPieces(edges);
|
|
11
|
+
return loopsToContours(chainLoops(pieces));
|
|
12
|
+
}
|
|
13
|
+
function edgesOf(flat) {
|
|
14
|
+
const { coords, contourStarts, anchorA, anchorB, anchorT } = flat;
|
|
15
|
+
const total = coords.length / 2;
|
|
16
|
+
const node = (i) => ({ x: coords[i * 2], y: coords[i * 2 + 1], a: anchorA[i], b: anchorB[i], t: anchorT[i] });
|
|
17
|
+
const edges = [];
|
|
18
|
+
contourStarts.forEach((start, c) => {
|
|
19
|
+
const end = c + 1 < contourStarts.length ? contourStarts[c + 1] : total;
|
|
20
|
+
for (let i = start; i < end; i++) {
|
|
21
|
+
const from = node(i), to = node(i + 1 < end ? i + 1 : start);
|
|
22
|
+
if (from.x !== to.x || from.y !== to.y) edges.push({ from, to, cuts: [] });
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return edges;
|
|
26
|
+
}
|
|
27
|
+
function cutAtCrossings(edges) {
|
|
28
|
+
const order = edges.slice().sort((p, q) => Math.min(p.from.x, p.to.x) - Math.min(q.from.x, q.to.x));
|
|
29
|
+
let found = false;
|
|
30
|
+
for (let i = 0; i < order.length; i++) {
|
|
31
|
+
const e = order[i];
|
|
32
|
+
const maxX = Math.max(e.from.x, e.to.x);
|
|
33
|
+
for (let j = i + 1; j < order.length; j++) {
|
|
34
|
+
const f = order[j];
|
|
35
|
+
if (Math.min(f.from.x, f.to.x) > maxX) break;
|
|
36
|
+
if (Math.max(e.from.y, e.to.y) < Math.min(f.from.y, f.to.y)) continue;
|
|
37
|
+
if (Math.max(f.from.y, f.to.y) < Math.min(e.from.y, e.to.y)) continue;
|
|
38
|
+
const hit = crossing(e, f);
|
|
39
|
+
if (!hit) continue;
|
|
40
|
+
e.cuts.push({ s: hit.s, node: hit.node });
|
|
41
|
+
f.cuts.push({ s: hit.u, node: hit.node });
|
|
42
|
+
found = true;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return found;
|
|
46
|
+
}
|
|
47
|
+
function crossing(e, f) {
|
|
48
|
+
const rx = e.to.x - e.from.x, ry = e.to.y - e.from.y;
|
|
49
|
+
const qx = f.to.x - f.from.x, qy = f.to.y - f.from.y;
|
|
50
|
+
const den = rx * qy - ry * qx;
|
|
51
|
+
if (den === 0) return null;
|
|
52
|
+
const dx = f.from.x - e.from.x, dy = f.from.y - e.from.y;
|
|
53
|
+
const s = (dx * qy - dy * qx) / den;
|
|
54
|
+
const u = (dx * ry - dy * rx) / den;
|
|
55
|
+
const lo = 1e-9, hi = 1 - 1e-9;
|
|
56
|
+
if (s <= lo || s >= hi || u <= lo || u >= hi) return null;
|
|
57
|
+
const x = e.from.x + rx * s, y = e.from.y + ry * s;
|
|
58
|
+
return { s, u, node: { x, y, ...anchorsAlong(e, s) } };
|
|
59
|
+
}
|
|
60
|
+
function anchorsAlong(e, s) {
|
|
61
|
+
const { from, to } = e;
|
|
62
|
+
if (from.a === to.a && from.b === to.b) return { a: from.a, b: from.b, t: from.t + (to.t - from.t) * s };
|
|
63
|
+
const near = s < 0.5 ? from : to;
|
|
64
|
+
return { a: near.a, b: near.b, t: near.t };
|
|
65
|
+
}
|
|
66
|
+
function boundaryPieces(edges) {
|
|
67
|
+
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
68
|
+
for (const { from: p } of edges) {
|
|
69
|
+
minX = Math.min(minX, p.x);
|
|
70
|
+
maxX = Math.max(maxX, p.x);
|
|
71
|
+
minY = Math.min(minY, p.y);
|
|
72
|
+
maxY = Math.max(maxY, p.y);
|
|
73
|
+
}
|
|
74
|
+
const eps = Math.max(Math.hypot(maxX - minX, maxY - minY) * 1e-7, 1e-9);
|
|
75
|
+
const filled = (x, y) => windingAt(edges, x, y) !== 0;
|
|
76
|
+
const out = [];
|
|
77
|
+
for (const e of edges) {
|
|
78
|
+
const stops = [e.from, ...e.cuts.sort((p, q) => p.s - q.s).map((c) => c.node), e.to];
|
|
79
|
+
for (let k = 0; k + 1 < stops.length; k++) {
|
|
80
|
+
const p = stops[k], q = stops[k + 1];
|
|
81
|
+
const dx = q.x - p.x, dy = q.y - p.y;
|
|
82
|
+
const len = Math.hypot(dx, dy);
|
|
83
|
+
if (len === 0) continue;
|
|
84
|
+
const mx = (p.x + q.x) / 2, my = (p.y + q.y) / 2;
|
|
85
|
+
const nx = -dy / len * eps, ny = dx / len * eps;
|
|
86
|
+
const left = filled(mx + nx, my + ny), right = filled(mx - nx, my - ny);
|
|
87
|
+
if (left && !right) out.push({ from: p, to: q });
|
|
88
|
+
else if (right && !left) out.push({ from: q, to: p });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
function windingAt(edges, x, y) {
|
|
94
|
+
let w = 0;
|
|
95
|
+
for (const { from: p, to: q } of edges) {
|
|
96
|
+
const side = (q.x - p.x) * (y - p.y) - (x - p.x) * (q.y - p.y);
|
|
97
|
+
if (p.y <= y && q.y > y && side > 0) w++;
|
|
98
|
+
else if (q.y <= y && p.y > y && side < 0) w--;
|
|
99
|
+
}
|
|
100
|
+
return w;
|
|
101
|
+
}
|
|
102
|
+
function chainLoops(pieces) {
|
|
103
|
+
const outgoing = /* @__PURE__ */ new Map();
|
|
104
|
+
for (const p of pieces) {
|
|
105
|
+
const k = keyOf(p.from);
|
|
106
|
+
const list = outgoing.get(k);
|
|
107
|
+
if (list) list.push(p);
|
|
108
|
+
else outgoing.set(k, [p]);
|
|
109
|
+
}
|
|
110
|
+
const used = /* @__PURE__ */ new Set();
|
|
111
|
+
const loops = [];
|
|
112
|
+
for (const first of pieces) {
|
|
113
|
+
if (used.has(first)) continue;
|
|
114
|
+
used.add(first);
|
|
115
|
+
const loop = [first.from];
|
|
116
|
+
const startKey = keyOf(first.from);
|
|
117
|
+
let cur = first;
|
|
118
|
+
while (keyOf(cur.to) !== startKey) {
|
|
119
|
+
const next = sharpestLeft(cur, (outgoing.get(keyOf(cur.to)) ?? []).filter((p) => !used.has(p)));
|
|
120
|
+
if (!next) break;
|
|
121
|
+
used.add(next);
|
|
122
|
+
loop.push(next.from);
|
|
123
|
+
cur = next;
|
|
124
|
+
}
|
|
125
|
+
if (keyOf(cur.to) === startKey && loop.length >= 3) loops.push(loop);
|
|
126
|
+
}
|
|
127
|
+
return loops;
|
|
128
|
+
}
|
|
129
|
+
function sharpestLeft(into, options) {
|
|
130
|
+
const ix = into.to.x - into.from.x, iy = into.to.y - into.from.y;
|
|
131
|
+
let best;
|
|
132
|
+
let bestTurn = -Infinity;
|
|
133
|
+
for (const p of options) {
|
|
134
|
+
const ox = p.to.x - p.from.x, oy = p.to.y - p.from.y;
|
|
135
|
+
const turn = Math.atan2(ix * oy - iy * ox, ix * ox + iy * oy);
|
|
136
|
+
if (turn > bestTurn) {
|
|
137
|
+
bestTurn = turn;
|
|
138
|
+
best = p;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return best;
|
|
142
|
+
}
|
|
143
|
+
function loopsToContours(loops) {
|
|
144
|
+
const out = { coords: [], contourStarts: [], anchorA: [], anchorB: [], anchorT: [] };
|
|
145
|
+
for (const loop of loops) {
|
|
146
|
+
out.contourStarts.push(out.coords.length / 2);
|
|
147
|
+
for (const n of loop) {
|
|
148
|
+
out.coords.push(n.x, n.y);
|
|
149
|
+
out.anchorA.push(n.a);
|
|
150
|
+
out.anchorB.push(n.b);
|
|
151
|
+
out.anchorT.push(n.t);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return out;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// src/tessellate/nesting.ts
|
|
158
|
+
function nestRings(flat) {
|
|
159
|
+
const { coords, contourStarts } = flat;
|
|
160
|
+
const total = coords.length / 2;
|
|
161
|
+
const rings = contourStarts.map((start, c) => {
|
|
162
|
+
const end = c + 1 < contourStarts.length ? contourStarts[c + 1] : total;
|
|
163
|
+
return { start, end, area: signedArea(coords, start, end), parent: -1, winding: 0 };
|
|
164
|
+
});
|
|
165
|
+
const boxes = rings.map((r) => boxOf(coords, r.start, r.end));
|
|
166
|
+
const bySize = rings.map((_, i) => i).filter((i) => rings[i].area !== 0);
|
|
167
|
+
bySize.sort((i, j) => Math.abs(rings[j].area) - Math.abs(rings[i].area));
|
|
168
|
+
for (let k = 0; k < bySize.length; k++) {
|
|
169
|
+
const r = rings[bySize[k]];
|
|
170
|
+
for (let m = k - 1; m >= 0; m--) {
|
|
171
|
+
const o = bySize[m];
|
|
172
|
+
if (contains(coords, rings[o], boxes[o], r)) {
|
|
173
|
+
r.parent = o;
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
r.winding = Math.sign(r.area) + (r.parent >= 0 ? rings[r.parent].winding : 0);
|
|
178
|
+
}
|
|
179
|
+
return rings;
|
|
180
|
+
}
|
|
181
|
+
function contains(coords, o, box, r) {
|
|
182
|
+
const eps = Math.max(box[2] - box[0], box[3] - box[1]) * 1e-9;
|
|
183
|
+
for (let i = r.start; i < r.end; i++) {
|
|
184
|
+
const x = coords[i * 2], y = coords[i * 2 + 1];
|
|
185
|
+
if (x < box[0] || x > box[2] || y < box[1] || y > box[3]) return false;
|
|
186
|
+
if (!onOutline(coords, o, x, y, eps)) return pointInPolygon(coords, x, y, o.start, o.end);
|
|
187
|
+
}
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
function onOutline(coords, o, x, y, eps) {
|
|
191
|
+
for (let i = o.start; i < o.end; i++) {
|
|
192
|
+
const j = i + 1 === o.end ? o.start : i + 1;
|
|
193
|
+
const ax = coords[i * 2], ay = coords[i * 2 + 1];
|
|
194
|
+
const dx = coords[j * 2] - ax, dy = coords[j * 2 + 1] - ay;
|
|
195
|
+
const len2 = dx * dx + dy * dy;
|
|
196
|
+
const s = len2 > 0 ? Math.max(0, Math.min(1, ((x - ax) * dx + (y - ay) * dy) / len2)) : 0;
|
|
197
|
+
if (Math.hypot(ax + dx * s - x, ay + dy * s - y) <= eps) return true;
|
|
198
|
+
}
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
function boxOf(coords, start, end) {
|
|
202
|
+
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
203
|
+
for (let i = start; i < end; i++) {
|
|
204
|
+
const x = coords[i * 2], y = coords[i * 2 + 1];
|
|
205
|
+
minX = Math.min(minX, x);
|
|
206
|
+
maxX = Math.max(maxX, x);
|
|
207
|
+
minY = Math.min(minY, y);
|
|
208
|
+
maxY = Math.max(maxY, y);
|
|
209
|
+
}
|
|
210
|
+
return [minX, minY, maxX, maxY];
|
|
211
|
+
}
|
|
212
|
+
function signedArea(coords, start, end) {
|
|
213
|
+
let a = 0;
|
|
214
|
+
for (let i = start; i < end; i++) {
|
|
215
|
+
const j = i + 1 === end ? start : i + 1;
|
|
216
|
+
a += coords[i * 2] * coords[j * 2 + 1] - coords[j * 2] * coords[i * 2 + 1];
|
|
217
|
+
}
|
|
218
|
+
return a * 0.5;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// src/tessellate/tessellate.ts
|
|
222
|
+
function tessellate(path, opts = {}) {
|
|
223
|
+
if (path.kind === "rect") return tessellateRect(path);
|
|
224
|
+
return tessellatePolygon(resolveCorners(path), opts);
|
|
225
|
+
}
|
|
226
|
+
function tessellateRect(p) {
|
|
227
|
+
const { x, y, width: w, height: h } = p;
|
|
228
|
+
return {
|
|
229
|
+
vertices: Float32Array.from(rectToContour(x, y, w, h)),
|
|
230
|
+
indices: new Uint32Array([0, 1, 2, 0, 2, 3]),
|
|
231
|
+
anchorA: new Uint32Array([0, 1, 2, 3]),
|
|
232
|
+
anchorB: new Uint32Array([0, 1, 2, 3]),
|
|
233
|
+
anchorT: new Float32Array([0, 0, 0, 0])
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
function flattenPolygon(p, tolerance) {
|
|
237
|
+
const closed = /* @__PURE__ */ new Set();
|
|
238
|
+
const all = flattenContours(p, tolerance, closed);
|
|
239
|
+
if (fillsOpenSubpaths(p)) return all;
|
|
240
|
+
const kept = { coords: [], contourStarts: [], anchorA: [], anchorB: [], anchorT: [] };
|
|
241
|
+
all.contourStarts.forEach((start, c) => {
|
|
242
|
+
if (!closed.has(c)) return;
|
|
243
|
+
const end = c + 1 < all.contourStarts.length ? all.contourStarts[c + 1] : all.coords.length / 2;
|
|
244
|
+
kept.contourStarts.push(kept.coords.length / 2);
|
|
245
|
+
kept.coords.push(...all.coords.slice(start * 2, end * 2));
|
|
246
|
+
kept.anchorA.push(...all.anchorA.slice(start, end));
|
|
247
|
+
kept.anchorB.push(...all.anchorB.slice(start, end));
|
|
248
|
+
kept.anchorT.push(...all.anchorT.slice(start, end));
|
|
249
|
+
});
|
|
250
|
+
return kept;
|
|
251
|
+
}
|
|
252
|
+
function flattenContours(p, tolerance, closed) {
|
|
253
|
+
const { commands, coords } = p;
|
|
254
|
+
const out = [];
|
|
255
|
+
const anchorA = [];
|
|
256
|
+
const anchorB = [];
|
|
257
|
+
const anchorT = [];
|
|
258
|
+
const contourStarts = [];
|
|
259
|
+
let startAnchor = -1;
|
|
260
|
+
let prevAnchor = -1;
|
|
261
|
+
let anchorCounter = 0;
|
|
262
|
+
const pushCurveAnchors = (anchorStart, arcAccum, total, target) => {
|
|
263
|
+
for (let k = 0; k < arcAccum.length; k++) {
|
|
264
|
+
anchorA.push(prevAnchor);
|
|
265
|
+
anchorB.push(target);
|
|
266
|
+
anchorT.push(total > 0 ? arcAccum[k] / total : 0);
|
|
267
|
+
}
|
|
268
|
+
const lastIdx = anchorStart + arcAccum.length - 1;
|
|
269
|
+
anchorA[lastIdx] = target;
|
|
270
|
+
anchorB[lastIdx] = target;
|
|
271
|
+
anchorT[lastIdx] = 0;
|
|
272
|
+
};
|
|
273
|
+
forEachSegment(commands, coords, (cmd, coordIdx, prevX, prevY, _i, opensSubpath) => {
|
|
274
|
+
if (opensSubpath) {
|
|
275
|
+
const anchor = Math.max(startAnchor, 0);
|
|
276
|
+
contourStarts.push(out.length / 2);
|
|
277
|
+
out.push(prevX, prevY);
|
|
278
|
+
anchorA.push(anchor);
|
|
279
|
+
anchorB.push(anchor);
|
|
280
|
+
anchorT.push(0);
|
|
281
|
+
prevAnchor = anchor;
|
|
282
|
+
}
|
|
283
|
+
switch (cmd) {
|
|
284
|
+
case PATH_M:
|
|
285
|
+
case PATH_L: {
|
|
286
|
+
if (cmd === PATH_M) {
|
|
287
|
+
contourStarts.push(out.length / 2);
|
|
288
|
+
startAnchor = anchorCounter;
|
|
289
|
+
}
|
|
290
|
+
out.push(coords[coordIdx], coords[coordIdx + 1]);
|
|
291
|
+
anchorA.push(anchorCounter);
|
|
292
|
+
anchorB.push(anchorCounter);
|
|
293
|
+
anchorT.push(0);
|
|
294
|
+
prevAnchor = anchorCounter;
|
|
295
|
+
anchorCounter++;
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
case PATH_Q: {
|
|
299
|
+
const target = anchorCounter;
|
|
300
|
+
const arcAccum = [];
|
|
301
|
+
const anchorStart = anchorA.length;
|
|
302
|
+
const total = flattenQuadraticWithArcLen(
|
|
303
|
+
prevX,
|
|
304
|
+
prevY,
|
|
305
|
+
coords[coordIdx],
|
|
306
|
+
coords[coordIdx + 1],
|
|
307
|
+
coords[coordIdx + 2],
|
|
308
|
+
coords[coordIdx + 3],
|
|
309
|
+
tolerance,
|
|
310
|
+
out,
|
|
311
|
+
arcAccum
|
|
312
|
+
);
|
|
313
|
+
pushCurveAnchors(anchorStart, arcAccum, total, target);
|
|
314
|
+
prevAnchor = target;
|
|
315
|
+
anchorCounter++;
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
case PATH_C: {
|
|
319
|
+
const target = anchorCounter;
|
|
320
|
+
const arcAccum = [];
|
|
321
|
+
const anchorStart = anchorA.length;
|
|
322
|
+
const total = flattenCubicWithArcLen(
|
|
323
|
+
prevX,
|
|
324
|
+
prevY,
|
|
325
|
+
coords[coordIdx],
|
|
326
|
+
coords[coordIdx + 1],
|
|
327
|
+
coords[coordIdx + 2],
|
|
328
|
+
coords[coordIdx + 3],
|
|
329
|
+
coords[coordIdx + 4],
|
|
330
|
+
coords[coordIdx + 5],
|
|
331
|
+
tolerance,
|
|
332
|
+
out,
|
|
333
|
+
arcAccum
|
|
334
|
+
);
|
|
335
|
+
pushCurveAnchors(anchorStart, arcAccum, total, target);
|
|
336
|
+
prevAnchor = target;
|
|
337
|
+
anchorCounter++;
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
case PATH_Z:
|
|
341
|
+
closed.add(contourStarts.length - 1);
|
|
342
|
+
prevAnchor = startAnchor;
|
|
343
|
+
break;
|
|
344
|
+
default:
|
|
345
|
+
throw new Error(`tessellate: unknown command code ${cmd}`);
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
return { coords: out, contourStarts, anchorA, anchorB, anchorT };
|
|
349
|
+
}
|
|
350
|
+
function tessellatePolygon(p, opts) {
|
|
351
|
+
const tolerance = opts.flattenTolerance ?? DEFAULT_FLATTEN_TOLERANCE;
|
|
352
|
+
const flat = flattenPolygon(p, tolerance);
|
|
353
|
+
if (p.fillRule === "evenodd") {
|
|
354
|
+
const { coords, contourStarts, anchorA, anchorB, anchorT } = flat;
|
|
355
|
+
return tessellateEvenoddWithAnchors(coords, contourStarts, anchorA, anchorB, anchorT);
|
|
356
|
+
}
|
|
357
|
+
const crossed = resolveCrossings(flat);
|
|
358
|
+
if (crossed) return tessellateNonzero(crossed, nestRings(crossed));
|
|
359
|
+
const rings = nestRings(flat);
|
|
360
|
+
if (rings.every((r) => Math.abs(r.winding) <= 1)) return tessellateNonzero(flat, rings);
|
|
361
|
+
const rebuilt = resolveCrossings(flat, true);
|
|
362
|
+
return tessellateNonzero(rebuilt, nestRings(rebuilt));
|
|
363
|
+
}
|
|
364
|
+
function tessellateNonzero(flat, rings) {
|
|
365
|
+
const { coords, contourStarts, anchorA, anchorB, anchorT } = flat;
|
|
366
|
+
const shapes = [];
|
|
367
|
+
const holesByShape = /* @__PURE__ */ new Map();
|
|
368
|
+
rings.forEach((r, i) => {
|
|
369
|
+
if (r.area === 0) return;
|
|
370
|
+
if (r.winding !== 0) shapes.push(i);
|
|
371
|
+
else if (holesByShape.has(r.parent)) holesByShape.get(r.parent).push(i);
|
|
372
|
+
else holesByShape.set(r.parent, [i]);
|
|
373
|
+
});
|
|
374
|
+
if (shapes.length <= 1 && (shapes[0] ?? 0) === 0) {
|
|
375
|
+
const tri = earcut(coords, contourStarts.length > 1 ? contourStarts.slice(1) : void 0);
|
|
376
|
+
return {
|
|
377
|
+
vertices: new Float32Array(coords),
|
|
378
|
+
indices: new Uint32Array(tri),
|
|
379
|
+
anchorA: new Uint32Array(anchorA),
|
|
380
|
+
anchorB: new Uint32Array(anchorB),
|
|
381
|
+
anchorT: new Float32Array(anchorT)
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
const finalCoords = [];
|
|
385
|
+
const finalAnchorA = [];
|
|
386
|
+
const finalAnchorB = [];
|
|
387
|
+
const finalAnchorT = [];
|
|
388
|
+
const finalIndices = [];
|
|
389
|
+
for (const pos of shapes) {
|
|
390
|
+
const holes = holesByShape.get(pos) ?? [];
|
|
391
|
+
const offset = finalCoords.length / 2;
|
|
392
|
+
const groupCoords = [];
|
|
393
|
+
const groupStarts = [0];
|
|
394
|
+
for (let i = rings[pos].start; i < rings[pos].end; i++) {
|
|
395
|
+
groupCoords.push(coords[i * 2], coords[i * 2 + 1]);
|
|
396
|
+
finalAnchorA.push(anchorA[i]);
|
|
397
|
+
finalAnchorB.push(anchorB[i]);
|
|
398
|
+
finalAnchorT.push(anchorT[i]);
|
|
399
|
+
}
|
|
400
|
+
for (const h of holes) {
|
|
401
|
+
groupStarts.push(groupCoords.length / 2);
|
|
402
|
+
for (let i = rings[h].start; i < rings[h].end; i++) {
|
|
403
|
+
groupCoords.push(coords[i * 2], coords[i * 2 + 1]);
|
|
404
|
+
finalAnchorA.push(anchorA[i]);
|
|
405
|
+
finalAnchorB.push(anchorB[i]);
|
|
406
|
+
finalAnchorT.push(anchorT[i]);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
const tri = earcut(groupCoords, groupStarts.length > 1 ? groupStarts.slice(1) : void 0);
|
|
410
|
+
for (const v of groupCoords) finalCoords.push(v);
|
|
411
|
+
for (const idx of tri) finalIndices.push(idx + offset);
|
|
412
|
+
}
|
|
413
|
+
return {
|
|
414
|
+
vertices: new Float32Array(finalCoords),
|
|
415
|
+
indices: new Uint32Array(finalIndices),
|
|
416
|
+
anchorA: new Uint32Array(finalAnchorA),
|
|
417
|
+
anchorB: new Uint32Array(finalAnchorB),
|
|
418
|
+
anchorT: new Float32Array(finalAnchorT)
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
function tessellateEvenoddWithAnchors(coords, contourStarts, anchorA, anchorB, anchorT) {
|
|
422
|
+
const indices = [];
|
|
423
|
+
const totalVerts = coords.length / 2;
|
|
424
|
+
for (let c = 0; c < contourStarts.length; c++) {
|
|
425
|
+
const start = contourStarts[c];
|
|
426
|
+
const end = c + 1 < contourStarts.length ? contourStarts[c + 1] : totalVerts;
|
|
427
|
+
for (let i = start + 1; i < end - 1; i++) {
|
|
428
|
+
indices.push(start, i, i + 1);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
return {
|
|
432
|
+
vertices: new Float32Array(coords),
|
|
433
|
+
indices: new Uint32Array(indices),
|
|
434
|
+
requiresStencil: true,
|
|
435
|
+
anchorA: new Uint32Array(anchorA),
|
|
436
|
+
anchorB: new Uint32Array(anchorB),
|
|
437
|
+
anchorT: new Float32Array(anchorT)
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
export { flattenPolygon, nestRings, resolveCrossings, tessellate };
|
|
442
|
+
//# sourceMappingURL=chunk-SASMXDBE.js.map
|
|
443
|
+
//# sourceMappingURL=chunk-SASMXDBE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tessellate/crossings.ts","../src/tessellate/nesting.ts","../src/tessellate/tessellate.ts"],"names":[],"mappings":"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","file":"chunk-SASMXDBE.js","sourcesContent":["/** Rebuilding outlines as the non-crossing boundary of their nonzero fill. */\n\n/** Flattened contours with each vertex's anchor parameterization. */\nexport interface FlattenedContours {\n coords: number[];\n contourStarts: number[];\n anchorA: number[];\n anchorB: number[];\n anchorT: number[];\n}\n\ninterface Node {\n x: number;\n y: number;\n a: number;\n b: number;\n t: number;\n}\n\ninterface Edge {\n from: Node;\n to: Node;\n /** Where crossings cut this edge, by parameter along it. */\n cuts: { s: number; node: Node }[];\n}\n\ninterface Piece {\n from: Node;\n to: Node;\n}\n\nconst keyOf = (n: Node): string => `${n.x},${n.y}`;\n\n/**\n * The boundary of `flat`'s nonzero fill as loops that do not cross, each with\n * the fill on its left, or `null` when no two edges cross and `always` is\n * not set.\n */\nexport function resolveCrossings(flat: FlattenedContours, always = false): FlattenedContours | null {\n const edges = edgesOf(flat);\n if (!cutAtCrossings(edges) && !always) return null;\n const pieces = boundaryPieces(edges);\n return loopsToContours(chainLoops(pieces));\n}\n\nfunction edgesOf(flat: FlattenedContours): Edge[] {\n const { coords, contourStarts, anchorA, anchorB, anchorT } = flat;\n const total = coords.length / 2;\n const node = (i: number): Node => ({ x: coords[i * 2], y: coords[i * 2 + 1], a: anchorA[i], b: anchorB[i], t: anchorT[i] });\n const edges: Edge[] = [];\n contourStarts.forEach((start, c) => {\n const end = c + 1 < contourStarts.length ? contourStarts[c + 1] : total;\n for (let i = start; i < end; i++) {\n const from = node(i), to = node(i + 1 < end ? i + 1 : start);\n if (from.x !== to.x || from.y !== to.y) edges.push({ from, to, cuts: [] });\n }\n });\n return edges;\n}\n\n/** Record every interior crossing on both edges it cuts; whether there were any. */\nfunction cutAtCrossings(edges: Edge[]): boolean {\n const order = edges.slice().sort((p, q) => Math.min(p.from.x, p.to.x) - Math.min(q.from.x, q.to.x));\n let found = false;\n for (let i = 0; i < order.length; i++) {\n const e = order[i];\n const maxX = Math.max(e.from.x, e.to.x);\n for (let j = i + 1; j < order.length; j++) {\n const f = order[j];\n if (Math.min(f.from.x, f.to.x) > maxX) break;\n if (Math.max(e.from.y, e.to.y) < Math.min(f.from.y, f.to.y)) continue;\n if (Math.max(f.from.y, f.to.y) < Math.min(e.from.y, e.to.y)) continue;\n const hit = crossing(e, f);\n if (!hit) continue;\n e.cuts.push({ s: hit.s, node: hit.node });\n f.cuts.push({ s: hit.u, node: hit.node });\n found = true;\n }\n }\n return found;\n}\n\nfunction crossing(e: Edge, f: Edge): { s: number; u: number; node: Node } | null {\n const rx = e.to.x - e.from.x, ry = e.to.y - e.from.y;\n const qx = f.to.x - f.from.x, qy = f.to.y - f.from.y;\n const den = rx * qy - ry * qx;\n if (den === 0) return null;\n const dx = f.from.x - e.from.x, dy = f.from.y - e.from.y;\n const s = (dx * qy - dy * qx) / den;\n const u = (dx * ry - dy * rx) / den;\n const lo = 1e-9, hi = 1 - 1e-9;\n if (s <= lo || s >= hi || u <= lo || u >= hi) return null;\n const x = e.from.x + rx * s, y = e.from.y + ry * s;\n return { s, u, node: { x, y, ...anchorsAlong(e, s) } };\n}\n\n/** Anchors for a point `s` of the way along `e`: interpolated within one\n * curve's run, else the nearer end's. */\nfunction anchorsAlong(e: Edge, s: number): { a: number; b: number; t: number } {\n const { from, to } = e;\n if (from.a === to.a && from.b === to.b) return { a: from.a, b: from.b, t: from.t + (to.t - from.t) * s };\n const near = s < 0.5 ? from : to;\n return { a: near.a, b: near.b, t: near.t };\n}\n\n/** The pieces between cuts that have fill on exactly one side, turned so it is on the left. */\nfunction boundaryPieces(edges: Edge[]): Piece[] {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const { from: p } of edges) {\n minX = Math.min(minX, p.x); maxX = Math.max(maxX, p.x);\n minY = Math.min(minY, p.y); maxY = Math.max(maxY, p.y);\n }\n const eps = Math.max(Math.hypot(maxX - minX, maxY - minY) * 1e-7, 1e-9);\n const filled = (x: number, y: number) => windingAt(edges, x, y) !== 0;\n\n const out: Piece[] = [];\n for (const e of edges) {\n const stops = [e.from, ...e.cuts.sort((p, q) => p.s - q.s).map((c) => c.node), e.to];\n for (let k = 0; k + 1 < stops.length; k++) {\n const p = stops[k], q = stops[k + 1];\n const dx = q.x - p.x, dy = q.y - p.y;\n const len = Math.hypot(dx, dy);\n if (len === 0) continue;\n const mx = (p.x + q.x) / 2, my = (p.y + q.y) / 2;\n const nx = (-dy / len) * eps, ny = (dx / len) * eps;\n const left = filled(mx + nx, my + ny), right = filled(mx - nx, my - ny);\n if (left && !right) out.push({ from: p, to: q });\n else if (right && !left) out.push({ from: q, to: p });\n }\n }\n return out;\n}\n\nfunction windingAt(edges: Edge[], x: number, y: number): number {\n let w = 0;\n for (const { from: p, to: q } of edges) {\n const side = (q.x - p.x) * (y - p.y) - (x - p.x) * (q.y - p.y);\n if (p.y <= y && q.y > y && side > 0) w++;\n else if (q.y <= y && p.y > y && side < 0) w--;\n }\n return w;\n}\n\n/** Join pieces end to start into closed loops. Where a node has several ways\n * on, take the sharpest left turn, which keeps to the face being traced. */\nfunction chainLoops(pieces: Piece[]): Node[][] {\n const outgoing = new Map<string, Piece[]>();\n for (const p of pieces) {\n const k = keyOf(p.from);\n const list = outgoing.get(k);\n if (list) list.push(p);\n else outgoing.set(k, [p]);\n }\n const used = new Set<Piece>();\n const loops: Node[][] = [];\n for (const first of pieces) {\n if (used.has(first)) continue;\n used.add(first);\n const loop: Node[] = [first.from];\n const startKey = keyOf(first.from);\n let cur = first;\n while (keyOf(cur.to) !== startKey) {\n const next = sharpestLeft(cur, (outgoing.get(keyOf(cur.to)) ?? []).filter((p) => !used.has(p)));\n if (!next) break;\n used.add(next);\n loop.push(next.from);\n cur = next;\n }\n if (keyOf(cur.to) === startKey && loop.length >= 3) loops.push(loop);\n }\n return loops;\n}\n\nfunction sharpestLeft(into: Piece, options: Piece[]): Piece | undefined {\n const ix = into.to.x - into.from.x, iy = into.to.y - into.from.y;\n let best: Piece | undefined;\n let bestTurn = -Infinity;\n for (const p of options) {\n const ox = p.to.x - p.from.x, oy = p.to.y - p.from.y;\n const turn = Math.atan2(ix * oy - iy * ox, ix * ox + iy * oy);\n if (turn > bestTurn) {\n bestTurn = turn;\n best = p;\n }\n }\n return best;\n}\n\nfunction loopsToContours(loops: Node[][]): FlattenedContours {\n const out: FlattenedContours = { coords: [], contourStarts: [], anchorA: [], anchorB: [], anchorT: [] };\n for (const loop of loops) {\n out.contourStarts.push(out.coords.length / 2);\n for (const n of loop) {\n out.coords.push(n.x, n.y);\n out.anchorA.push(n.a);\n out.anchorB.push(n.b);\n out.anchorT.push(n.t);\n }\n }\n return out;\n}\n","/** How the rings of a fill that does not cross itself sit inside one another. */\n\nimport { pointInPolygon } from '../polyline';\nimport type { FlattenedContours } from './crossings';\n\nexport interface Ring {\n start: number;\n end: number;\n area: number;\n /** The smallest ring this one lies inside, or -1. */\n parent: number;\n /** Nonzero winding number just inside this ring. */\n winding: number;\n}\n\n/** Each contour's ring. A zero-area ring has no parent and winding 0. */\nexport function nestRings(flat: FlattenedContours): Ring[] {\n const { coords, contourStarts } = flat;\n const total = coords.length / 2;\n const rings: Ring[] = contourStarts.map((start, c) => {\n const end = c + 1 < contourStarts.length ? contourStarts[c + 1] : total;\n return { start, end, area: signedArea(coords, start, end), parent: -1, winding: 0 };\n });\n const boxes = rings.map((r) => boxOf(coords, r.start, r.end));\n const bySize = rings.map((_, i) => i).filter((i) => rings[i].area !== 0);\n bySize.sort((i, j) => Math.abs(rings[j].area) - Math.abs(rings[i].area));\n for (let k = 0; k < bySize.length; k++) {\n const r = rings[bySize[k]];\n for (let m = k - 1; m >= 0; m--) {\n const o = bySize[m];\n if (contains(coords, rings[o], boxes[o], r)) {\n r.parent = o;\n break;\n }\n }\n r.winding = Math.sign(r.area) + (r.parent >= 0 ? rings[r.parent].winding : 0);\n }\n return rings;\n}\n\n/** Whether `r` lies inside `o`, given that neither crosses the other. Judged\n * at the first vertex of `r` not on `o`'s outline, since one on it is\n * inside or out by rounding. */\nfunction contains(coords: number[], o: Ring, box: number[], r: Ring): boolean {\n const eps = Math.max(box[2] - box[0], box[3] - box[1]) * 1e-9;\n for (let i = r.start; i < r.end; i++) {\n const x = coords[i * 2], y = coords[i * 2 + 1];\n if (x < box[0] || x > box[2] || y < box[1] || y > box[3]) return false;\n if (!onOutline(coords, o, x, y, eps)) return pointInPolygon(coords, x, y, o.start, o.end);\n }\n return false;\n}\n\nfunction onOutline(coords: number[], o: Ring, x: number, y: number, eps: number): boolean {\n for (let i = o.start; i < o.end; i++) {\n const j = i + 1 === o.end ? o.start : i + 1;\n const ax = coords[i * 2], ay = coords[i * 2 + 1];\n const dx = coords[j * 2] - ax, dy = coords[j * 2 + 1] - ay;\n const len2 = dx * dx + dy * dy;\n const s = len2 > 0 ? Math.max(0, Math.min(1, ((x - ax) * dx + (y - ay) * dy) / len2)) : 0;\n if (Math.hypot(ax + dx * s - x, ay + dy * s - y) <= eps) return true;\n }\n return false;\n}\n\nfunction boxOf(coords: number[], start: number, end: number): number[] {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (let i = start; i < end; i++) {\n const x = coords[i * 2], y = coords[i * 2 + 1];\n minX = Math.min(minX, x); maxX = Math.max(maxX, x);\n minY = Math.min(minY, y); maxY = Math.max(maxY, y);\n }\n return [minX, minY, maxX, maxY];\n}\n\nfunction signedArea(coords: number[], start: number, end: number): number {\n let a = 0;\n for (let i = start; i < end; i++) {\n const j = i + 1 === end ? start : i + 1;\n a += coords[i * 2] * coords[j * 2 + 1] - coords[j * 2] * coords[i * 2 + 1];\n }\n return a * 0.5;\n}\n","import earcut from 'earcut';\nimport { forEachSegment, PATH_M, PATH_L, PATH_Z, PATH_C, PATH_Q } from '../commands';\nimport { resolveCorners } from '../paths/corners';\nimport { rectToContour } from '../box';\nimport type { Path, PolygonPath, RectPath } from '../path';\nimport { fillsOpenSubpaths } from '../openFill';\nimport {\n DEFAULT_FLATTEN_TOLERANCE,\n flattenCubicWithArcLen,\n flattenQuadraticWithArcLen,\n} from '../flatten';\nimport type { Mesh } from './mesh';\nimport { resolveCrossings, type FlattenedContours } from './crossings';\nimport { nestRings, type Ring } from './nesting';\n\n/** Options for `tessellate`. A smaller tolerance means more triangles and\n * smoother curves; it is in path-local units, so callers rendering at a\n * larger scale should tighten it. */\nexport interface TessellateOptions {\n /** Flatness tolerance for bezier subdivision in path-local units. */\n flattenTolerance?: number;\n}\n\n/** Turn a path into a triangle mesh the renderer can draw: curves flattened to\n * line segments, then the resulting polygon triangulated. */\nexport function tessellate(path: Path, opts: TessellateOptions = {}): Mesh {\n if (path.kind === 'rect') return tessellateRect(path);\n return tessellatePolygon(resolveCorners(path), opts);\n}\n\nfunction tessellateRect(p: RectPath): Mesh {\n const { x, y, width: w, height: h } = p;\n return {\n vertices: Float32Array.from(rectToContour(x, y, w, h)),\n indices: new Uint32Array([0, 1, 2, 0, 2, 3]),\n anchorA: new Uint32Array([0, 1, 2, 3]),\n anchorB: new Uint32Array([0, 1, 2, 3]),\n anchorT: new Float32Array([0, 0, 0, 0]),\n };\n}\n\n/** The contours a fill covers: all of them, or only those a `Z` closed. */\nexport function flattenPolygon(p: PolygonPath, tolerance: number): FlattenedContours {\n const closed = new Set<number>();\n const all = flattenContours(p, tolerance, closed);\n if (fillsOpenSubpaths(p)) return all;\n const kept: FlattenedContours = { coords: [], contourStarts: [], anchorA: [], anchorB: [], anchorT: [] };\n all.contourStarts.forEach((start, c) => {\n if (!closed.has(c)) return;\n const end = c + 1 < all.contourStarts.length ? all.contourStarts[c + 1] : all.coords.length / 2;\n kept.contourStarts.push(kept.coords.length / 2);\n kept.coords.push(...all.coords.slice(start * 2, end * 2));\n kept.anchorA.push(...all.anchorA.slice(start, end));\n kept.anchorB.push(...all.anchorB.slice(start, end));\n kept.anchorT.push(...all.anchorT.slice(start, end));\n });\n return kept;\n}\n\n/** Flatten every contour, noting in `closed` the index of each one a `Z` ends. */\nfunction flattenContours(p: PolygonPath, tolerance: number, closed: Set<number>): FlattenedContours {\n const { commands, coords } = p;\n const out: number[] = [];\n const anchorA: number[] = [];\n const anchorB: number[] = [];\n const anchorT: number[] = [];\n const contourStarts: number[] = [];\n let startAnchor = -1;\n let prevAnchor = -1;\n let anchorCounter = 0;\n\n // Anchor bookkeeping for the points a curve just appended: interior points\n // interpolate (prevAnchor → target); the last is pinned anchor-exact.\n const pushCurveAnchors = (anchorStart: number, arcAccum: number[], total: number, target: number): void => {\n for (let k = 0; k < arcAccum.length; k++) {\n anchorA.push(prevAnchor);\n anchorB.push(target);\n anchorT.push(total > 0 ? arcAccum[k] / total : 0);\n }\n const lastIdx = anchorStart + arcAccum.length - 1;\n anchorA[lastIdx] = target;\n anchorB[lastIdx] = target;\n anchorT[lastIdx] = 0;\n };\n\n forEachSegment(commands, coords, (cmd, coordIdx, prevX, prevY, _i, opensSubpath) => {\n if (opensSubpath) {\n const anchor = Math.max(startAnchor, 0);\n contourStarts.push(out.length / 2);\n out.push(prevX, prevY);\n anchorA.push(anchor);\n anchorB.push(anchor);\n anchorT.push(0);\n prevAnchor = anchor;\n }\n switch (cmd) {\n case PATH_M:\n case PATH_L: {\n if (cmd === PATH_M) {\n contourStarts.push(out.length / 2);\n startAnchor = anchorCounter;\n }\n out.push(coords[coordIdx], coords[coordIdx + 1]);\n anchorA.push(anchorCounter);\n anchorB.push(anchorCounter);\n anchorT.push(0);\n prevAnchor = anchorCounter;\n anchorCounter++;\n break;\n }\n case PATH_Q: {\n const target = anchorCounter;\n const arcAccum: number[] = [];\n const anchorStart = anchorA.length;\n const total = flattenQuadraticWithArcLen(\n prevX, prevY,\n coords[coordIdx], coords[coordIdx + 1],\n coords[coordIdx + 2], coords[coordIdx + 3],\n tolerance, out, arcAccum,\n );\n pushCurveAnchors(anchorStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_C: {\n const target = anchorCounter;\n const arcAccum: number[] = [];\n const anchorStart = anchorA.length;\n const total = flattenCubicWithArcLen(\n prevX, prevY,\n coords[coordIdx], coords[coordIdx + 1],\n coords[coordIdx + 2], coords[coordIdx + 3],\n coords[coordIdx + 4], coords[coordIdx + 5],\n tolerance, out, arcAccum,\n );\n pushCurveAnchors(anchorStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_Z:\n closed.add(contourStarts.length - 1);\n // The pen returns to the subpath start (forEachSegment does that); the\n // anchor it carries has to follow, or a curve after the Z interpolates\n // from the wrong end.\n prevAnchor = startAnchor;\n break;\n default:\n throw new Error(`tessellate: unknown command code ${cmd}`);\n }\n });\n\n return { coords: out, contourStarts, anchorA, anchorB, anchorT };\n}\n\nfunction tessellatePolygon(p: PolygonPath, opts: TessellateOptions): Mesh {\n const tolerance = opts.flattenTolerance ?? DEFAULT_FLATTEN_TOLERANCE;\n const flat = flattenPolygon(p, tolerance);\n\n if (p.fillRule === 'evenodd') {\n const { coords, contourStarts, anchorA, anchorB, anchorT } = flat;\n return tessellateEvenoddWithAnchors(coords, contourStarts, anchorA, anchorB, anchorT);\n }\n const crossed = resolveCrossings(flat);\n if (crossed) return tessellateNonzero(crossed, nestRings(crossed));\n const rings = nestRings(flat);\n if (rings.every((r) => Math.abs(r.winding) <= 1)) return tessellateNonzero(flat, rings);\n // Nested same-wound rings would cover the region they share twice.\n const rebuilt = resolveCrossings(flat, true)!;\n return tessellateNonzero(rebuilt, nestRings(rebuilt));\n}\n\n/** Triangulate rings that do not cross and wind at most once anywhere: each\n * ring with fill inside it, less the rings directly inside it, which are its\n * holes. */\nfunction tessellateNonzero(flat: FlattenedContours, rings: Ring[]): Mesh {\n const { coords, contourStarts, anchorA, anchorB, anchorT } = flat;\n const shapes: number[] = [];\n const holesByShape = new Map<number, number[]>();\n rings.forEach((r, i) => {\n if (r.area === 0) return;\n if (r.winding !== 0) shapes.push(i);\n else if (holesByShape.has(r.parent)) holesByShape.get(r.parent)!.push(i);\n else holesByShape.set(r.parent, [i]);\n });\n\n if (shapes.length <= 1 && (shapes[0] ?? 0) === 0) {\n const tri = earcut(coords, contourStarts.length > 1 ? contourStarts.slice(1) : undefined);\n return {\n vertices: new Float32Array(coords),\n indices: new Uint32Array(tri),\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n }\n\n const finalCoords: number[] = [];\n const finalAnchorA: number[] = [];\n const finalAnchorB: number[] = [];\n const finalAnchorT: number[] = [];\n const finalIndices: number[] = [];\n for (const pos of shapes) {\n const holes = holesByShape.get(pos) ?? [];\n const offset = finalCoords.length / 2;\n const groupCoords: number[] = [];\n const groupStarts: number[] = [0];\n for (let i = rings[pos].start; i < rings[pos].end; i++) {\n groupCoords.push(coords[i * 2], coords[i * 2 + 1]);\n finalAnchorA.push(anchorA[i]);\n finalAnchorB.push(anchorB[i]);\n finalAnchorT.push(anchorT[i]);\n }\n for (const h of holes) {\n groupStarts.push(groupCoords.length / 2);\n for (let i = rings[h].start; i < rings[h].end; i++) {\n groupCoords.push(coords[i * 2], coords[i * 2 + 1]);\n finalAnchorA.push(anchorA[i]);\n finalAnchorB.push(anchorB[i]);\n finalAnchorT.push(anchorT[i]);\n }\n }\n const tri = earcut(groupCoords, groupStarts.length > 1 ? groupStarts.slice(1) : undefined);\n for (const v of groupCoords) finalCoords.push(v);\n for (const idx of tri) finalIndices.push(idx + offset);\n }\n\n return {\n vertices: new Float32Array(finalCoords),\n indices: new Uint32Array(finalIndices),\n anchorA: new Uint32Array(finalAnchorA),\n anchorB: new Uint32Array(finalAnchorB),\n anchorT: new Float32Array(finalAnchorT),\n };\n}\n\nfunction tessellateEvenoddWithAnchors(\n coords: number[],\n contourStarts: number[],\n anchorA: number[],\n anchorB: number[],\n anchorT: number[],\n): Mesh {\n const indices: number[] = [];\n const totalVerts = coords.length / 2;\n for (let c = 0; c < contourStarts.length; c++) {\n const start = contourStarts[c];\n const end = c + 1 < contourStarts.length ? contourStarts[c + 1] : totalVerts;\n for (let i = start + 1; i < end - 1; i++) {\n indices.push(start, i, i + 1);\n }\n }\n return {\n vertices: new Float32Array(coords),\n indices: new Uint32Array(indices),\n requiresStencil: true,\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n}\n"]}
|