@weasel-js/geom 1.7.0 → 1.7.2
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 +11 -1
- package/dist/3d/index.d.ts +17 -0
- package/dist/3d/index.js +3 -2
- package/dist/3d/index.js.map +1 -1
- package/dist/booleans/index.d.ts +90 -44
- package/dist/booleans/index.js +645 -5
- package/dist/booleans/index.js.map +1 -1
- package/dist/chunk-6T5I3PR5.js +172 -0
- package/dist/chunk-6T5I3PR5.js.map +1 -0
- package/dist/chunk-7ROQRYOA.js +29 -0
- package/dist/chunk-7ROQRYOA.js.map +1 -0
- package/dist/chunk-HEZTRG2M.js +55 -0
- package/dist/chunk-HEZTRG2M.js.map +1 -0
- package/dist/chunk-HPVINMOM.js +34 -0
- package/dist/chunk-HPVINMOM.js.map +1 -0
- package/dist/{chunk-36DHVSOV.js → chunk-RQYCDPU5.js} +36 -134
- package/dist/chunk-RQYCDPU5.js.map +1 -0
- package/dist/{chunk-3GFNUO4N.js → chunk-TXEGHCJ4.js} +3 -29
- package/dist/chunk-TXEGHCJ4.js.map +1 -0
- package/dist/chunk-URQMDR6Q.js +80 -0
- package/dist/chunk-URQMDR6Q.js.map +1 -0
- package/dist/cubicMath-CpCvuEl8.d.ts +37 -0
- package/dist/curves/index.d.ts +84 -0
- package/dist/curves/index.js +513 -0
- package/dist/curves/index.js.map +1 -0
- package/dist/index.d.ts +539 -2
- package/dist/index.js +1550 -60
- package/dist/index.js.map +1 -1
- package/dist/path-D0CoudGM.d.ts +45 -0
- package/dist/tessellate/index.d.ts +87 -0
- package/dist/tessellate/index.js +316 -0
- package/dist/tessellate/index.js.map +1 -0
- package/package.json +15 -2
- package/dist/chunk-36DHVSOV.js.map +0 -1
- package/dist/chunk-3GFNUO4N.js.map +0 -1
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { P as Path } from '../path-D0CoudGM.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A tessellated representation of a Path, ready to upload to GL.
|
|
5
|
+
*
|
|
6
|
+
* - `vertices` is interleaved x,y in path-local coordinates (`Float32Array`
|
|
7
|
+
* of length `2 * vertexCount`).
|
|
8
|
+
* - `indices` are triangle indices into `vertices` (`Uint32Array`, length
|
|
9
|
+
* `3 * triangleCount`).
|
|
10
|
+
* - `requiresStencil` is set for paths whose fillRule is `'evenodd'` and
|
|
11
|
+
* whose triangulation is a *naive* per-contour fan rather than a clean
|
|
12
|
+
* inside/outside triangulation. The renderer must use a stencil
|
|
13
|
+
* two-pass when this flag is true. Single-contour paths and `'nonzero'`
|
|
14
|
+
* multi-contour paths leave it false.
|
|
15
|
+
* - `anchorA` / `anchorB` / `anchorT` parameterize each mesh vertex by
|
|
16
|
+
* the two consecutive path anchors it lies between and the arc-length
|
|
17
|
+
* fraction along that segment (0 = at A, 1 = at B). Vertices that fall
|
|
18
|
+
* exactly on an anchor set A === B and t = 0. Used at draw time when
|
|
19
|
+
* the DrawCommand supplies per-anchor colors so the renderer can lerp
|
|
20
|
+
* per mesh vertex. Optional — emitted by the path tessellators; absent
|
|
21
|
+
* on meshes built by other paths (e.g. text glyphs).
|
|
22
|
+
*/
|
|
23
|
+
interface Mesh {
|
|
24
|
+
readonly vertices: Float32Array;
|
|
25
|
+
readonly indices: Uint32Array;
|
|
26
|
+
readonly requiresStencil?: boolean;
|
|
27
|
+
readonly anchorA?: Uint32Array;
|
|
28
|
+
readonly anchorB?: Uint32Array;
|
|
29
|
+
readonly anchorT?: Float32Array;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Options for `tessellate`. A smaller tolerance means more triangles and
|
|
33
|
+
* smoother curves; it is in path-local units, so callers rendering at a
|
|
34
|
+
* larger scale should tighten it. */
|
|
35
|
+
interface TessellateOptions {
|
|
36
|
+
/** Flatness tolerance for bezier subdivision in path-local units. */
|
|
37
|
+
flattenTolerance?: number;
|
|
38
|
+
}
|
|
39
|
+
/** Turn a path into a triangle mesh the renderer can draw: curves flattened to
|
|
40
|
+
* line segments, then the resulting polygon triangulated. */
|
|
41
|
+
declare function tessellate(path: Path, opts?: TessellateOptions): Mesh;
|
|
42
|
+
|
|
43
|
+
/** One contour of a path, flattened to straight segments. */
|
|
44
|
+
interface Polyline {
|
|
45
|
+
/** Interleaved x,y vertices (length = 2 × point count). */
|
|
46
|
+
points: number[];
|
|
47
|
+
/** Whether the contour was closed (ends with Z, or is a RectPath). */
|
|
48
|
+
closed: boolean;
|
|
49
|
+
/** For each point, the previous anchor index. Anchor-aligned points set A === B. */
|
|
50
|
+
anchorA?: Uint32Array;
|
|
51
|
+
/** For each point, the next anchor index. */
|
|
52
|
+
anchorB?: Uint32Array;
|
|
53
|
+
/** For each point, the arc-length fraction along (A, B). 0 at anchor A; for anchor-aligned, set to 0. */
|
|
54
|
+
anchorT?: Float32Array;
|
|
55
|
+
/** Per-point stroke width, populated by the tessellator when the Stroke
|
|
56
|
+
* carries `vertexWidths`. Undefined means uniform `Stroke.width`. */
|
|
57
|
+
widths?: Float32Array;
|
|
58
|
+
}
|
|
59
|
+
/** Options for `extractPolylines`. */
|
|
60
|
+
interface ExtractOptions {
|
|
61
|
+
flattenTolerance?: number;
|
|
62
|
+
}
|
|
63
|
+
/** Flatten each contour of a path to a straight-segment polyline, carrying the
|
|
64
|
+
* anchor parameterization per point. A rect yields one closed contour. */
|
|
65
|
+
declare function extractPolylines(path: Path, opts?: ExtractOptions): Polyline[];
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Shortening a flattened subpath so a filled marker is not speared by its own
|
|
69
|
+
* line. SVG has no equivalent — it paints the marker over a full-length
|
|
70
|
+
* stroke — so this is the one place our rendering deliberately differs.
|
|
71
|
+
*
|
|
72
|
+
* Runs before dash splitting, so a dash pattern fits the visible line rather
|
|
73
|
+
* than running off under the head. The anchor-param interpolation matches
|
|
74
|
+
* `splitForDash`'s rule for a boundary landing mid-segment.
|
|
75
|
+
*/
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Shorten `pl` by `startInset` from its first point and `endInset` from its
|
|
79
|
+
* last, both in the same world units as the points.
|
|
80
|
+
*
|
|
81
|
+
* Returns `pl` itself when there is nothing to do (both insets zero, or the
|
|
82
|
+
* subpath is closed and so has no free ends), and `null` when the insets
|
|
83
|
+
* consume the whole run — a caller should then draw no ribbon at all.
|
|
84
|
+
*/
|
|
85
|
+
declare function trimPolyline(pl: Polyline, startInset: number, endInset: number): Polyline | null;
|
|
86
|
+
|
|
87
|
+
export { type ExtractOptions, type Mesh, type Polyline, type TessellateOptions, extractPolylines, tessellate, trimPolyline };
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { rectToContour } from '../chunk-6T5I3PR5.js';
|
|
2
|
+
export { extractPolylines } from '../chunk-6T5I3PR5.js';
|
|
3
|
+
import { DEFAULT_FLATTEN_TOLERANCE, pointInPolygon, flattenCubicWithArcLen, flattenQuadraticWithArcLen } from '../chunk-RQYCDPU5.js';
|
|
4
|
+
import '../chunk-7ROQRYOA.js';
|
|
5
|
+
import { forEachSegment, PATH_Z, PATH_C, PATH_Q, PATH_L, PATH_M } from '../chunk-HEZTRG2M.js';
|
|
6
|
+
import earcut from 'earcut';
|
|
7
|
+
|
|
8
|
+
function tessellate(path, opts = {}) {
|
|
9
|
+
if (path.kind === "rect") return tessellateRect(path);
|
|
10
|
+
return tessellatePolygon(path, opts);
|
|
11
|
+
}
|
|
12
|
+
function tessellateRect(p) {
|
|
13
|
+
const { x, y, width: w, height: h } = p;
|
|
14
|
+
return {
|
|
15
|
+
vertices: Float32Array.from(rectToContour(x, y, w, h)),
|
|
16
|
+
indices: new Uint32Array([0, 1, 2, 0, 2, 3]),
|
|
17
|
+
anchorA: new Uint32Array([0, 1, 2, 3]),
|
|
18
|
+
anchorB: new Uint32Array([0, 1, 2, 3]),
|
|
19
|
+
anchorT: new Float32Array([0, 0, 0, 0])
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function flattenPolygon(p, tolerance) {
|
|
23
|
+
const { commands, coords } = p;
|
|
24
|
+
const out = [];
|
|
25
|
+
const anchorA = [];
|
|
26
|
+
const anchorB = [];
|
|
27
|
+
const anchorT = [];
|
|
28
|
+
const contourStarts = [];
|
|
29
|
+
let startAnchor = -1;
|
|
30
|
+
let prevAnchor = -1;
|
|
31
|
+
let anchorCounter = 0;
|
|
32
|
+
const pushCurveAnchors = (anchorStart, arcAccum, total, target) => {
|
|
33
|
+
for (let k = 0; k < arcAccum.length; k++) {
|
|
34
|
+
anchorA.push(prevAnchor);
|
|
35
|
+
anchorB.push(target);
|
|
36
|
+
anchorT.push(total > 0 ? arcAccum[k] / total : 0);
|
|
37
|
+
}
|
|
38
|
+
const lastIdx = anchorStart + arcAccum.length - 1;
|
|
39
|
+
anchorA[lastIdx] = target;
|
|
40
|
+
anchorB[lastIdx] = target;
|
|
41
|
+
anchorT[lastIdx] = 0;
|
|
42
|
+
};
|
|
43
|
+
forEachSegment(commands, coords, (cmd, coordIdx, prevX, prevY) => {
|
|
44
|
+
switch (cmd) {
|
|
45
|
+
case PATH_M:
|
|
46
|
+
case PATH_L: {
|
|
47
|
+
if (cmd === PATH_M) {
|
|
48
|
+
contourStarts.push(out.length / 2);
|
|
49
|
+
startAnchor = anchorCounter;
|
|
50
|
+
}
|
|
51
|
+
out.push(coords[coordIdx], coords[coordIdx + 1]);
|
|
52
|
+
anchorA.push(anchorCounter);
|
|
53
|
+
anchorB.push(anchorCounter);
|
|
54
|
+
anchorT.push(0);
|
|
55
|
+
prevAnchor = anchorCounter;
|
|
56
|
+
anchorCounter++;
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
case PATH_Q: {
|
|
60
|
+
const target = anchorCounter;
|
|
61
|
+
const arcAccum = [];
|
|
62
|
+
const anchorStart = anchorA.length;
|
|
63
|
+
const total = flattenQuadraticWithArcLen(
|
|
64
|
+
prevX,
|
|
65
|
+
prevY,
|
|
66
|
+
coords[coordIdx],
|
|
67
|
+
coords[coordIdx + 1],
|
|
68
|
+
coords[coordIdx + 2],
|
|
69
|
+
coords[coordIdx + 3],
|
|
70
|
+
tolerance,
|
|
71
|
+
out,
|
|
72
|
+
arcAccum
|
|
73
|
+
);
|
|
74
|
+
pushCurveAnchors(anchorStart, arcAccum, total, target);
|
|
75
|
+
prevAnchor = target;
|
|
76
|
+
anchorCounter++;
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
case PATH_C: {
|
|
80
|
+
const target = anchorCounter;
|
|
81
|
+
const arcAccum = [];
|
|
82
|
+
const anchorStart = anchorA.length;
|
|
83
|
+
const total = flattenCubicWithArcLen(
|
|
84
|
+
prevX,
|
|
85
|
+
prevY,
|
|
86
|
+
coords[coordIdx],
|
|
87
|
+
coords[coordIdx + 1],
|
|
88
|
+
coords[coordIdx + 2],
|
|
89
|
+
coords[coordIdx + 3],
|
|
90
|
+
coords[coordIdx + 4],
|
|
91
|
+
coords[coordIdx + 5],
|
|
92
|
+
tolerance,
|
|
93
|
+
out,
|
|
94
|
+
arcAccum
|
|
95
|
+
);
|
|
96
|
+
pushCurveAnchors(anchorStart, arcAccum, total, target);
|
|
97
|
+
prevAnchor = target;
|
|
98
|
+
anchorCounter++;
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
case PATH_Z:
|
|
102
|
+
prevAnchor = startAnchor;
|
|
103
|
+
break;
|
|
104
|
+
default:
|
|
105
|
+
throw new Error(`tessellate: unknown command code ${cmd}`);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
return { coords: out, contourStarts, anchorA, anchorB, anchorT };
|
|
109
|
+
}
|
|
110
|
+
function tessellatePolygon(p, opts) {
|
|
111
|
+
const tolerance = opts.flattenTolerance ?? DEFAULT_FLATTEN_TOLERANCE;
|
|
112
|
+
const { coords, contourStarts, anchorA, anchorB, anchorT } = flattenPolygon(p, tolerance);
|
|
113
|
+
if (p.fillRule === "evenodd") {
|
|
114
|
+
return tessellateEvenoddWithAnchors(coords, contourStarts, anchorA, anchorB, anchorT);
|
|
115
|
+
}
|
|
116
|
+
const totalVerts = coords.length / 2;
|
|
117
|
+
const contourEnd = (i) => i + 1 < contourStarts.length ? contourStarts[i + 1] : totalVerts;
|
|
118
|
+
if (contourStarts.length <= 1) {
|
|
119
|
+
const tri = earcut(coords);
|
|
120
|
+
return {
|
|
121
|
+
vertices: new Float32Array(coords),
|
|
122
|
+
indices: new Uint32Array(tri),
|
|
123
|
+
anchorA: new Uint32Array(anchorA),
|
|
124
|
+
anchorB: new Uint32Array(anchorB),
|
|
125
|
+
anchorT: new Float32Array(anchorT)
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const areas = contourStarts.map((s, i) => signedArea(coords, s, contourEnd(i)));
|
|
129
|
+
const refSign = Math.sign(areas[0]) || 1;
|
|
130
|
+
const positives = [];
|
|
131
|
+
const negatives = [];
|
|
132
|
+
for (let i = 0; i < contourStarts.length; i++) {
|
|
133
|
+
if (areas[i] === 0) continue;
|
|
134
|
+
if (Math.sign(areas[i]) === refSign) positives.push(i);
|
|
135
|
+
else negatives.push(i);
|
|
136
|
+
}
|
|
137
|
+
if (positives.length === 1 && negatives.length > 0) {
|
|
138
|
+
const holeIndices = contourStarts.slice(1);
|
|
139
|
+
const tri = earcut(coords, holeIndices);
|
|
140
|
+
return {
|
|
141
|
+
vertices: new Float32Array(coords),
|
|
142
|
+
indices: new Uint32Array(tri),
|
|
143
|
+
anchorA: new Uint32Array(anchorA),
|
|
144
|
+
anchorB: new Uint32Array(anchorB),
|
|
145
|
+
anchorT: new Float32Array(anchorT)
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const holesByPositive = /* @__PURE__ */ new Map();
|
|
149
|
+
const orphanPositives = [];
|
|
150
|
+
for (const n of negatives) {
|
|
151
|
+
const px = coords[contourStarts[n] * 2];
|
|
152
|
+
const py = coords[contourStarts[n] * 2 + 1];
|
|
153
|
+
let bestPos = -1;
|
|
154
|
+
let bestAbsArea = Infinity;
|
|
155
|
+
for (const pos of positives) {
|
|
156
|
+
const absArea = Math.abs(areas[pos]);
|
|
157
|
+
if (absArea < bestAbsArea && pointInPolygon(coords, px, py, contourStarts[pos], contourEnd(pos))) {
|
|
158
|
+
bestAbsArea = absArea;
|
|
159
|
+
bestPos = pos;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (bestPos >= 0) {
|
|
163
|
+
const arr = holesByPositive.get(bestPos) ?? [];
|
|
164
|
+
arr.push(n);
|
|
165
|
+
holesByPositive.set(bestPos, arr);
|
|
166
|
+
} else {
|
|
167
|
+
orphanPositives.push(n);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const allPositives = [...positives, ...orphanPositives];
|
|
171
|
+
const finalCoords = [];
|
|
172
|
+
const finalAnchorA = [];
|
|
173
|
+
const finalAnchorB = [];
|
|
174
|
+
const finalAnchorT = [];
|
|
175
|
+
const finalIndices = [];
|
|
176
|
+
for (const pos of allPositives) {
|
|
177
|
+
const holes = holesByPositive.get(pos) ?? [];
|
|
178
|
+
const offset = finalCoords.length / 2;
|
|
179
|
+
const groupCoords = [];
|
|
180
|
+
const groupStarts = [0];
|
|
181
|
+
for (let i = contourStarts[pos]; i < contourEnd(pos); i++) {
|
|
182
|
+
groupCoords.push(coords[i * 2], coords[i * 2 + 1]);
|
|
183
|
+
finalAnchorA.push(anchorA[i]);
|
|
184
|
+
finalAnchorB.push(anchorB[i]);
|
|
185
|
+
finalAnchorT.push(anchorT[i]);
|
|
186
|
+
}
|
|
187
|
+
for (const h of holes) {
|
|
188
|
+
groupStarts.push(groupCoords.length / 2);
|
|
189
|
+
for (let i = contourStarts[h]; i < contourEnd(h); i++) {
|
|
190
|
+
groupCoords.push(coords[i * 2], coords[i * 2 + 1]);
|
|
191
|
+
finalAnchorA.push(anchorA[i]);
|
|
192
|
+
finalAnchorB.push(anchorB[i]);
|
|
193
|
+
finalAnchorT.push(anchorT[i]);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const tri = earcut(groupCoords, groupStarts.length > 1 ? groupStarts.slice(1) : void 0);
|
|
197
|
+
for (const v of groupCoords) finalCoords.push(v);
|
|
198
|
+
for (const idx of tri) finalIndices.push(idx + offset);
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
vertices: new Float32Array(finalCoords),
|
|
202
|
+
indices: new Uint32Array(finalIndices),
|
|
203
|
+
anchorA: new Uint32Array(finalAnchorA),
|
|
204
|
+
anchorB: new Uint32Array(finalAnchorB),
|
|
205
|
+
anchorT: new Float32Array(finalAnchorT)
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function tessellateEvenoddWithAnchors(coords, contourStarts, anchorA, anchorB, anchorT) {
|
|
209
|
+
const indices = [];
|
|
210
|
+
const totalVerts = coords.length / 2;
|
|
211
|
+
for (let c = 0; c < contourStarts.length; c++) {
|
|
212
|
+
const start = contourStarts[c];
|
|
213
|
+
const end = c + 1 < contourStarts.length ? contourStarts[c + 1] : totalVerts;
|
|
214
|
+
for (let i = start + 1; i < end - 1; i++) {
|
|
215
|
+
indices.push(start, i, i + 1);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
vertices: new Float32Array(coords),
|
|
220
|
+
indices: new Uint32Array(indices),
|
|
221
|
+
requiresStencil: true,
|
|
222
|
+
anchorA: new Uint32Array(anchorA),
|
|
223
|
+
anchorB: new Uint32Array(anchorB),
|
|
224
|
+
anchorT: new Float32Array(anchorT)
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
function signedArea(coords, start, end) {
|
|
228
|
+
let a = 0;
|
|
229
|
+
for (let i = start; i < end; i++) {
|
|
230
|
+
const j = i + 1 === end ? start : i + 1;
|
|
231
|
+
a += coords[i * 2] * coords[j * 2 + 1] - coords[j * 2] * coords[i * 2 + 1];
|
|
232
|
+
}
|
|
233
|
+
return a * 0.5;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// src/tessellate/trim.ts
|
|
237
|
+
var EPS = 1e-9;
|
|
238
|
+
function sampleAt(pl, cum, A, B, T, W, dist) {
|
|
239
|
+
const n = cum.length;
|
|
240
|
+
let i = 1;
|
|
241
|
+
while (i < n - 1 && cum[i] < dist) i++;
|
|
242
|
+
const segStart = cum[i - 1];
|
|
243
|
+
const segLen = cum[i] - segStart;
|
|
244
|
+
const f = segLen > EPS ? (dist - segStart) / segLen : 0;
|
|
245
|
+
const px = pl.points[(i - 1) * 2], py = pl.points[(i - 1) * 2 + 1];
|
|
246
|
+
const qx = pl.points[i * 2], qy = pl.points[i * 2 + 1];
|
|
247
|
+
let a, b, t;
|
|
248
|
+
if (A[i - 1] === A[i] && B[i - 1] === B[i]) {
|
|
249
|
+
a = A[i - 1];
|
|
250
|
+
b = B[i - 1];
|
|
251
|
+
t = T[i - 1] + (T[i] - T[i - 1]) * f;
|
|
252
|
+
} else if (f < 0.5) {
|
|
253
|
+
a = A[i - 1];
|
|
254
|
+
b = B[i - 1];
|
|
255
|
+
t = T[i - 1];
|
|
256
|
+
} else {
|
|
257
|
+
a = A[i];
|
|
258
|
+
b = B[i];
|
|
259
|
+
t = T[i];
|
|
260
|
+
}
|
|
261
|
+
const w = W ? W[i - 1] + (W[i] - W[i - 1]) * f : 0;
|
|
262
|
+
return { x: px + (qx - px) * f, y: py + (qy - py) * f, a, b, t, w, next: i };
|
|
263
|
+
}
|
|
264
|
+
function trimPolyline(pl, startInset, endInset) {
|
|
265
|
+
const from = Math.max(0, startInset);
|
|
266
|
+
const to = Math.max(0, endInset);
|
|
267
|
+
if (from <= 0 && to <= 0) return pl;
|
|
268
|
+
if (pl.closed) return pl;
|
|
269
|
+
const n = pl.points.length / 2;
|
|
270
|
+
if (n < 2) return null;
|
|
271
|
+
const A = pl.anchorA ?? new Uint32Array(n);
|
|
272
|
+
const B = pl.anchorB ?? new Uint32Array(n);
|
|
273
|
+
const T = pl.anchorT ?? new Float32Array(n);
|
|
274
|
+
const W = pl.widths;
|
|
275
|
+
const cum = new Float64Array(n);
|
|
276
|
+
for (let i = 1; i < n; i++) {
|
|
277
|
+
const dx = pl.points[i * 2] - pl.points[(i - 1) * 2];
|
|
278
|
+
const dy = pl.points[i * 2 + 1] - pl.points[(i - 1) * 2 + 1];
|
|
279
|
+
cum[i] = cum[i - 1] + Math.hypot(dx, dy);
|
|
280
|
+
}
|
|
281
|
+
const total = cum[n - 1];
|
|
282
|
+
const cutA = from;
|
|
283
|
+
const cutB = total - to;
|
|
284
|
+
if (cutB - cutA <= EPS) return null;
|
|
285
|
+
const head = sampleAt(pl, cum, A, B, T, W, cutA);
|
|
286
|
+
const tail = sampleAt(pl, cum, A, B, T, W, cutB);
|
|
287
|
+
const points = [head.x, head.y];
|
|
288
|
+
const aOut = [head.a];
|
|
289
|
+
const bOut = [head.b];
|
|
290
|
+
const tOut = [head.t];
|
|
291
|
+
const wOut = W ? [head.w] : void 0;
|
|
292
|
+
for (let i = head.next; i < tail.next; i++) {
|
|
293
|
+
points.push(pl.points[i * 2], pl.points[i * 2 + 1]);
|
|
294
|
+
aOut.push(A[i]);
|
|
295
|
+
bOut.push(B[i]);
|
|
296
|
+
tOut.push(T[i]);
|
|
297
|
+
if (wOut) wOut.push(W[i]);
|
|
298
|
+
}
|
|
299
|
+
points.push(tail.x, tail.y);
|
|
300
|
+
aOut.push(tail.a);
|
|
301
|
+
bOut.push(tail.b);
|
|
302
|
+
tOut.push(tail.t);
|
|
303
|
+
if (wOut) wOut.push(tail.w);
|
|
304
|
+
return {
|
|
305
|
+
points,
|
|
306
|
+
closed: false,
|
|
307
|
+
anchorA: new Uint32Array(aOut),
|
|
308
|
+
anchorB: new Uint32Array(bOut),
|
|
309
|
+
anchorT: new Float32Array(tOut),
|
|
310
|
+
...wOut ? { widths: new Float32Array(wOut) } : {}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export { tessellate, trimPolyline };
|
|
315
|
+
//# sourceMappingURL=index.js.map
|
|
316
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/tessellate/tessellate.ts","../../src/tessellate/trim.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import earcut from 'earcut';\nimport { forEachSegment, PATH_M, PATH_L, PATH_Z, PATH_C, PATH_Q } from '../commands';\nimport { pointInPolygon } from '../polyline';\nimport { rectToContour } from '../box';\nimport type { Path, PolygonPath, RectPath } from '../path';\nimport {\n DEFAULT_FLATTEN_TOLERANCE,\n flattenCubicWithArcLen,\n flattenQuadraticWithArcLen,\n} from '../flatten';\nimport type { Mesh } from './mesh';\n\n/** Options for `tessellate`. A smaller tolerance means more triangles and\n * smoother curves; it is in path-local units, so callers rendering at a\n * larger scale should tighten it. */\nexport interface TessellateOptions {\n /** Flatness tolerance for bezier subdivision in path-local units. */\n flattenTolerance?: number;\n}\n\n/** Turn a path into a triangle mesh the renderer can draw: curves flattened to\n * line segments, then the resulting polygon triangulated. */\nexport function tessellate(path: Path, opts: TessellateOptions = {}): Mesh {\n if (path.kind === 'rect') return tessellateRect(path);\n return tessellatePolygon(path, opts);\n}\n\nfunction tessellateRect(p: RectPath): Mesh {\n const { x, y, width: w, height: h } = p;\n return {\n vertices: Float32Array.from(rectToContour(x, y, w, h)),\n indices: new Uint32Array([0, 1, 2, 0, 2, 3]),\n anchorA: new Uint32Array([0, 1, 2, 3]),\n anchorB: new Uint32Array([0, 1, 2, 3]),\n anchorT: new Float32Array([0, 0, 0, 0]),\n };\n}\n\ninterface FlattenedContours {\n coords: number[];\n contourStarts: number[];\n anchorA: number[];\n anchorB: number[];\n anchorT: number[];\n}\n\nfunction flattenPolygon(p: PolygonPath, tolerance: number): FlattenedContours {\n const { commands, coords } = p;\n const out: number[] = [];\n const anchorA: number[] = [];\n const anchorB: number[] = [];\n const anchorT: number[] = [];\n const contourStarts: number[] = [];\n let startAnchor = -1;\n let prevAnchor = -1;\n let anchorCounter = 0;\n\n // Anchor bookkeeping for the points a curve just appended: interior points\n // interpolate (prevAnchor → target); the last is pinned anchor-exact.\n const pushCurveAnchors = (anchorStart: number, arcAccum: number[], total: number, target: number): void => {\n for (let k = 0; k < arcAccum.length; k++) {\n anchorA.push(prevAnchor);\n anchorB.push(target);\n anchorT.push(total > 0 ? arcAccum[k] / total : 0);\n }\n const lastIdx = anchorStart + arcAccum.length - 1;\n anchorA[lastIdx] = target;\n anchorB[lastIdx] = target;\n anchorT[lastIdx] = 0;\n };\n\n forEachSegment(commands, coords, (cmd, coordIdx, prevX, prevY) => {\n switch (cmd) {\n case PATH_M:\n case PATH_L: {\n if (cmd === PATH_M) {\n contourStarts.push(out.length / 2);\n startAnchor = anchorCounter;\n }\n out.push(coords[coordIdx], coords[coordIdx + 1]);\n anchorA.push(anchorCounter);\n anchorB.push(anchorCounter);\n anchorT.push(0);\n prevAnchor = anchorCounter;\n anchorCounter++;\n break;\n }\n case PATH_Q: {\n const target = anchorCounter;\n const arcAccum: number[] = [];\n const anchorStart = anchorA.length;\n const total = flattenQuadraticWithArcLen(\n prevX, prevY,\n coords[coordIdx], coords[coordIdx + 1],\n coords[coordIdx + 2], coords[coordIdx + 3],\n tolerance, out, arcAccum,\n );\n pushCurveAnchors(anchorStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_C: {\n const target = anchorCounter;\n const arcAccum: number[] = [];\n const anchorStart = anchorA.length;\n const total = flattenCubicWithArcLen(\n prevX, prevY,\n coords[coordIdx], coords[coordIdx + 1],\n coords[coordIdx + 2], coords[coordIdx + 3],\n coords[coordIdx + 4], coords[coordIdx + 5],\n tolerance, out, arcAccum,\n );\n pushCurveAnchors(anchorStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_Z:\n // The pen returns to the subpath start (forEachSegment does that); the\n // anchor it carries has to follow, or a curve after the Z interpolates\n // from the wrong end.\n prevAnchor = startAnchor;\n break;\n default:\n throw new Error(`tessellate: unknown command code ${cmd}`);\n }\n });\n\n return { coords: out, contourStarts, anchorA, anchorB, anchorT };\n}\n\nfunction tessellatePolygon(p: PolygonPath, opts: TessellateOptions): Mesh {\n const tolerance = opts.flattenTolerance ?? DEFAULT_FLATTEN_TOLERANCE;\n const { coords, contourStarts, anchorA, anchorB, anchorT } = flattenPolygon(p, tolerance);\n\n if (p.fillRule === 'evenodd') {\n return tessellateEvenoddWithAnchors(coords, contourStarts, anchorA, anchorB, anchorT);\n }\n\n // nonzero compound-path tessellation:\n // - The first contour establishes the reference winding direction.\n // - Subsequent contours with the SAME winding as the first are positives\n // (filled, disjoint shapes).\n // - Subsequent contours with OPPOSITE winding are holes; each is grouped\n // with the smallest positive whose polygon contains its first vertex.\n // - Each (positive, [its holes]) group is earcut'd independently;\n // triangles concatenated.\n // Authors mostly write disjoint-positives-with-same-winding; the previous\n // implementation passed every subsequent contour as a hole, which broke\n // those (a duck with body+head+beak, a hamburglar with brim+crown+cape).\n // Using shoelace sign relative to the first contour avoids guessing about\n // screen-down vs math-up axis conventions.\n\n const totalVerts = coords.length / 2;\n const contourEnd = (i: number): number =>\n i + 1 < contourStarts.length ? contourStarts[i + 1] : totalVerts;\n\n if (contourStarts.length <= 1) {\n const tri = earcut(coords);\n return {\n vertices: new Float32Array(coords),\n indices: new Uint32Array(tri),\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n }\n\n const areas: number[] = contourStarts.map((s, i) => signedArea(coords, s, contourEnd(i)));\n const refSign = Math.sign(areas[0]) || 1;\n\n const positives: number[] = [];\n const negatives: number[] = [];\n for (let i = 0; i < contourStarts.length; i++) {\n if (areas[i] === 0) continue;\n if (Math.sign(areas[i]) === refSign) positives.push(i);\n else negatives.push(i);\n }\n\n if (positives.length === 1 && negatives.length > 0) {\n // Classic outer-with-holes pattern; pass directly to earcut.\n const holeIndices = contourStarts.slice(1);\n const tri = earcut(coords, holeIndices);\n return {\n vertices: new Float32Array(coords),\n indices: new Uint32Array(tri),\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n }\n\n // Group each opposite-wound contour with the smallest positive that\n // contains its first vertex. Orphans (opposite-wound but not inside any\n // positive) get promoted to independent positives — author probably\n // intended them as separate shapes with inconsistent winding.\n const holesByPositive = new Map<number, number[]>();\n const orphanPositives: number[] = [];\n for (const n of negatives) {\n const px = coords[contourStarts[n] * 2];\n const py = coords[contourStarts[n] * 2 + 1];\n let bestPos = -1;\n let bestAbsArea = Infinity;\n for (const pos of positives) {\n const absArea = Math.abs(areas[pos]);\n if (absArea < bestAbsArea && pointInPolygon(coords, px, py, contourStarts[pos], contourEnd(pos))) {\n bestAbsArea = absArea;\n bestPos = pos;\n }\n }\n if (bestPos >= 0) {\n const arr = holesByPositive.get(bestPos) ?? [];\n arr.push(n);\n holesByPositive.set(bestPos, arr);\n } else {\n orphanPositives.push(n);\n }\n }\n\n const allPositives = [...positives, ...orphanPositives];\n\n const finalCoords: number[] = [];\n const finalAnchorA: number[] = [];\n const finalAnchorB: number[] = [];\n const finalAnchorT: number[] = [];\n const finalIndices: number[] = [];\n for (const pos of allPositives) {\n const holes = holesByPositive.get(pos) ?? [];\n const offset = finalCoords.length / 2;\n const groupCoords: number[] = [];\n const groupStarts: number[] = [0];\n for (let i = contourStarts[pos]; i < contourEnd(pos); i++) {\n groupCoords.push(coords[i * 2], coords[i * 2 + 1]);\n finalAnchorA.push(anchorA[i]);\n finalAnchorB.push(anchorB[i]);\n finalAnchorT.push(anchorT[i]);\n }\n for (const h of holes) {\n groupStarts.push(groupCoords.length / 2);\n for (let i = contourStarts[h]; i < contourEnd(h); i++) {\n groupCoords.push(coords[i * 2], coords[i * 2 + 1]);\n finalAnchorA.push(anchorA[i]);\n finalAnchorB.push(anchorB[i]);\n finalAnchorT.push(anchorT[i]);\n }\n }\n const tri = earcut(groupCoords, groupStarts.length > 1 ? groupStarts.slice(1) : undefined);\n for (const v of groupCoords) finalCoords.push(v);\n for (const idx of tri) finalIndices.push(idx + offset);\n }\n\n return {\n vertices: new Float32Array(finalCoords),\n indices: new Uint32Array(finalIndices),\n anchorA: new Uint32Array(finalAnchorA),\n anchorB: new Uint32Array(finalAnchorB),\n anchorT: new Float32Array(finalAnchorT),\n };\n}\n\nfunction tessellateEvenoddWithAnchors(\n coords: number[],\n contourStarts: number[],\n anchorA: number[],\n anchorB: number[],\n anchorT: number[],\n): Mesh {\n const indices: number[] = [];\n const totalVerts = coords.length / 2;\n for (let c = 0; c < contourStarts.length; c++) {\n const start = contourStarts[c];\n const end = c + 1 < contourStarts.length ? contourStarts[c + 1] : totalVerts;\n for (let i = start + 1; i < end - 1; i++) {\n indices.push(start, i, i + 1);\n }\n }\n return {\n vertices: new Float32Array(coords),\n indices: new Uint32Array(indices),\n requiresStencil: true,\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n}\n\nfunction signedArea(coords: number[], start: number, end: number): number {\n let a = 0;\n for (let i = start; i < end; i++) {\n const j = i + 1 === end ? start : i + 1;\n a += coords[i * 2] * coords[j * 2 + 1] - coords[j * 2] * coords[i * 2 + 1];\n }\n return a * 0.5;\n}\n","/**\n * Shortening a flattened subpath so a filled marker is not speared by its own\n * line. SVG has no equivalent — it paints the marker over a full-length\n * stroke — so this is the one place our rendering deliberately differs.\n *\n * Runs before dash splitting, so a dash pattern fits the visible line rather\n * than running off under the head. The anchor-param interpolation matches\n * `splitForDash`'s rule for a boundary landing mid-segment.\n */\n\nimport type { Polyline } from './polyline';\n\nconst EPS = 1e-9;\n\ninterface Sample {\n x: number; y: number;\n a: number; b: number; t: number;\n w: number;\n /** Index of the first original point at or after this sample. */\n next: number;\n}\n\nfunction sampleAt(\n pl: Polyline, cum: Float64Array,\n A: Uint32Array, B: Uint32Array, T: Float32Array, W: Float32Array | undefined,\n dist: number,\n): Sample {\n const n = cum.length;\n let i = 1;\n while (i < n - 1 && cum[i] < dist) i++;\n const segStart = cum[i - 1];\n const segLen = cum[i] - segStart;\n const f = segLen > EPS ? (dist - segStart) / segLen : 0;\n\n const px = pl.points[(i - 1) * 2], py = pl.points[(i - 1) * 2 + 1];\n const qx = pl.points[i * 2], qy = pl.points[i * 2 + 1];\n\n let a: number, b: number, t: number;\n if (A[i - 1] === A[i] && B[i - 1] === B[i]) {\n a = A[i - 1]; b = B[i - 1];\n t = T[i - 1] + (T[i] - T[i - 1]) * f;\n } else if (f < 0.5) {\n a = A[i - 1]; b = B[i - 1]; t = T[i - 1];\n } else {\n a = A[i]; b = B[i]; t = T[i];\n }\n\n const w = W ? W[i - 1] + (W[i] - W[i - 1]) * f : 0;\n return { x: px + (qx - px) * f, y: py + (qy - py) * f, a, b, t, w, next: i };\n}\n\n/**\n * Shorten `pl` by `startInset` from its first point and `endInset` from its\n * last, both in the same world units as the points.\n *\n * Returns `pl` itself when there is nothing to do (both insets zero, or the\n * subpath is closed and so has no free ends), and `null` when the insets\n * consume the whole run — a caller should then draw no ribbon at all.\n */\nexport function trimPolyline(\n pl: Polyline,\n startInset: number,\n endInset: number,\n): Polyline | null {\n const from = Math.max(0, startInset);\n const to = Math.max(0, endInset);\n if (from <= 0 && to <= 0) return pl;\n if (pl.closed) return pl;\n\n const n = pl.points.length / 2;\n if (n < 2) return null;\n\n const A = pl.anchorA ?? new Uint32Array(n);\n const B = pl.anchorB ?? new Uint32Array(n);\n const T = pl.anchorT ?? new Float32Array(n);\n const W = pl.widths;\n\n const cum = new Float64Array(n);\n for (let i = 1; i < n; i++) {\n const dx = pl.points[i * 2] - pl.points[(i - 1) * 2];\n const dy = pl.points[i * 2 + 1] - pl.points[(i - 1) * 2 + 1];\n cum[i] = cum[i - 1] + Math.hypot(dx, dy);\n }\n const total = cum[n - 1];\n const cutA = from;\n const cutB = total - to;\n if (cutB - cutA <= EPS) return null;\n\n const head = sampleAt(pl, cum, A, B, T, W, cutA);\n const tail = sampleAt(pl, cum, A, B, T, W, cutB);\n\n const points: number[] = [head.x, head.y];\n const aOut: number[] = [head.a];\n const bOut: number[] = [head.b];\n const tOut: number[] = [head.t];\n const wOut: number[] | undefined = W ? [head.w] : undefined;\n\n for (let i = head.next; i < tail.next; i++) {\n points.push(pl.points[i * 2], pl.points[i * 2 + 1]);\n aOut.push(A[i]); bOut.push(B[i]); tOut.push(T[i]);\n if (wOut) wOut.push(W![i]);\n }\n\n points.push(tail.x, tail.y);\n aOut.push(tail.a); bOut.push(tail.b); tOut.push(tail.t);\n if (wOut) wOut.push(tail.w);\n\n return {\n points,\n closed: false,\n anchorA: new Uint32Array(aOut),\n anchorB: new Uint32Array(bOut),\n anchorT: new Float32Array(tOut),\n ...(wOut ? { widths: new Float32Array(wOut) } : {}),\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weasel-js/geom",
|
|
3
|
-
"version": "1.7.
|
|
4
|
-
"description": "Pure geometry kernel for @weasel-js/core: affine, box, curve, polyline in 2D. Dependency-free core; polygon booleans in
|
|
3
|
+
"version": "1.7.2",
|
|
4
|
+
"description": "Pure geometry kernel for @weasel-js/core: affine, box, curve, polyline, the Path command stream and its math, and easing curves in 2D. Dependency-free core; curve representations in ./curves, tessellation in ./tessellate (earcut), polygon booleans and path splitting in ./booleans (polygon-clipping), vectors, quaternions, 4x4 matrices and ray intersection in ./3d.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"sideEffects": false,
|
|
@@ -21,17 +21,30 @@
|
|
|
21
21
|
"import": "./dist/3d/index.js",
|
|
22
22
|
"types": "./dist/3d/index.d.ts"
|
|
23
23
|
},
|
|
24
|
+
"./curves": {
|
|
25
|
+
"import": "./dist/curves/index.js",
|
|
26
|
+
"types": "./dist/curves/index.d.ts"
|
|
27
|
+
},
|
|
28
|
+
"./tessellate": {
|
|
29
|
+
"import": "./dist/tessellate/index.js",
|
|
30
|
+
"types": "./dist/tessellate/index.d.ts"
|
|
31
|
+
},
|
|
24
32
|
"./package.json": "./package.json"
|
|
25
33
|
},
|
|
26
34
|
"peerDependencies": {
|
|
35
|
+
"earcut": "3.2.3",
|
|
27
36
|
"polygon-clipping": "^0.15.7"
|
|
28
37
|
},
|
|
29
38
|
"peerDependenciesMeta": {
|
|
39
|
+
"earcut": {
|
|
40
|
+
"optional": true
|
|
41
|
+
},
|
|
30
42
|
"polygon-clipping": {
|
|
31
43
|
"optional": true
|
|
32
44
|
}
|
|
33
45
|
},
|
|
34
46
|
"devDependencies": {
|
|
47
|
+
"earcut": "3.2.3",
|
|
35
48
|
"polygon-clipping": "^0.15.7"
|
|
36
49
|
},
|
|
37
50
|
"scripts": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands.ts","../src/curve.ts","../src/flatten.ts"],"names":[],"mappings":"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","file":"chunk-36DHVSOV.js","sourcesContent":["/**\n * SVG-style command-stream encoding — the kit's single declaration of the path\n * opcodes. `Path` in @weasel-js/core wraps this with `kind` + `fillRule`.\n *\n * The codes index a `Uint8Array` command stream whose coords live in a\n * parallel float array, so a code declared anywhere but `PATH_COMMANDS` makes\n * every walker that doesn't know it misread the coord stream from that command\n * on — silently, for every path. Derive, never restate.\n */\n\n/** Opcode table: command code and the float coords it consumes. */\nexport const PATH_COMMANDS = {\n /** moveTo — opens a new subpath. */\n M: { code: 0, coords: 2 },\n /** Straight segment from the pen to the next coord pair. */\n L: { code: 1, coords: 2 },\n /** Cubic bezier: two control points then the endpoint. */\n C: { code: 2, coords: 6 },\n /** Quadratic bezier: one control point then the endpoint. */\n Q: { code: 3, coords: 4 },\n /** Close the current subpath back to its start. Consumes no coords and\n * leaves the pen where it is. */\n Z: { code: 4, coords: 0 },\n} as const;\n\n/** Mnemonic of a declared command (`'M' | 'L' | …`). */\nexport type PathCommandName = keyof typeof PATH_COMMANDS;\n/** Numeric code of a declared command. */\nexport type PathCommandCode = (typeof PATH_COMMANDS)[PathCommandName]['code'];\n\nexport const PATH_M = PATH_COMMANDS.M.code;\nexport const PATH_L = PATH_COMMANDS.L.code;\nexport const PATH_C = PATH_COMMANDS.C.code;\nexport const PATH_Q = PATH_COMMANDS.Q.code;\nexport const PATH_Z = PATH_COMMANDS.Z.code;\n\n/** Float coords consumed by each command, indexed by command code. */\nexport const PATH_CMD_LENGTHS: readonly number[] = buildCmdLengths();\n\nfunction buildCmdLengths(): number[] {\n const lengths: number[] = [];\n for (const { code, coords } of Object.values(PATH_COMMANDS)) lengths[code] = coords;\n return lengths;\n}\n\n/** Float coords consumed by the command with this code. */\nexport function pathCommandCoordCount(cmd: number): number {\n return PATH_CMD_LENGTHS[cmd];\n}\n\n/**\n * Visit each command with its coord offset and the pen position BEFORE the\n * command consumes its coords (the segment start). The callback receives\n * (cmd, coordIndex, penX, penY, commandIndex) and stops the walk by returning\n * `false`. The pen advances to the command's last coord pair afterward; `Z`\n * returns it to the subpath's opening `M`, so a command following a `Z`\n * without an intervening `M` starts where SVG says it does.\n *\n * A code `PATH_COMMANDS` does not declare throws once the visitor has seen it,\n * since the walker cannot tell how many coords it consumes.\n */\nexport function forEachSegment(\n commands: ArrayLike<number>,\n coords: ArrayLike<number>,\n visit: (\n cmd: number,\n coordIndex: number,\n penX: number,\n penY: number,\n commandIndex: number,\n ) => void | boolean,\n): void {\n let ci = 0;\n let px = 0, py = 0;\n let startX = 0, startY = 0;\n for (let i = 0; i < commands.length; i++) {\n const cmd = commands[i];\n if (visit(cmd, ci, px, py, i) === false) return;\n const len = pathCommandCoordCount(cmd);\n if (len === undefined) throw new Error(`forEachSegment: unknown command code ${cmd}`);\n if (len > 0) {\n px = coords[ci + len - 2];\n py = coords[ci + len - 1];\n ci += len;\n if (cmd === PATH_M) { startX = px; startY = py; }\n } else if (cmd === PATH_Z) {\n px = startX; py = startY;\n }\n }\n}\n","import type { Box } from './box';\n\n/** Cubic Bezier point at parameter t (de Casteljau / Bernstein form). */\nexport function cubicEvalAt(\n x0: number, y0: number, x1: number, y1: number,\n x2: number, y2: number, x3: number, y3: number, t: number,\n): [number, number] {\n const u = 1 - t;\n const a = u * u * u, b = 3 * u * u * t, c = 3 * u * t * t, d = t * t * t;\n return [\n a * x0 + b * x1 + c * x2 + d * x3,\n a * y0 + b * y1 + c * y2 + d * y3,\n ];\n}\n\n/**\n * Degree-elevate a quadratic (q0, ctrl, q1) to a cubic. Returns the two\n * cubic control points [c1x, c1y, c2x, c2y]; the cubic endpoints equal the\n * quadratic endpoints. c1 = q0 + 2/3(ctrl-q0), c2 = q1 + 2/3(ctrl-q1).\n */\nexport function elevateQuadraticToCubic(\n q0x: number, q0y: number, cx: number, cy: number, q1x: number, q1y: number,\n): [number, number, number, number] {\n return [\n q0x + (2 / 3) * (cx - q0x),\n q0y + (2 / 3) * (cy - q0y),\n q1x + (2 / 3) * (cx - q1x),\n q1y + (2 / 3) * (cy - q1y),\n ];\n}\n\n/** Axis-aligned extrema parameters of one cubic component (the 0,1 ends plus\n * any derivative roots in (0,1)). Used by cubicBounds. */\nfunction componentExtremaTs(p0: number, p1: number, p2: number, p3: number): number[] {\n // B'(t)=0 → quadratic a t² + b t + c = 0 with:\n const a = -p0 + 3 * p1 - 3 * p2 + p3;\n const b = 2 * (p0 - 2 * p1 + p2);\n const c = -p0 + p1;\n const ts: number[] = [];\n const push = (t: number) => { if (t > 0 && t < 1) ts.push(t); };\n if (Math.abs(a) < 1e-12) {\n if (Math.abs(b) > 1e-12) push(-c / b);\n } else {\n const disc = b * b - 4 * a * c;\n if (disc >= 0) {\n const sq = Math.sqrt(disc);\n push((-b + sq) / (2 * a));\n push((-b - sq) / (2 * a));\n }\n }\n return ts;\n}\n\n/** Tight AABB of a cubic, evaluating only extrema that lie on the curve. */\nexport function cubicBounds(\n x0: number, y0: number, x1: number, y1: number,\n x2: number, y2: number, x3: number, y3: number,\n): Box {\n let minX = Math.min(x0, x3), maxX = Math.max(x0, x3);\n let minY = Math.min(y0, y3), maxY = Math.max(y0, y3);\n for (const t of componentExtremaTs(x0, x1, x2, x3)) {\n const [ex] = cubicEvalAt(x0, y0, x1, y1, x2, y2, x3, y3, t);\n if (ex < minX) minX = ex;\n if (ex > maxX) maxX = ex;\n }\n for (const t of componentExtremaTs(y0, y1, y2, y3)) {\n const [, ey] = cubicEvalAt(x0, y0, x1, y1, x2, y2, x3, y3, t);\n if (ey < minY) minY = ey;\n if (ey > maxY) maxY = ey;\n }\n return [minX, minY, maxX, maxY];\n}\n\n/** Quadratic Bezier point at parameter t (Bernstein form). */\nexport function quadraticEvalAt(\n x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, t: number,\n): [number, number] {\n const u = 1 - t;\n const a = u * u, b = 2 * u * t, c = t * t;\n return [a * x0 + b * x1 + c * x2, a * y0 + b * y1 + c * y2];\n}\n\n/** A line segment's coords: start, end. */\nexport type LineCoords = [number, number, number, number];\n/** A quadratic Bezier's coords: start, control, end. */\nexport type QuadraticCoords = [number, number, number, number, number, number];\n/** A cubic Bezier's coords: start, two controls, end. */\nexport type CubicCoords = [number, number, number, number, number, number, number, number];\n\n/**\n * Split a cubic at parameter t (de Casteljau). The two halves share the point\n * at t and together trace the original exactly. A t outside [0, 1] splits the\n * curve's polynomial extension.\n */\nexport function splitCubicAt(\n x0: number, y0: number, x1: number, y1: number,\n x2: number, y2: number, x3: number, y3: number, t: number,\n): [CubicCoords, CubicCoords] {\n const ax = x0 + (x1 - x0) * t, ay = y0 + (y1 - y0) * t;\n const bx = x1 + (x2 - x1) * t, by = y1 + (y2 - y1) * t;\n const cx = x2 + (x3 - x2) * t, cy = y2 + (y3 - y2) * t;\n const dx = ax + (bx - ax) * t, dy = ay + (by - ay) * t;\n const ex = bx + (cx - bx) * t, ey = by + (cy - by) * t;\n const mx = dx + (ex - dx) * t, my = dy + (ey - dy) * t;\n return [[x0, y0, ax, ay, dx, dy, mx, my], [mx, my, ex, ey, cx, cy, x3, y3]];\n}\n\n/** Split a quadratic at parameter t (de Casteljau). See {@link splitCubicAt}. */\nexport function splitQuadraticAt(\n x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, t: number,\n): [QuadraticCoords, QuadraticCoords] {\n const ax = x0 + (x1 - x0) * t, ay = y0 + (y1 - y0) * t;\n const bx = x1 + (x2 - x1) * t, by = y1 + (y2 - y1) * t;\n const mx = ax + (bx - ax) * t, my = ay + (by - ay) * t;\n return [[x0, y0, ax, ay, mx, my], [mx, my, bx, by, x2, y2]];\n}\n\n/** Split a line segment at parameter t. See {@link splitCubicAt}. */\nexport function splitLineAt(\n x0: number, y0: number, x1: number, y1: number, t: number,\n): [LineCoords, LineCoords] {\n const mx = x0 + (x1 - x0) * t, my = y0 + (y1 - y0) * t;\n return [[x0, y0, mx, my], [mx, my, x1, y1]];\n}\n","/**\n * Bezier flattening — subdivide cubic and quadratic segments into polyline\n * approximations within a flatness tolerance. Used by hit-testing and\n * (eventually) any kernel that doesn't want to special-case curves.\n *\n * The flatness metric is the maximum perpendicular distance from any\n * control point to the chord between endpoints. When that distance falls\n * below `tolerance`, the segment is \"flat enough\" and emitted as a single\n * line segment.\n *\n * Tolerance is in world units. 0.5 is a sensible default for screen-rate\n * rendering at 1× zoom; consumers that zoom in heavily should pass a\n * tighter tolerance.\n */\n\nexport const DEFAULT_FLATTEN_TOLERANCE = 0.5;\n\n/** Floor for a non-positive or NaN tolerance. Without it the flatness test can\n * never be satisfied and the subdivision recurses until the stack blows. */\nconst MIN_FLATTEN_TOLERANCE = 1e-6;\n\n/** Subdivision ceiling. The tolerance floor bounds the common runaway; this\n * bounds the other one, coordinates large enough that reaching 1e-6 takes\n * hundreds of levels. Error falls roughly 4x per level, so 16 is far beyond\n * any tolerance a caller can mean. */\nconst MAX_FLATTEN_DEPTH = 16;\n\nfunction usableTolerance(tolerance: number): number {\n return tolerance > 0 ? tolerance : MIN_FLATTEN_TOLERANCE;\n}\n\nfunction finite6(a: number, b: number, c: number, d: number, e: number, f: number): boolean {\n return Number.isFinite(a) && Number.isFinite(b) && Number.isFinite(c)\n && Number.isFinite(d) && Number.isFinite(e) && Number.isFinite(f);\n}\n\nfunction finite8(\n a: number, b: number, c: number, d: number,\n e: number, f: number, g: number, h: number,\n): boolean {\n return finite6(a, b, c, d, e, f) && Number.isFinite(g) && Number.isFinite(h);\n}\n\n/** Distance from point P to line AB (perpendicular). */\nfunction distPointToLine(px: number, py: number, ax: number, ay: number, bx: number, by: number): number {\n const dx = bx - ax;\n const dy = by - ay;\n const len2 = dx * dx + dy * dy;\n if (len2 === 0) {\n const ex = px - ax;\n const ey = py - ay;\n return Math.sqrt(ex * ex + ey * ey);\n }\n const cross = (px - ax) * dy - (py - ay) * dx;\n return Math.abs(cross) / Math.sqrt(len2);\n}\n\n/**\n * Recursively subdivide a cubic bezier (P0..P3) and append `lineTo`-style\n * vertices to `out` (interleaved x,y). The starting endpoint is *not*\n * appended — callers usually emitted it as the segment's previous vertex.\n */\nexport function flattenCubic(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n x3: number, y3: number,\n tolerance: number,\n out: number[],\n): void {\n if (!finite8(x0, y0, x1, y1, x2, y2, x3, y3)) {\n out.push(x3, y3);\n return;\n }\n flattenCubicRec(x0, y0, x1, y1, x2, y2, x3, y3, usableTolerance(tolerance), out, 0);\n}\n\nfunction flattenCubicRec(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n x3: number, y3: number,\n tolerance: number,\n out: number[],\n depth: number,\n): void {\n const d1 = distPointToLine(x1, y1, x0, y0, x3, y3);\n const d2 = distPointToLine(x2, y2, x0, y0, x3, y3);\n if (Math.max(d1, d2) <= tolerance || depth >= MAX_FLATTEN_DEPTH) {\n out.push(x3, y3);\n return;\n }\n // De Casteljau split at t=0.5\n const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;\n const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;\n const x23 = (x2 + x3) * 0.5, y23 = (y2 + y3) * 0.5;\n const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;\n const x123 = (x12 + x23) * 0.5, y123 = (y12 + y23) * 0.5;\n const x0123 = (x012 + x123) * 0.5, y0123 = (y012 + y123) * 0.5;\n flattenCubicRec(x0, y0, x01, y01, x012, y012, x0123, y0123, tolerance, out, depth + 1);\n flattenCubicRec(x0123, y0123, x123, y123, x23, y23, x3, y3, tolerance, out, depth + 1);\n}\n\n/** Recursively subdivide a quadratic bezier (P0, P1, P2). */\nexport function flattenQuadratic(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n tolerance: number,\n out: number[],\n): void {\n if (!finite6(x0, y0, x1, y1, x2, y2)) {\n out.push(x2, y2);\n return;\n }\n flattenQuadraticRec(x0, y0, x1, y1, x2, y2, usableTolerance(tolerance), out, 0);\n}\n\nfunction flattenQuadraticRec(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n tolerance: number,\n out: number[],\n depth: number,\n): void {\n const d = distPointToLine(x1, y1, x0, y0, x2, y2);\n if (d <= tolerance || depth >= MAX_FLATTEN_DEPTH) {\n out.push(x2, y2);\n return;\n }\n const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;\n const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;\n const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;\n flattenQuadraticRec(x0, y0, x01, y01, x012, y012, tolerance, out, depth + 1);\n flattenQuadraticRec(x012, y012, x12, y12, x2, y2, tolerance, out, depth + 1);\n}\n\n/**\n * Like `flattenCubic` but also appends, for each new flattened point, its\n * arc-length fraction `t` (relative to the polyline distance accumulated so\n * far inside this curve) to `arcOut`. Caller then post-processes the segment's\n * `arcOut` range by dividing each by the segment's total flattened arc length\n * to yield t ∈ (0, 1].\n *\n * The returned values are *cumulative distance from the segment start*, not\n * normalized fractions. Two-pass design (accumulate, then divide) keeps the\n * recursive splitter simple — it doesn't need to know the total length up\n * front.\n */\nexport function flattenCubicWithArcLen(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n x3: number, y3: number,\n tolerance: number,\n out: number[],\n arcOut: number[],\n): number {\n if (!finite8(x0, y0, x1, y1, x2, y2, x3, y3)) {\n out.push(x3, y3);\n arcOut.push(0);\n return 0;\n }\n return flattenCubicArcRec(x0, y0, x1, y1, x2, y2, x3, y3, usableTolerance(tolerance), out, arcOut, 0, 0);\n}\n\nfunction flattenCubicArcRec(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n x3: number, y3: number,\n tolerance: number,\n out: number[],\n arcOut: number[],\n accum: number,\n depth: number,\n): number {\n const d1 = distPointToLine(x1, y1, x0, y0, x3, y3);\n const d2 = distPointToLine(x2, y2, x0, y0, x3, y3);\n if (Math.max(d1, d2) <= tolerance || depth >= MAX_FLATTEN_DEPTH) {\n const lastX = out.length >= 2 ? out[out.length - 2] : x0;\n const lastY = out.length >= 2 ? out[out.length - 1] : y0;\n const seg = Math.hypot(x3 - lastX, y3 - lastY);\n accum += seg;\n out.push(x3, y3);\n arcOut.push(accum);\n return accum;\n }\n const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;\n const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;\n const x23 = (x2 + x3) * 0.5, y23 = (y2 + y3) * 0.5;\n const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;\n const x123 = (x12 + x23) * 0.5, y123 = (y12 + y23) * 0.5;\n const x0123 = (x012 + x123) * 0.5, y0123 = (y012 + y123) * 0.5;\n accum = flattenCubicArcRec(x0, y0, x01, y01, x012, y012, x0123, y0123, tolerance, out, arcOut, accum, depth + 1);\n accum = flattenCubicArcRec(x0123, y0123, x123, y123, x23, y23, x3, y3, tolerance, out, arcOut, accum, depth + 1);\n return accum;\n}\n\n/** Flatten a quadratic bezier into line segments within `tolerance`, appending\n * points to `out` and their cumulative arc lengths to `arcOut`. The arc\n * lengths are what lets per-anchor color and dash phase be interpolated\n * evenly along the curve rather than per segment. */\nexport function flattenQuadraticWithArcLen(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n tolerance: number,\n out: number[],\n arcOut: number[],\n): number {\n if (!finite6(x0, y0, x1, y1, x2, y2)) {\n out.push(x2, y2);\n arcOut.push(0);\n return 0;\n }\n return flattenQuadraticArcRec(x0, y0, x1, y1, x2, y2, usableTolerance(tolerance), out, arcOut, 0, 0);\n}\n\nfunction flattenQuadraticArcRec(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n tolerance: number,\n out: number[],\n arcOut: number[],\n accum: number,\n depth: number,\n): number {\n const d = distPointToLine(x1, y1, x0, y0, x2, y2);\n if (d <= tolerance || depth >= MAX_FLATTEN_DEPTH) {\n const lastX = out.length >= 2 ? out[out.length - 2] : x0;\n const lastY = out.length >= 2 ? out[out.length - 1] : y0;\n const seg = Math.hypot(x2 - lastX, y2 - lastY);\n accum += seg;\n out.push(x2, y2);\n arcOut.push(accum);\n return accum;\n }\n const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;\n const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;\n const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;\n accum = flattenQuadraticArcRec(x0, y0, x01, y01, x012, y012, tolerance, out, arcOut, accum, depth + 1);\n accum = flattenQuadraticArcRec(x012, y012, x12, y12, x2, y2, tolerance, out, arcOut, accum, depth + 1);\n return accum;\n}\n\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/scalar.ts","../src/portCurve.ts"],"names":[],"mappings":"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","file":"chunk-3GFNUO4N.js","sourcesContent":["/**\n * Scalar / 2-vector primitives and the kernel-wide epsilon policy.\n *\n * Points are scalar pairs (px, py); there is no point struct. All math is\n * f64 (JS-native). Epsilons are f32-SCALE and magnitude-relative, because\n * stored coords are quantized to Float32 (~7 significant digits) — see the\n * geometry-kernel spec.\n */\n\n/** Base relative epsilon, sized for Float32 storage (~1 part in 1e-6). */\nexport const EPS = 1e-6;\n\n/** A determinant at or below this fraction of its matrix's own scale counts as\n * singular. Dimensionless, so a uniformly tiny matrix still inverts while a\n * large one whose determinant is only rounding does not. */\nexport const SINGULAR_RATIO = 1e-12;\n\n/** 2D cross (wedge) product of vectors (ax,ay) and (bx,by). */\nexport function cross(ax: number, ay: number, bx: number, by: number): number {\n return ax * by - ay * bx;\n}\n\n/** 2D dot product. */\nexport function dot(ax: number, ay: number, bx: number, by: number): number {\n return ax * bx + ay * by;\n}\n\n/** Component difference (ax-bx, ay-by) as a tuple. Cold-path use only. */\nexport function sub(ax: number, ay: number, bx: number, by: number): [number, number] {\n return [ax - bx, ay - by];\n}\n\n/** Squared length of (x,y). Avoids the sqrt; compare against squared thresholds. */\nexport function len2(x: number, y: number): number {\n return x * x + y * y;\n}\n\n/** Three-valued sign. */\nexport function sign(n: number): -1 | 0 | 1 {\n return n > 0 ? 1 : n < 0 ? -1 : 0;\n}\n\n/**\n * Magnitude-scaled approximate equality. Two values are equal when their\n * absolute difference is within EPS scaled by the larger magnitude. Every\n * comparison of two *computed coordinates* goes through this — never `===`,\n * never an f64-tight literal.\n *\n * The exception is a guard against an exact algebraic value that a formula\n * produces bit-for-bit: a homogeneous `w === 1`, a ray's `d === 0`. Those are\n * testing a branch, not comparing coordinates, and `geom/3d` has two of them\n * (`mat4.ts`, `ray3.ts`). Widening one to `approxEq` would change which branch\n * runs, not how precisely it runs.\n */\nexport function approxEq(a: number, b: number, eps: number = EPS): boolean {\n if (a === b) return true; // also the only way two infinities compare equal\n const diff = Math.abs(a - b);\n // Infinity/Infinity is 1, so an unguarded relative test calls every finite\n // number equal to an infinity.\n if (!Number.isFinite(diff)) return false;\n const scale = Math.max(1, Math.abs(a), Math.abs(b));\n return diff <= eps * scale;\n}\n","/**\n * The cubic control points that make a curve leave a port along its normal and\n * arrive at the next against that port's normal — what makes a routed edge read\n * as plugged into a box rather than aimed at it.\n *\n * The rule is stated once, over loose components, and the 2D barrel and `./3d`\n * each wrap it in their own currency. Every operation here is closed on the\n * plane z = 0, so a planar problem answered through the 3D wrapper returns the\n * same numbers as through the 2D one, not an approximation of them.\n */\n\n/** How far a control point reaches toward the other end, as a fraction of the\n * straight-line distance between the two. */\nexport const PORT_REACH = 0.4;\n\n/**\n * `[c1, c2]` for the cubic from `a` to `b`.\n *\n * A null normal falls back to a plain lerp along the chord, which is what makes\n * an unported waypoint curve smoothly instead of kinking. The two ends are not\n * symmetric: `outNormal` points the way the curve departs, while `inNormal`\n * points out of the receiving port, so `c2` is pushed *along* it to arrive\n * against it.\n */\nexport function portControls(\n a: readonly number[],\n b: readonly number[],\n outNormal: readonly number[] | null | undefined,\n inNormal: readonly number[] | null | undefined,\n reach: number = PORT_REACH,\n): [number[], number[]] {\n let sum = 0;\n for (let i = 0; i < a.length; i++) {\n const d = b[i]! - a[i]!;\n sum += d * d;\n }\n const span = Math.sqrt(sum) * reach;\n\n const c1: number[] = [];\n const c2: number[] = [];\n for (let i = 0; i < a.length; i++) {\n const ai = a[i]!;\n const bi = b[i]!;\n c1.push(outNormal == null ? ai + (bi - ai) * reach : ai + outNormal[i]! * span);\n c2.push(inNormal == null ? bi - (bi - ai) * reach : bi + inNormal[i]! * span);\n }\n return [c1, c2];\n}\n\n/** A cubic evaluated at `t`, component-wise, in whatever dimension it was given. */\nexport function cubicAt(\n p0: readonly number[],\n p1: readonly number[],\n p2: readonly number[],\n p3: readonly number[],\n t: number,\n): number[] {\n const u = 1 - t;\n const a = u * u * u;\n const b = 3 * u * u * t;\n const c = 3 * u * t * t;\n const d = t * t * t;\n const out: number[] = [];\n for (let i = 0; i < p0.length; i++) {\n out.push(a * p0[i]! + b * p1[i]! + c * p2[i]! + d * p3[i]!);\n }\n return out;\n}\n"]}
|