@weasel-js/geom 1.15.2 → 1.16.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/3d/index.d.ts +13 -1
- package/dist/3d/index.js +11 -1
- package/dist/3d/index.js.map +1 -1
- package/dist/booleans/index.js +3 -2
- package/dist/booleans/index.js.map +1 -1
- package/dist/{chunk-IDSKOHA4.js → chunk-5W425HJA.js} +81 -15
- package/dist/chunk-5W425HJA.js.map +1 -0
- package/dist/chunk-FOXMA54X.js +266 -0
- package/dist/chunk-FOXMA54X.js.map +1 -0
- package/dist/chunk-IOD2NFHQ.js +212 -0
- package/dist/chunk-IOD2NFHQ.js.map +1 -0
- package/dist/{chunk-OQP5M5VD.js → chunk-OBPXEPUH.js} +3 -3
- package/dist/{chunk-OQP5M5VD.js.map → chunk-OBPXEPUH.js.map} +1 -1
- package/dist/chunk-QSVZO7QZ.js +40 -0
- package/dist/chunk-QSVZO7QZ.js.map +1 -0
- package/dist/{chunk-GA5R5KWD.js → chunk-TBS4NHGQ.js} +13 -30
- package/dist/chunk-TBS4NHGQ.js.map +1 -0
- package/dist/{chunk-MIKP4V2C.js → chunk-VJG5ZWCR.js} +3 -3
- package/dist/{chunk-MIKP4V2C.js.map → chunk-VJG5ZWCR.js.map} +1 -1
- package/dist/{chunk-STYO7J4Y.js → chunk-ZV24QZ6X.js} +3 -3
- package/dist/{chunk-STYO7J4Y.js.map → chunk-ZV24QZ6X.js.map} +1 -1
- package/dist/index.d.ts +86 -11
- package/dist/index.js +267 -128
- package/dist/index.js.map +1 -1
- package/dist/lengthTable-Cv3W6lsH.d.ts +64 -0
- package/dist/tessellate/index.d.ts +23 -1
- package/dist/tessellate/index.js +29 -15
- package/dist/tessellate/index.js.map +1 -1
- package/dist/warp/index.js +4 -3
- package/dist/warp/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-GA5R5KWD.js.map +0 -1
- package/dist/chunk-IDSKOHA4.js.map +0 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { segmentCoords, bezierPoint } from './chunk-QSVZO7QZ.js';
|
|
2
|
+
import { resolveCorners, DEFAULT_FLATTEN_TOLERANCE, flattenCubicWithArcLen, flattenQuadraticWithArcLen } from './chunk-TBS4NHGQ.js';
|
|
3
|
+
import { segmentLength } from './chunk-IOD2NFHQ.js';
|
|
2
4
|
import { rectToContour, forEachSegment, PATH_Z, PATH_C, PATH_Q, PATH_L, PATH_M } from './chunk-346XYYMX.js';
|
|
3
5
|
|
|
4
6
|
// src/tessellate/polyline.ts
|
|
@@ -27,6 +29,7 @@ function extractPolygon(p, opts) {
|
|
|
27
29
|
let aT = null;
|
|
28
30
|
let current = null;
|
|
29
31
|
let prevAnchor = -1;
|
|
32
|
+
let dropped;
|
|
30
33
|
let startAnchor = 0;
|
|
31
34
|
const beginContour = () => {
|
|
32
35
|
pts = [];
|
|
@@ -37,21 +40,13 @@ function extractPolygon(p, opts) {
|
|
|
37
40
|
out.push(next);
|
|
38
41
|
return next;
|
|
39
42
|
};
|
|
40
|
-
const dropDuplicateClosingPoint = () => {
|
|
41
|
-
if (!pts || !aA || !aB || !aT) return;
|
|
42
|
-
const n = pts.length / 2;
|
|
43
|
-
if (n < 2) return;
|
|
44
|
-
if (pts[0] !== pts[(n - 1) * 2] || pts[1] !== pts[(n - 1) * 2 + 1]) return;
|
|
45
|
-
pts.length -= 2;
|
|
46
|
-
aA.length -= 1;
|
|
47
|
-
aB.length -= 1;
|
|
48
|
-
aT.length -= 1;
|
|
49
|
-
};
|
|
50
43
|
const commit = (target) => {
|
|
51
44
|
if (!pts || !aA || !aB || !aT) return;
|
|
52
45
|
target.anchorA = new Uint32Array(aA);
|
|
53
46
|
target.anchorB = new Uint32Array(aB);
|
|
54
47
|
target.anchorT = new Float32Array(aT);
|
|
48
|
+
if (dropped !== void 0) target.closeAnchor = dropped;
|
|
49
|
+
dropped = void 0;
|
|
55
50
|
};
|
|
56
51
|
const pushCurveAnchors = (segStart, arcAccum, total, target) => {
|
|
57
52
|
for (let k = 0; k < arcAccum.length; k++) {
|
|
@@ -137,7 +132,7 @@ function extractPolygon(p, opts) {
|
|
|
137
132
|
case PATH_Z: {
|
|
138
133
|
if (current) {
|
|
139
134
|
current.closed = true;
|
|
140
|
-
dropDuplicateClosingPoint();
|
|
135
|
+
if (pts && aA && aB && aT) dropped = dropDuplicateClosingPoint(pts, aA, aB, aT) ?? dropped;
|
|
141
136
|
}
|
|
142
137
|
break;
|
|
143
138
|
}
|
|
@@ -148,7 +143,78 @@ function extractPolygon(p, opts) {
|
|
|
148
143
|
if (current) commit(current);
|
|
149
144
|
return out;
|
|
150
145
|
}
|
|
146
|
+
function dropDuplicateClosingPoint(pts, aA, aB, aT) {
|
|
147
|
+
const n = pts.length / 2;
|
|
148
|
+
if (n < 2) return void 0;
|
|
149
|
+
if (pts[0] !== pts[(n - 1) * 2] || pts[1] !== pts[(n - 1) * 2 + 1]) return void 0;
|
|
150
|
+
const anchor = aA[n - 1] === aB[n - 1] ? aA[n - 1] : void 0;
|
|
151
|
+
pts.length -= 2;
|
|
152
|
+
aA.length -= 1;
|
|
153
|
+
aB.length -= 1;
|
|
154
|
+
aT.length -= 1;
|
|
155
|
+
return anchor;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// src/tessellate/atCurve.ts
|
|
159
|
+
function polylineAtCurve(pl, segment, t, run) {
|
|
160
|
+
const p = pl.points;
|
|
161
|
+
const n = p.length / 2;
|
|
162
|
+
const ends = anchorIndices(pl, n);
|
|
163
|
+
if (ends.length < 2) return { length: 0, x: p[0] ?? 0, y: p[1] ?? 0 };
|
|
164
|
+
const k = Math.min(Math.max(Math.floor(segment), 0), ends.length - 2);
|
|
165
|
+
const f = Math.min(Math.max(t, 0), 1);
|
|
166
|
+
const i0 = ends[k];
|
|
167
|
+
const i1 = ends[k + 1];
|
|
168
|
+
const ctl = run?.controls?.[k];
|
|
169
|
+
const seg = ctl && ctl.length > 0 ? segmentCoords([p[i0 * 2], p[i0 * 2 + 1], p[i1 % n * 2], p[i1 % n * 2 + 1]], ctl, 2, 0) : null;
|
|
170
|
+
let x, y;
|
|
171
|
+
if (seg) [x, y] = bezierPoint(seg, 2, f);
|
|
172
|
+
else {
|
|
173
|
+
x = lerp(p[i0 * 2], p[i1 % n * 2], f);
|
|
174
|
+
y = lerp(p[i0 * 2 + 1], p[i1 % n * 2 + 1], f);
|
|
175
|
+
}
|
|
176
|
+
const { chord, u } = !seg && i1 - i0 === 1 ? { chord: i0, u: f } : chordOf(pl, n, i0, i1, x, y, seg ? arcShare(seg, f) : f);
|
|
177
|
+
let length = 0;
|
|
178
|
+
for (let i = 0; i < chord; i++) length += chordLength(p, n, i);
|
|
179
|
+
return { length: length + u * chordLength(p, n, chord), x, y };
|
|
180
|
+
}
|
|
181
|
+
function anchorIndices(pl, n) {
|
|
182
|
+
const { anchorA: A, anchorB: B } = pl;
|
|
183
|
+
const out = [];
|
|
184
|
+
for (let i = 0; i < n; i++) if (!A || !B || A[i] === B[i]) out.push(i);
|
|
185
|
+
if (pl.closed && n >= 2) out.push(n);
|
|
186
|
+
return out;
|
|
187
|
+
}
|
|
188
|
+
function chordOf(pl, n, i0, i1, x, y, share) {
|
|
189
|
+
const T = pl.anchorT;
|
|
190
|
+
const at = (i) => i >= i1 ? 1 : i <= i0 ? 0 : T ? T[i] : (i - i0) / (i1 - i0);
|
|
191
|
+
let j = i0;
|
|
192
|
+
while (j < i1 - 1 && at(j + 1) <= share) j++;
|
|
193
|
+
let u = project(pl.points, n, j, x, y);
|
|
194
|
+
const step = u < 0 ? -1 : u > 1 ? 1 : 0;
|
|
195
|
+
while (step !== 0 && j + step >= i0 && j + step < i1 && (step < 0 ? u < 0 : u > 1)) {
|
|
196
|
+
j += step;
|
|
197
|
+
u = project(pl.points, n, j, x, y);
|
|
198
|
+
}
|
|
199
|
+
return { chord: j, u: Math.min(Math.max(u, 0), 1) };
|
|
200
|
+
}
|
|
201
|
+
function project(p, n, i, x, y) {
|
|
202
|
+
const ax = p[i * 2], ay = p[i * 2 + 1];
|
|
203
|
+
const j = (i + 1) % n;
|
|
204
|
+
const dx = p[j * 2] - ax, dy = p[j * 2 + 1] - ay;
|
|
205
|
+
const l2 = dx * dx + dy * dy;
|
|
206
|
+
return l2 > 0 ? ((x - ax) * dx + (y - ay) * dy) / l2 : 0;
|
|
207
|
+
}
|
|
208
|
+
function chordLength(p, n, i) {
|
|
209
|
+
const j = (i + 1) % n;
|
|
210
|
+
return Math.hypot(p[j * 2] - p[i * 2], p[j * 2 + 1] - p[i * 2 + 1]);
|
|
211
|
+
}
|
|
212
|
+
function arcShare(seg, t) {
|
|
213
|
+
const whole = segmentLength(seg, 2);
|
|
214
|
+
return whole > 0 ? segmentLength(seg, 2, 0, t) / whole : t;
|
|
215
|
+
}
|
|
216
|
+
var lerp = (a, b, f) => a + (b - a) * f;
|
|
151
217
|
|
|
152
|
-
export { extractPolylines };
|
|
153
|
-
//# sourceMappingURL=chunk-
|
|
154
|
-
//# sourceMappingURL=chunk-
|
|
218
|
+
export { extractPolylines, polylineAtCurve };
|
|
219
|
+
//# sourceMappingURL=chunk-5W425HJA.js.map
|
|
220
|
+
//# sourceMappingURL=chunk-5W425HJA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tessellate/polyline.ts","../src/tessellate/atCurve.ts"],"names":[],"mappings":"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","file":"chunk-5W425HJA.js","sourcesContent":["import { forEachSegment, PATH_M, PATH_L, PATH_Z, PATH_C, PATH_Q } from '../commands';\nimport { resolveCorners } from '../paths/corners';\nimport { rectToContour } from '../box';\nimport { DEFAULT_FLATTEN_TOLERANCE, flattenCubicWithArcLen, flattenQuadraticWithArcLen } from '../flatten';\nimport type { Path, PolygonPath, RectPath } from '../path';\n\n/** One contour of a path, flattened to straight segments. */\nexport interface Polyline {\n /** Interleaved x,y vertices (length = 2 × point count). */\n points: number[];\n /** Whether the contour was closed (ends with Z, or is a RectPath). */\n closed: boolean;\n /** For each point, the previous anchor index. Anchor-aligned points set A === B. */\n anchorA?: Uint32Array;\n /** For each point, the next anchor index. */\n anchorB?: Uint32Array;\n /** For each point, the arc-length fraction along (A, B). 0 at anchor A; for anchor-aligned, set to 0. */\n anchorT?: Float32Array;\n /** A closed contour's last anchor when it repeated the first point and was\n * dropped for that; the closing edge ends at it. */\n closeAnchor?: number;\n /** Per-point stroke width, populated by the tessellator when the Stroke\n * carries `vertexWidths`. Undefined means uniform `Stroke.width`. */\n widths?: Float32Array;\n /** Per-point distance the ribbon's middle sits off the path toward the\n * normal `(−dy, dx)` of the direction of travel: half the right edge's\n * distance less the left's. Set alongside `widths` only when the two sides\n * differ somewhere; undefined means centered. */\n offsets?: Float32Array;\n}\n\n/** Options for `extractPolylines`. */\nexport interface ExtractOptions {\n flattenTolerance?: number;\n /** How far out from the path its outermost edge sits, as a stroke's half\n * width does. Flattening keeps that edge within `flattenTolerance` of the\n * true one too. Unset, only the path itself is. */\n offset?: number;\n}\n\n/** Flatten each contour of a path to a straight-segment polyline, carrying the\n * anchor parameterization per point. A rect yields one closed contour. */\nexport function extractPolylines(path: Path, opts: ExtractOptions = {}): Polyline[] {\n if (path.kind === 'rect') return [extractRect(path)];\n return extractPolygon(resolveCorners(path), opts);\n}\n\nfunction extractRect(p: RectPath): Polyline {\n const { x, y, width: w, height: h } = p;\n return {\n points: Array.from(rectToContour(x, y, w, h)),\n closed: true,\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\nfunction extractPolygon(p: PolygonPath, opts: ExtractOptions): Polyline[] {\n const tolerance = opts.flattenTolerance ?? DEFAULT_FLATTEN_TOLERANCE;\n const { commands, coords } = p;\n const out: Polyline[] = [];\n // Anchors are numbered globally (across all contours) in command-stream order.\n let anchorCounter = 0;\n\n // Builders for the current polyline.\n let pts: number[] | null = null;\n let aA: number[] | null = null;\n let aB: number[] | null = null;\n let aT: number[] | null = null;\n let current: Polyline | null = null;\n\n let prevAnchor = -1;\n let dropped: number | undefined;\n // The anchor a subpath opened by a bare drawing command starts from.\n let startAnchor = 0;\n\n const beginContour = (): Polyline => {\n pts = [];\n aA = [];\n aB = [];\n aT = [];\n const next: Polyline = { points: pts, closed: false };\n out.push(next);\n return next;\n };\n\n const commit = (target: Polyline): void => {\n if (!pts || !aA || !aB || !aT) return;\n target.anchorA = new Uint32Array(aA);\n target.anchorB = new Uint32Array(aB);\n target.anchorT = new Float32Array(aT);\n if (dropped !== undefined) target.closeAnchor = dropped;\n dropped = undefined;\n };\n\n // Fill anchorA/B/T for each point a curve just appended: interior points\n // interpolate (prevAnchor → target), and the final point is pinned to the\n // target so the draw-time lerp returns anchor B's color exactly.\n const pushCurveAnchors = (segStart: number, arcAccum: number[], total: number, target: number): void => {\n for (let k = 0; k < arcAccum.length; k++) {\n aA!.push(prevAnchor);\n aB!.push(target);\n aT!.push(total > 0 ? arcAccum[k] / total : 0);\n }\n const lastIdx = (segStart + arcAccum.length) - 1;\n aA![lastIdx] = target;\n aB![lastIdx] = target;\n aT![lastIdx] = 0;\n };\n\n forEachSegment(commands, coords, (cmd, coordIdx, prevX, prevY, _i, opensSubpath) => {\n if (opensSubpath) {\n if (current) commit(current);\n current = beginContour();\n pts!.push(prevX, prevY);\n aA!.push(startAnchor);\n aB!.push(startAnchor);\n aT!.push(0);\n prevAnchor = startAnchor;\n }\n switch (cmd) {\n case PATH_M:\n case PATH_L: {\n if (cmd === PATH_M) {\n if (current) commit(current);\n current = beginContour();\n startAnchor = anchorCounter;\n }\n pts!.push(coords[coordIdx], coords[coordIdx + 1]);\n aA!.push(anchorCounter);\n aB!.push(anchorCounter);\n aT!.push(0);\n prevAnchor = anchorCounter;\n anchorCounter++;\n break;\n }\n case PATH_Q: {\n const target = anchorCounter;\n const segStart = pts!.length / 2;\n const arcAccum: number[] = [];\n const total = flattenQuadraticWithArcLen(\n prevX, prevY,\n coords[coordIdx], coords[coordIdx + 1],\n coords[coordIdx + 2], coords[coordIdx + 3],\n tolerance, pts!, arcAccum, opts.offset,\n );\n pushCurveAnchors(segStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_C: {\n const target = anchorCounter;\n const segStart = pts!.length / 2;\n const arcAccum: number[] = [];\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, pts!, arcAccum, opts.offset,\n );\n pushCurveAnchors(segStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_Z: {\n if (current) {\n current.closed = true;\n if (pts && aA && aB && aT) dropped = dropDuplicateClosingPoint(pts, aA, aB, aT) ?? dropped;\n }\n break;\n }\n default:\n throw new Error(`extractPolylines: unknown command code ${cmd}`);\n }\n });\n\n if (current) commit(current);\n return out;\n}\n\n/**\n * A closed contour's last point repeating its first leaves a zero-length\n * closing segment, which the stroker discards along with the wrap-around\n * join it should have carried, notching the ribbon at the contour's start.\n * Every font outline serialized by opentype.js is written this way. Exact\n * equality is the right test: the duplicate is a re-emission of the same\n * number, and a near-miss is a genuine (if tiny) segment the author asked for.\n * Answers the dropped point's anchor, when it was one.\n */\nfunction dropDuplicateClosingPoint(pts: number[], aA: number[], aB: number[], aT: number[]): number | undefined {\n const n = pts.length / 2;\n if (n < 2) return undefined;\n if (pts[0] !== pts[(n - 1) * 2] || pts[1] !== pts[(n - 1) * 2 + 1]) return undefined;\n const anchor = aA[n - 1] === aB[n - 1] ? aA[n - 1] : undefined;\n pts.length -= 2;\n aA.length -= 1;\n aB.length -= 1;\n aT.length -= 1;\n return anchor;\n}\n","import { bezierPoint, segmentCoords } from '../along/bezier';\nimport type { LengthRun } from '../along/lengthTable';\nimport { segmentLength } from '../paths/segmentLength';\nimport type { Polyline } from './polyline';\n\n/** A curve position found on one flattening of its run. */\nexport interface PolylinePlace {\n /** How far from the polyline's first point it sits, along the polyline: the polyline's own measure. */\n length: number;\n /** The point itself, on the curve rather than on the chord beside it. */\n x: number;\n y: number;\n}\n\n/**\n * Where curve position (`segment`, `t`) falls on `pl`, a flattening of `run`.\n * Segment `k` runs from `pl`'s `k`-th anchor-aligned point to the next, a\n * closed `pl`'s closing edge last, as `pathLengthTable` counts them; `run`\n * gives each curve's control points, and without one every segment is\n * straight. The ends come from `pl`, so a run of the same shape carried\n * elsewhere (a rect shifted by alignment) places onto it too.\n */\nexport function polylineAtCurve(pl: Polyline, segment: number, t: number, run?: LengthRun): PolylinePlace {\n const p = pl.points;\n const n = p.length / 2;\n const ends = anchorIndices(pl, n);\n if (ends.length < 2) return { length: 0, x: p[0] ?? 0, y: p[1] ?? 0 };\n const k = Math.min(Math.max(Math.floor(segment), 0), ends.length - 2);\n const f = Math.min(Math.max(t, 0), 1);\n const i0 = ends[k];\n const i1 = ends[k + 1];\n const ctl = run?.controls?.[k];\n const seg = ctl && ctl.length > 0 ? segmentCoords([p[i0 * 2], p[i0 * 2 + 1], p[(i1 % n) * 2], p[(i1 % n) * 2 + 1]], ctl, 2, 0) : null;\n let x: number, y: number;\n if (seg) [x, y] = bezierPoint(seg, 2, f);\n else {\n x = lerp(p[i0 * 2], p[(i1 % n) * 2], f);\n y = lerp(p[i0 * 2 + 1], p[(i1 % n) * 2 + 1], f);\n }\n const { chord, u } = !seg && i1 - i0 === 1 ? { chord: i0, u: f } : chordOf(pl, n, i0, i1, x, y, seg ? arcShare(seg, f) : f);\n let length = 0;\n for (let i = 0; i < chord; i++) length += chordLength(p, n, i);\n return { length: length + u * chordLength(p, n, chord), x, y };\n}\n\n/** The indices of `pl`'s anchor-aligned points, then `n` for a closed one's return to its first. */\nfunction anchorIndices(pl: Polyline, n: number): number[] {\n const { anchorA: A, anchorB: B } = pl;\n const out: number[] = [];\n for (let i = 0; i < n; i++) if (!A || !B || A[i] === B[i]) out.push(i);\n if (pl.closed && n >= 2) out.push(n);\n return out;\n}\n\n/** Of the chords from `i0` to `i1`, the one point (x, y) lies beside and how far along it: first by\n * arc-length share `share`, then by projection, which a flattening keeps within its tolerance. */\nfunction chordOf(\n pl: Polyline, n: number, i0: number, i1: number, x: number, y: number, share: number,\n): { chord: number; u: number } {\n const T = pl.anchorT;\n const at = (i: number) => (i >= i1 ? 1 : i <= i0 ? 0 : T ? T[i] : (i - i0) / (i1 - i0));\n let j = i0;\n while (j < i1 - 1 && at(j + 1) <= share) j++;\n let u = project(pl.points, n, j, x, y);\n // Step toward the chord the point projects onto, never back the way it came.\n const step = u < 0 ? -1 : u > 1 ? 1 : 0;\n while (step !== 0 && j + step >= i0 && j + step < i1 && (step < 0 ? u < 0 : u > 1)) {\n j += step;\n u = project(pl.points, n, j, x, y);\n }\n return { chord: j, u: Math.min(Math.max(u, 0), 1) };\n}\n\nfunction project(p: readonly number[], n: number, i: number, x: number, y: number): number {\n const ax = p[i * 2], ay = p[i * 2 + 1];\n const j = (i + 1) % n;\n const dx = p[j * 2] - ax, dy = p[j * 2 + 1] - ay;\n const l2 = dx * dx + dy * dy;\n return l2 > 0 ? ((x - ax) * dx + (y - ay) * dy) / l2 : 0;\n}\n\nfunction chordLength(p: readonly number[], n: number, i: number): number {\n const j = (i + 1) % n;\n return Math.hypot(p[j * 2] - p[i * 2], p[j * 2 + 1] - p[i * 2 + 1]);\n}\n\n/** The share of `seg`'s arc length that lies before parameter `t`. */\nfunction arcShare(seg: readonly number[], t: number): number {\n const whole = segmentLength(seg, 2);\n return whole > 0 ? segmentLength(seg, 2, 0, t) / whole : t;\n}\n\nconst lerp = (a: number, b: number, f: number): number => a + (b - a) * f;\n"]}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { segmentCoords, bezierDirection, bezierPoint } from './chunk-QSVZO7QZ.js';
|
|
2
|
+
import { arcLookup, segmentLength, lookupT } from './chunk-IOD2NFHQ.js';
|
|
3
|
+
|
|
4
|
+
// src/along/lengthTable.ts
|
|
5
|
+
var INTERNALS = /* @__PURE__ */ Symbol("lengthTable.internals");
|
|
6
|
+
function lengthTable(runs, dim, anchorSources) {
|
|
7
|
+
const runStart = new Float64Array(runs.length + 1);
|
|
8
|
+
const cum = [];
|
|
9
|
+
let total = 0;
|
|
10
|
+
runs.forEach((run, r) => {
|
|
11
|
+
const c = runLengths(run, dim, total);
|
|
12
|
+
cum.push(c);
|
|
13
|
+
total = c[c.length - 1];
|
|
14
|
+
runStart[r + 1] = total;
|
|
15
|
+
});
|
|
16
|
+
const anchors = anchorBreakpoints(runs, dim, cum, anchorSources ?? null);
|
|
17
|
+
const table = { dim, runs, total, runStart, segments: anchors.segments };
|
|
18
|
+
table[INTERNALS] = { cum, ...anchors, arcs: runs.map(() => []) };
|
|
19
|
+
return table;
|
|
20
|
+
}
|
|
21
|
+
function segmentArc(t, r, i) {
|
|
22
|
+
const ctl = t.runs[r].controls?.[i];
|
|
23
|
+
if (!ctl || ctl.length === 0) return null;
|
|
24
|
+
const arcs = tableInternals(t).arcs[r];
|
|
25
|
+
let arc = arcs[i];
|
|
26
|
+
if (!arc) {
|
|
27
|
+
const coords = segmentCoords(t.runs[r].points, ctl, t.dim, i);
|
|
28
|
+
arcs[i] = arc = { coords, lookup: arcLookup(coords, t.dim) };
|
|
29
|
+
}
|
|
30
|
+
return arc;
|
|
31
|
+
}
|
|
32
|
+
function tableInternals(t) {
|
|
33
|
+
const hit = t[INTERNALS];
|
|
34
|
+
if (!hit) throw new Error("LengthTable: not built by lengthTable(); build one with it rather than by hand");
|
|
35
|
+
return hit;
|
|
36
|
+
}
|
|
37
|
+
function lengthAtAnchor(t, anchor) {
|
|
38
|
+
if (Number.isNaN(anchor)) return NaN;
|
|
39
|
+
const { bpAnchor, bpLength } = tableInternals(t);
|
|
40
|
+
const n = bpAnchor.length;
|
|
41
|
+
if (n === 0) return 0;
|
|
42
|
+
if (anchor <= bpAnchor[0]) return bpLength[0];
|
|
43
|
+
if (anchor >= bpAnchor[n - 1]) return bpLength[n - 1];
|
|
44
|
+
let lo = 0;
|
|
45
|
+
let hi = n - 1;
|
|
46
|
+
while (hi - lo > 1) {
|
|
47
|
+
const mid = lo + hi >> 1;
|
|
48
|
+
if (bpAnchor[mid] <= anchor) lo = mid;
|
|
49
|
+
else hi = mid;
|
|
50
|
+
}
|
|
51
|
+
const span = bpAnchor[hi] - bpAnchor[lo];
|
|
52
|
+
const f = span > 0 ? (anchor - bpAnchor[lo]) / span : 1;
|
|
53
|
+
return bpLength[lo] + f * (bpLength[hi] - bpLength[lo]);
|
|
54
|
+
}
|
|
55
|
+
function anchorAtLength(t, s) {
|
|
56
|
+
if (Number.isNaN(s)) return NaN;
|
|
57
|
+
const { bpAnchor, bpLength } = tableInternals(t);
|
|
58
|
+
const n = bpAnchor.length;
|
|
59
|
+
if (n === 0) return 0;
|
|
60
|
+
if (s <= bpLength[0]) return bpAnchor[0];
|
|
61
|
+
if (s >= bpLength[n - 1]) return bpAnchor[n - 1];
|
|
62
|
+
let lo = 0;
|
|
63
|
+
let hi = n - 1;
|
|
64
|
+
while (hi - lo > 1) {
|
|
65
|
+
const mid = lo + hi >> 1;
|
|
66
|
+
if (bpLength[mid] <= s) lo = mid;
|
|
67
|
+
else hi = mid;
|
|
68
|
+
}
|
|
69
|
+
const f = (s - bpLength[lo]) / (bpLength[hi] - bpLength[lo]);
|
|
70
|
+
return bpAnchor[lo] + f * (bpAnchor[hi] - bpAnchor[lo]);
|
|
71
|
+
}
|
|
72
|
+
function lengthAtSubpath(t, subpath) {
|
|
73
|
+
if (Number.isNaN(subpath)) return NaN;
|
|
74
|
+
const n = t.runs.length;
|
|
75
|
+
const c = Math.min(Math.max(subpath, 0), n);
|
|
76
|
+
const i = Math.floor(c);
|
|
77
|
+
if (i >= n) return t.total;
|
|
78
|
+
return t.runStart[i] + (c - i) * (t.runStart[i + 1] - t.runStart[i]);
|
|
79
|
+
}
|
|
80
|
+
function lengthAtSegmentFraction(t, f) {
|
|
81
|
+
if (Number.isNaN(f)) return NaN;
|
|
82
|
+
const c = Math.min(Math.max(f, 0), 1);
|
|
83
|
+
if (t.segments <= 0) return c * t.total;
|
|
84
|
+
const { runAnchor } = tableInternals(t);
|
|
85
|
+
let s = c * t.segments;
|
|
86
|
+
for (let r = 0; r < runAnchor.length / 2; r++) {
|
|
87
|
+
const start = runAnchor[r * 2];
|
|
88
|
+
const span = runAnchor[r * 2 + 1] - start;
|
|
89
|
+
if (span > 0 && s <= span) return lengthAtAnchor(t, start + s);
|
|
90
|
+
s -= Math.max(span, 0);
|
|
91
|
+
}
|
|
92
|
+
return t.total;
|
|
93
|
+
}
|
|
94
|
+
var wraps = (run, n) => run.closed && (n >= 2 || n === 1 && (run.controls?.[0]?.length ?? 0) > 0);
|
|
95
|
+
function runLengths(run, dim, base) {
|
|
96
|
+
const p = run.points;
|
|
97
|
+
const n = Math.floor(p.length / dim);
|
|
98
|
+
const wrap = wraps(run, n);
|
|
99
|
+
const c = new Float64Array(Math.max(n + (wrap ? 1 : 0), 1));
|
|
100
|
+
c[0] = base;
|
|
101
|
+
for (let i = 1; i < c.length; i++) {
|
|
102
|
+
const ctl = run.controls?.[i - 1];
|
|
103
|
+
if (ctl && ctl.length > 0) {
|
|
104
|
+
const len = segmentLength(segmentCoords(p, ctl, dim, i - 1), dim);
|
|
105
|
+
c[i] = c[i - 1] + (Number.isFinite(len) ? len : 0);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
const a = (i - 1) * dim;
|
|
109
|
+
const b = i % n * dim;
|
|
110
|
+
let d2 = 0;
|
|
111
|
+
for (let k = 0; k < dim; k++) d2 += (p[b + k] - p[a + k]) ** 2;
|
|
112
|
+
c[i] = c[i - 1] + Math.sqrt(d2);
|
|
113
|
+
}
|
|
114
|
+
return c;
|
|
115
|
+
}
|
|
116
|
+
function anchorBreakpoints(runs, dim, cum, sources) {
|
|
117
|
+
const ids = [];
|
|
118
|
+
const lens = [];
|
|
119
|
+
const runAnchor = new Float64Array(runs.length * 2);
|
|
120
|
+
let segments = 0;
|
|
121
|
+
let next = 0;
|
|
122
|
+
runs.forEach((run, r) => {
|
|
123
|
+
const n = Math.floor(run.points.length / dim);
|
|
124
|
+
const c = cum[r];
|
|
125
|
+
const raw = expandedBreaks(run, n, c, next);
|
|
126
|
+
next += n;
|
|
127
|
+
const folded = foldToAuthored(raw, sources, wraps(run, n));
|
|
128
|
+
if (folded.ids.length === 0) return;
|
|
129
|
+
const first = folded.ids[0];
|
|
130
|
+
let last = folded.ids[folded.ids.length - 1];
|
|
131
|
+
if (wraps(run, n)) {
|
|
132
|
+
last += 1;
|
|
133
|
+
folded.ids.push(last);
|
|
134
|
+
folded.lens.push(c[c.length - 1]);
|
|
135
|
+
}
|
|
136
|
+
runAnchor[r * 2] = first;
|
|
137
|
+
runAnchor[r * 2 + 1] = last;
|
|
138
|
+
segments += last - first;
|
|
139
|
+
ids.push(...folded.ids);
|
|
140
|
+
lens.push(...folded.lens);
|
|
141
|
+
});
|
|
142
|
+
return { bpAnchor: Float64Array.from(ids), bpLength: Float64Array.from(lens), runAnchor, segments };
|
|
143
|
+
}
|
|
144
|
+
function expandedBreaks(run, n, c, next) {
|
|
145
|
+
const ids = [];
|
|
146
|
+
const lens = [];
|
|
147
|
+
const { anchorA: A, anchorB: B } = run;
|
|
148
|
+
if (!A || !B) {
|
|
149
|
+
for (let i = 0; i < n; i++) {
|
|
150
|
+
ids.push(next + i);
|
|
151
|
+
lens.push(c[i]);
|
|
152
|
+
}
|
|
153
|
+
return { ids, lens };
|
|
154
|
+
}
|
|
155
|
+
for (let i = 0; i < n; i++) {
|
|
156
|
+
if (A[i] === B[i]) {
|
|
157
|
+
ids.push(A[i]);
|
|
158
|
+
lens.push(c[i]);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const dropped = closingAnchorOf(run, n);
|
|
162
|
+
if (dropped !== void 0) {
|
|
163
|
+
ids.push(dropped);
|
|
164
|
+
lens.push(c[n]);
|
|
165
|
+
}
|
|
166
|
+
return { ids, lens };
|
|
167
|
+
}
|
|
168
|
+
function closingAnchor(run, dim = 2) {
|
|
169
|
+
return closingAnchorOf(run, Math.floor(run.points.length / dim));
|
|
170
|
+
}
|
|
171
|
+
function closingAnchorOf(run, n) {
|
|
172
|
+
const { anchorA: A, anchorB: B } = run;
|
|
173
|
+
if (!wraps(run, n)) return void 0;
|
|
174
|
+
if (run.closeAnchor !== void 0) return run.closeAnchor;
|
|
175
|
+
return A && B && A[n - 1] !== B[n - 1] ? B[n - 1] : void 0;
|
|
176
|
+
}
|
|
177
|
+
function foldToAuthored(raw, sources, closed) {
|
|
178
|
+
const ids = [];
|
|
179
|
+
const lens = [];
|
|
180
|
+
let lo = 0;
|
|
181
|
+
let hi = 0;
|
|
182
|
+
const flush = () => {
|
|
183
|
+
if (ids.length > lens.length) lens.push((lo + hi) / 2);
|
|
184
|
+
};
|
|
185
|
+
for (let i = 0; i < raw.ids.length; i++) {
|
|
186
|
+
const id = sources ? sources[raw.ids[i]] ?? raw.ids[i] : raw.ids[i];
|
|
187
|
+
const len = raw.lens[i];
|
|
188
|
+
if (closed && ids.length > 0 && id === ids[0]) continue;
|
|
189
|
+
if (ids.length > 0 && id === ids[ids.length - 1]) {
|
|
190
|
+
hi = len;
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
flush();
|
|
194
|
+
ids.push(id);
|
|
195
|
+
lo = len;
|
|
196
|
+
hi = len;
|
|
197
|
+
}
|
|
198
|
+
flush();
|
|
199
|
+
return { ids, lens };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// src/along/positions.ts
|
|
203
|
+
function pointAtLength(t, s) {
|
|
204
|
+
const { cum } = tableInternals(t);
|
|
205
|
+
const len = Number.isNaN(s) ? 0 : Math.min(Math.max(s, 0), t.total);
|
|
206
|
+
let r = cum.findIndex((c2, i) => c2.length >= 2 && len <= t.runStart[i + 1]);
|
|
207
|
+
if (r < 0) {
|
|
208
|
+
r = t.runs.length - 1;
|
|
209
|
+
while (r >= 0 && t.runs[r].points.length < t.dim) r--;
|
|
210
|
+
if (r < 0) return { point: [0, 0, 0], tangent: [0, 0, 0] };
|
|
211
|
+
return { point: at(t, r, 0), tangent: [0, 0, 0] };
|
|
212
|
+
}
|
|
213
|
+
const c = cum[r];
|
|
214
|
+
let lo = 0;
|
|
215
|
+
let hi = c.length - 2;
|
|
216
|
+
while (lo < hi) {
|
|
217
|
+
const mid = lo + hi >> 1;
|
|
218
|
+
if (c[mid + 1] < len) lo = mid + 1;
|
|
219
|
+
else hi = mid;
|
|
220
|
+
}
|
|
221
|
+
return pointOnSegment(t, r, lo, len);
|
|
222
|
+
}
|
|
223
|
+
function pointOnSegment(t, r, i, len) {
|
|
224
|
+
const c = tableInternals(t).cum[r];
|
|
225
|
+
const span = c[i + 1] - c[i];
|
|
226
|
+
const local = Math.min(Math.max(len - c[i], 0), span);
|
|
227
|
+
const arc = segmentArc(t, r, i);
|
|
228
|
+
if (arc) {
|
|
229
|
+
const u = lookupT(arc.coords, t.dim, arc.lookup, local);
|
|
230
|
+
return { point: bezierPoint(arc.coords, t.dim, u), tangent: bezierDirection(arc.coords, t.dim, u) ?? tangentNear(t, r, i) };
|
|
231
|
+
}
|
|
232
|
+
const f = span > 0 ? local / span : 0;
|
|
233
|
+
const a = at(t, r, i);
|
|
234
|
+
const b = at(t, r, i + 1);
|
|
235
|
+
return { point: [lerp(a[0], b[0], f), lerp(a[1], b[1], f), lerp(a[2], b[2], f)], tangent: tangentNear(t, r, i) };
|
|
236
|
+
}
|
|
237
|
+
function at(t, r, i) {
|
|
238
|
+
const { points } = t.runs[r];
|
|
239
|
+
const n = Math.floor(points.length / t.dim);
|
|
240
|
+
const o = i % n * t.dim;
|
|
241
|
+
return [points[o], points[o + 1], t.dim === 3 ? points[o + 2] : 0];
|
|
242
|
+
}
|
|
243
|
+
function tangentNear(t, r, i) {
|
|
244
|
+
const last = tableInternals(t).cum[r].length - 2;
|
|
245
|
+
for (let k = i; k >= 0; k--) {
|
|
246
|
+
const d = direction(t, r, k);
|
|
247
|
+
if (d) return d;
|
|
248
|
+
}
|
|
249
|
+
for (let k = i + 1; k <= last; k++) {
|
|
250
|
+
const d = direction(t, r, k);
|
|
251
|
+
if (d) return d;
|
|
252
|
+
}
|
|
253
|
+
return [0, 0, 0];
|
|
254
|
+
}
|
|
255
|
+
function direction(t, r, i) {
|
|
256
|
+
const a = at(t, r, i);
|
|
257
|
+
const b = at(t, r, i + 1);
|
|
258
|
+
const d = [b[0] - a[0], b[1] - a[1], b[2] - a[2]];
|
|
259
|
+
const l = Math.hypot(d[0], d[1], d[2]);
|
|
260
|
+
return l > 0 ? [d[0] / l, d[1] / l, d[2] / l] : null;
|
|
261
|
+
}
|
|
262
|
+
var lerp = (a, b, f) => a + (b - a) * f;
|
|
263
|
+
|
|
264
|
+
export { anchorAtLength, closingAnchor, lengthAtAnchor, lengthAtSegmentFraction, lengthAtSubpath, lengthTable, pointAtLength, pointOnSegment, segmentArc, tableInternals };
|
|
265
|
+
//# sourceMappingURL=chunk-FOXMA54X.js.map
|
|
266
|
+
//# sourceMappingURL=chunk-FOXMA54X.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/along/lengthTable.ts","../src/along/positions.ts"],"names":["c"],"mappings":"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","file":"chunk-FOXMA54X.js","sourcesContent":["import { arcLookup, segmentLength, type ArcLookup } from '../paths/segmentLength';\nimport { segmentCoords } from './bezier';\n\n/** One subpath of a path in pen order: points joined by straight segments, or by curves where `controls` gives them. */\nexport interface LengthRun {\n /** `dim` components per point. A closed run does not repeat its first point. */\n points: ArrayLike<number>;\n /** Whether a closing edge runs from the last point back to the first. */\n closed: boolean;\n /** Per point, the anchor before it, the anchor after it, and the arc-length\n * fraction between them, as `Polyline` carries them. Absent, every point is\n * an anchor, numbered on from the previous run's. */\n anchorA?: ArrayLike<number>;\n anchorB?: ArrayLike<number>;\n anchorT?: ArrayLike<number>;\n /** A closed run's last anchor when it sat on the first point and was dropped, as `Polyline` carries it. */\n closeAnchor?: number;\n /** Per segment, from point `i` to the next (a closed run's closing edge last), the control\n * points of the curve between them, `dim` components each; empty, null or absent where\n * the segment is straight. A curved segment is measured by its exact arc length. */\n controls?: readonly (ArrayLike<number> | null | undefined)[];\n}\n\n/** A stretch of a path between two pen-order lengths, `from` before `to`. */\nexport interface LengthSpan {\n from: number;\n to: number;\n}\n\n/** A path's arc length in pen order: subpaths in order, the lift between them covering no distance. */\nexport interface LengthTable {\n readonly dim: 2 | 3;\n readonly runs: readonly LengthRun[];\n /** Pen-order length, closing edges included. */\n readonly total: number;\n /** Where each run starts, `runs.length + 1` entries; the last is `total`. */\n readonly runStart: Float64Array;\n /** The anchor range: per subpath, the segments between its anchors, a closed one's closing edge included. */\n readonly segments: number;\n}\n\n/** @internal What the queries read, kept off the public shape. */\nexport interface LengthTableInternals {\n /** Per run, the pen-order length at each point, then at the closing edge's end for a closed run. */\n cum: Float64Array[];\n /** Authored anchor positions and their lengths, both ascending. */\n bpAnchor: Float64Array;\n bpLength: Float64Array;\n /** Per run, its first anchor and the anchor its last segment ends at. */\n runAnchor: Float64Array;\n /** Per run and segment, a curve's control points and arc lookup, filled on first query. */\n arcs: (SegmentArc | undefined)[][];\n}\n\n/** @internal A curved segment as flat control points, with its {@link ArcLookup}. */\nexport interface SegmentArc {\n coords: number[];\n lookup: ArcLookup;\n}\n\n// A symbol rather than a side table, so a spread copy of a table still answers.\nconst INTERNALS = Symbol('lengthTable.internals');\ntype WithInternals = LengthTable & { [INTERNALS]?: LengthTableInternals };\n\n/**\n * The length table of `runs`, in `dim` components per point. `anchorSources`\n * (from `resolveCornersWithSources`) maps the anchors of a corner-expanded path\n * back to the authored ones, so anchor queries answer in authored numbering:\n * an anchor rounded into an arc sits at the arc's midpoint.\n */\nexport function lengthTable(runs: readonly LengthRun[], dim: 2 | 3, anchorSources?: Uint32Array | null): LengthTable {\n const runStart = new Float64Array(runs.length + 1);\n const cum: Float64Array[] = [];\n let total = 0;\n runs.forEach((run, r) => {\n const c = runLengths(run, dim, total);\n cum.push(c);\n total = c[c.length - 1];\n runStart[r + 1] = total;\n });\n const anchors = anchorBreakpoints(runs, dim, cum, anchorSources ?? null);\n const table: WithInternals = { dim, runs, total, runStart, segments: anchors.segments };\n table[INTERNALS] = { cum, ...anchors, arcs: runs.map(() => []) };\n return table;\n}\n\n/** @internal Segment `i` of run `r` when it is a curve, with its arc lookup, built on first use; null when straight. */\nexport function segmentArc(t: LengthTable, r: number, i: number): SegmentArc | null {\n const ctl = t.runs[r].controls?.[i];\n if (!ctl || ctl.length === 0) return null;\n const arcs = tableInternals(t).arcs[r];\n let arc = arcs[i];\n if (!arc) {\n const coords = segmentCoords(t.runs[r].points, ctl, t.dim, i);\n arcs[i] = arc = { coords, lookup: arcLookup(coords, t.dim) };\n }\n return arc;\n}\n\n/** @internal */\nexport function tableInternals(t: LengthTable): LengthTableInternals {\n const hit = (t as WithInternals)[INTERNALS];\n if (!hit) throw new Error('LengthTable: not built by lengthTable(); build one with it rather than by hand');\n return hit;\n}\n\n/** The pen-order length at authored anchor position `anchor`; `3.5` is halfway\n * along the segment from anchor 3 by length. Clamps to the path. */\nexport function lengthAtAnchor(t: LengthTable, anchor: number): number {\n if (Number.isNaN(anchor)) return NaN;\n const { bpAnchor, bpLength } = tableInternals(t);\n const n = bpAnchor.length;\n if (n === 0) return 0;\n if (anchor <= bpAnchor[0]) return bpLength[0];\n if (anchor >= bpAnchor[n - 1]) return bpLength[n - 1];\n let lo = 0;\n let hi = n - 1;\n while (hi - lo > 1) {\n const mid = (lo + hi) >> 1;\n if (bpAnchor[mid] <= anchor) lo = mid;\n else hi = mid;\n }\n const span = bpAnchor[hi] - bpAnchor[lo];\n const f = span > 0 ? (anchor - bpAnchor[lo]) / span : 1;\n return bpLength[lo] + f * (bpLength[hi] - bpLength[lo]);\n}\n\n/** The authored anchor position at pen length `s`: the inverse of\n * {@link lengthAtAnchor}. Where a pen lift puts two anchors at one length,\n * the later. Clamps to the path. */\nexport function anchorAtLength(t: LengthTable, s: number): number {\n if (Number.isNaN(s)) return NaN;\n const { bpAnchor, bpLength } = tableInternals(t);\n const n = bpAnchor.length;\n if (n === 0) return 0;\n if (s <= bpLength[0]) return bpAnchor[0];\n if (s >= bpLength[n - 1]) return bpAnchor[n - 1];\n let lo = 0;\n let hi = n - 1;\n while (hi - lo > 1) {\n const mid = (lo + hi) >> 1;\n if (bpLength[mid] <= s) lo = mid;\n else hi = mid;\n }\n const f = (s - bpLength[lo]) / (bpLength[hi] - bpLength[lo]);\n return bpAnchor[lo] + f * (bpAnchor[hi] - bpAnchor[lo]);\n}\n\n/** The pen-order length at the start of subpath `subpath`; a fractional part\n * goes that share of the way along it by length. Clamps to the path. */\nexport function lengthAtSubpath(t: LengthTable, subpath: number): number {\n if (Number.isNaN(subpath)) return NaN;\n const n = t.runs.length;\n const c = Math.min(Math.max(subpath, 0), n);\n const i = Math.floor(c);\n if (i >= n) return t.total;\n return t.runStart[i] + (c - i) * (t.runStart[i + 1] - t.runStart[i]);\n}\n\n/** The pen-order length at fraction `f` of the anchor range: each segment an\n * equal share, a pen lift none. Clamps to the path. */\nexport function lengthAtSegmentFraction(t: LengthTable, f: number): number {\n if (Number.isNaN(f)) return NaN;\n const c = Math.min(Math.max(f, 0), 1);\n if (t.segments <= 0) return c * t.total;\n const { runAnchor } = tableInternals(t);\n let s = c * t.segments;\n for (let r = 0; r < runAnchor.length / 2; r++) {\n const start = runAnchor[r * 2];\n const span = runAnchor[r * 2 + 1] - start;\n if (span > 0 && s <= span) return lengthAtAnchor(t, start + s);\n s -= Math.max(span, 0);\n }\n return t.total;\n}\n\n/** Whether `run`, of `n` points, has a closing edge: a lone point closes only through a curve back to itself. */\nconst wraps = (run: LengthRun, n: number): boolean =>\n run.closed && (n >= 2 || (n === 1 && (run.controls?.[0]?.length ?? 0) > 0));\n\nfunction runLengths(run: LengthRun, dim: 2 | 3, base: number): Float64Array {\n const p = run.points;\n const n = Math.floor(p.length / dim);\n const wrap = wraps(run, n);\n const c = new Float64Array(Math.max(n + (wrap ? 1 : 0), 1));\n c[0] = base;\n for (let i = 1; i < c.length; i++) {\n const ctl = run.controls?.[i - 1];\n if (ctl && ctl.length > 0) {\n // A curve whose coordinates are not finite flattens to its end point, covering no distance.\n const len = segmentLength(segmentCoords(p, ctl, dim, i - 1), dim);\n c[i] = c[i - 1] + (Number.isFinite(len) ? len : 0);\n continue;\n }\n const a = (i - 1) * dim;\n const b = (i % n) * dim;\n let d2 = 0;\n for (let k = 0; k < dim; k++) d2 += (p[b + k] - p[a + k]) ** 2;\n c[i] = c[i - 1] + Math.sqrt(d2);\n }\n return c;\n}\n\n/** Per run, its anchor-aligned points as (expanded anchor, length) pairs, then\n * folded into authored numbering. */\nfunction anchorBreakpoints(\n runs: readonly LengthRun[], dim: number, cum: readonly Float64Array[], sources: Uint32Array | null,\n): Omit<LengthTableInternals, 'cum' | 'arcs'> & { segments: number } {\n const ids: number[] = [];\n const lens: number[] = [];\n const runAnchor = new Float64Array(runs.length * 2);\n let segments = 0;\n let next = 0;\n runs.forEach((run, r) => {\n const n = Math.floor(run.points.length / dim);\n const c = cum[r];\n const raw = expandedBreaks(run, n, c, next);\n next += n;\n const folded = foldToAuthored(raw, sources, wraps(run, n));\n if (folded.ids.length === 0) return;\n const first = folded.ids[0];\n let last = folded.ids[folded.ids.length - 1];\n if (wraps(run, n)) {\n last += 1;\n folded.ids.push(last);\n folded.lens.push(c[c.length - 1]);\n }\n runAnchor[r * 2] = first;\n runAnchor[r * 2 + 1] = last;\n segments += last - first;\n ids.push(...folded.ids);\n lens.push(...folded.lens);\n });\n return { bpAnchor: Float64Array.from(ids), bpLength: Float64Array.from(lens), runAnchor, segments };\n}\n\nfunction expandedBreaks(run: LengthRun, n: number, c: Float64Array, next: number): { ids: number[]; lens: number[] } {\n const ids: number[] = [];\n const lens: number[] = [];\n const { anchorA: A, anchorB: B } = run;\n if (!A || !B) {\n for (let i = 0; i < n; i++) { ids.push(next + i); lens.push(c[i]); }\n return { ids, lens };\n }\n for (let i = 0; i < n; i++) {\n if (A[i] === B[i]) { ids.push(A[i]); lens.push(c[i]); }\n }\n // A last anchor dropped as a duplicate of the first point ends the closing edge's drawn part.\n const dropped = closingAnchorOf(run, n);\n if (dropped !== undefined) { ids.push(dropped); lens.push(c[n]); }\n return { ids, lens };\n}\n\n/**\n * The anchor a closed run's closing edge ends at when that anchor was dropped\n * as a duplicate of the first point: `closeAnchor`, else the anchor the last\n * point is heading toward. `undefined` when none was dropped, so the edge\n * ends at the run's first anchor. `dim` is the run's components per point.\n */\nexport function closingAnchor(run: LengthRun, dim: 2 | 3 = 2): number | undefined {\n return closingAnchorOf(run, Math.floor(run.points.length / dim));\n}\n\nfunction closingAnchorOf(run: LengthRun, n: number): number | undefined {\n const { anchorA: A, anchorB: B } = run;\n if (!wraps(run, n)) return undefined;\n if (run.closeAnchor !== undefined) return run.closeAnchor;\n return A && B && A[n - 1] !== B[n - 1] ? B[n - 1] : undefined;\n}\n\nfunction foldToAuthored(\n raw: { ids: number[]; lens: number[] }, sources: Uint32Array | null, closed: boolean,\n): { ids: number[]; lens: number[] } {\n const ids: number[] = [];\n const lens: number[] = [];\n let lo = 0;\n let hi = 0;\n const flush = () => { if (ids.length > lens.length) lens.push((lo + hi) / 2); };\n for (let i = 0; i < raw.ids.length; i++) {\n const id = sources ? (sources[raw.ids[i]] ?? raw.ids[i]) : raw.ids[i];\n const len = raw.lens[i];\n // A closed run's first anchor stays at its start; the arc rounding it is drawn last, so it joins the closing edge.\n if (closed && ids.length > 0 && id === ids[0]) continue;\n if (ids.length > 0 && id === ids[ids.length - 1]) { hi = len; continue; }\n flush();\n ids.push(id);\n lo = len;\n hi = len;\n }\n flush();\n return { ids, lens };\n}\n","import { lookupT } from '../paths/segmentLength';\nimport { bezierDirection, bezierPoint } from './bezier';\nimport { segmentArc, tableInternals, type LengthTable } from './lengthTable';\n\ntype Comps = [number, number, number];\n\n/**\n * The point at pen-order length `s`, and the unit tangent of the segment\n * arriving there (leaving, at a run's start); on a curve, the exact point and\n * the curve's own direction. Components past the table's\n * `dim` read 0. Clamps to the path; where two runs meet, answers the end of the\n * earlier one. A path with no length answers a zero tangent.\n */\nexport function pointAtLength(t: LengthTable, s: number): { point: Comps; tangent: Comps } {\n const { cum } = tableInternals(t);\n const len = Number.isNaN(s) ? 0 : Math.min(Math.max(s, 0), t.total);\n let r = cum.findIndex((c, i) => c.length >= 2 && len <= t.runStart[i + 1]);\n if (r < 0) {\n r = t.runs.length - 1;\n while (r >= 0 && t.runs[r].points.length < t.dim) r--;\n if (r < 0) return { point: [0, 0, 0], tangent: [0, 0, 0] };\n return { point: at(t, r, 0), tangent: [0, 0, 0] };\n }\n const c = cum[r];\n let lo = 0;\n let hi = c.length - 2;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (c[mid + 1] < len) lo = mid + 1;\n else hi = mid;\n }\n return pointOnSegment(t, r, lo, len);\n}\n\n/**\n * @internal {@link pointAtLength} on a segment already found: the point at\n * pen-order length `len` on segment `i` of run `r`, `len` clamped to it.\n */\nexport function pointOnSegment(t: LengthTable, r: number, i: number, len: number): { point: Comps; tangent: Comps } {\n const c = tableInternals(t).cum[r];\n const span = c[i + 1] - c[i];\n const local = Math.min(Math.max(len - c[i], 0), span);\n const arc = segmentArc(t, r, i);\n if (arc) {\n const u = lookupT(arc.coords, t.dim, arc.lookup, local);\n return { point: bezierPoint(arc.coords, t.dim, u), tangent: bezierDirection(arc.coords, t.dim, u) ?? tangentNear(t, r, i) };\n }\n const f = span > 0 ? local / span : 0;\n const a = at(t, r, i);\n const b = at(t, r, i + 1);\n return { point: [lerp(a[0], b[0], f), lerp(a[1], b[1], f), lerp(a[2], b[2], f)], tangent: tangentNear(t, r, i) };\n}\n\n/** Point `i` of run `r`, wrapping a closed run's closing edge back to its first. */\nfunction at(t: LengthTable, r: number, i: number): Comps {\n const { points } = t.runs[r];\n const n = Math.floor(points.length / t.dim);\n const o = (i % n) * t.dim;\n return [points[o], points[o + 1], t.dim === 3 ? points[o + 2] : 0];\n}\n\n/** The direction of segment `i`, or of the nearest one with length, looking back first. */\nfunction tangentNear(t: LengthTable, r: number, i: number): Comps {\n const last = tableInternals(t).cum[r].length - 2;\n for (let k = i; k >= 0; k--) { const d = direction(t, r, k); if (d) return d; }\n for (let k = i + 1; k <= last; k++) { const d = direction(t, r, k); if (d) return d; }\n return [0, 0, 0];\n}\n\nfunction direction(t: LengthTable, r: number, i: number): Comps | null {\n const a = at(t, r, i);\n const b = at(t, r, i + 1);\n const d: Comps = [b[0] - a[0], b[1] - a[1], b[2] - a[2]];\n const l = Math.hypot(d[0], d[1], d[2]);\n return l > 0 ? [d[0] / l, d[1] / l, d[2] / l] : null;\n}\n\nconst lerp = (a: number, b: number, f: number): number => a + (b - a) * f;\n"]}
|