@mylasertools/kerfscript 0.3.0 → 0.4.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/CHANGELOG.md +18 -0
- package/LANGUAGE.md +17 -12
- package/dist/assembly.d.cts +20 -0
- package/dist/assembly.d.ts +20 -0
- package/dist/cli.js +408 -59
- package/dist/evaluator.d.cts +3 -0
- package/dist/evaluator.d.ts +3 -0
- package/dist/geometry.d.cts +2 -0
- package/dist/geometry.d.ts +2 -0
- package/dist/index.cjs +24 -19
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +24 -19
- package/dist/render.d.cts +2 -0
- package/dist/render.d.ts +2 -0
- package/docs/javascript.md +11 -10
- package/docs/parts-and-sheets.md +32 -0
- package/docs/versions.md +2 -2
- package/docs/webassembly.md +3 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -12302,6 +12302,273 @@ var require_opentype = __commonJS({
|
|
|
12302
12302
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
12303
12303
|
import { basename, dirname, extname, join, resolve } from "node:path";
|
|
12304
12304
|
|
|
12305
|
+
// src/assembly.ts
|
|
12306
|
+
var RAD = Math.PI / 180;
|
|
12307
|
+
function multiply(a, b) {
|
|
12308
|
+
const out = new Array(16).fill(0);
|
|
12309
|
+
for (let r = 0; r < 4; r++)
|
|
12310
|
+
for (let c = 0; c < 4; c++)
|
|
12311
|
+
for (let k = 0; k < 4; k++) out[r * 4 + c] += a[r * 4 + k] * b[k * 4 + c];
|
|
12312
|
+
return out;
|
|
12313
|
+
}
|
|
12314
|
+
function rotation(axis, degrees) {
|
|
12315
|
+
const c = Math.cos(degrees * RAD);
|
|
12316
|
+
const s = Math.sin(degrees * RAD);
|
|
12317
|
+
if (axis === 0) return [1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1];
|
|
12318
|
+
if (axis === 1) return [c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1];
|
|
12319
|
+
return [c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
|
12320
|
+
}
|
|
12321
|
+
var clean = (n2) => Math.abs(n2) < 1e-12 ? 0 : n2;
|
|
12322
|
+
function placementMatrix(p) {
|
|
12323
|
+
const [ax, ay, az] = p.rotate;
|
|
12324
|
+
const r = multiply(rotation(2, az), multiply(rotation(1, ay), rotation(0, ax)));
|
|
12325
|
+
r[3] = p.at[0];
|
|
12326
|
+
r[7] = p.at[1];
|
|
12327
|
+
r[11] = p.at[2];
|
|
12328
|
+
return r.map(clean);
|
|
12329
|
+
}
|
|
12330
|
+
function apply(m, x, y, z) {
|
|
12331
|
+
return [
|
|
12332
|
+
m[0] * x + m[1] * y + m[2] * z + m[3],
|
|
12333
|
+
m[4] * x + m[5] * y + m[6] * z + m[7],
|
|
12334
|
+
m[8] * x + m[9] * y + m[10] * z + m[11]
|
|
12335
|
+
];
|
|
12336
|
+
}
|
|
12337
|
+
function invertRigid(m) {
|
|
12338
|
+
const [tx, ty, tz] = [m[3], m[7], m[11]];
|
|
12339
|
+
const r = [m[0], m[4], m[8], m[1], m[5], m[9], m[2], m[6], m[10]];
|
|
12340
|
+
return [
|
|
12341
|
+
r[0],
|
|
12342
|
+
r[1],
|
|
12343
|
+
r[2],
|
|
12344
|
+
-(r[0] * tx + r[1] * ty + r[2] * tz),
|
|
12345
|
+
r[3],
|
|
12346
|
+
r[4],
|
|
12347
|
+
r[5],
|
|
12348
|
+
-(r[3] * tx + r[4] * ty + r[5] * tz),
|
|
12349
|
+
r[6],
|
|
12350
|
+
r[7],
|
|
12351
|
+
r[8],
|
|
12352
|
+
-(r[6] * tx + r[7] * ty + r[8] * tz),
|
|
12353
|
+
0,
|
|
12354
|
+
0,
|
|
12355
|
+
0,
|
|
12356
|
+
1
|
|
12357
|
+
];
|
|
12358
|
+
}
|
|
12359
|
+
function bounds2(regions) {
|
|
12360
|
+
let [x0, y0, x1, y1] = [Infinity, Infinity, -Infinity, -Infinity];
|
|
12361
|
+
for (const ring of regions)
|
|
12362
|
+
for (const [x, y] of ring) {
|
|
12363
|
+
x0 = Math.min(x0, x);
|
|
12364
|
+
y0 = Math.min(y0, y);
|
|
12365
|
+
x1 = Math.max(x1, x);
|
|
12366
|
+
y1 = Math.max(y1, y);
|
|
12367
|
+
}
|
|
12368
|
+
return [x0, y0, x1, y1];
|
|
12369
|
+
}
|
|
12370
|
+
function worldBox(p) {
|
|
12371
|
+
const [x0, y0, x1, y1] = bounds2(p.outline);
|
|
12372
|
+
const lo = [Infinity, Infinity, Infinity];
|
|
12373
|
+
const hi = [-Infinity, -Infinity, -Infinity];
|
|
12374
|
+
for (const x of [x0, x1])
|
|
12375
|
+
for (const y of [y0, y1])
|
|
12376
|
+
for (const z of [0, p.thickness]) {
|
|
12377
|
+
const w = apply(p.matrix, x, y, z);
|
|
12378
|
+
for (let k = 0; k < 3; k++) {
|
|
12379
|
+
lo[k] = Math.min(lo[k], w[k]);
|
|
12380
|
+
hi[k] = Math.max(hi[k], w[k]);
|
|
12381
|
+
}
|
|
12382
|
+
}
|
|
12383
|
+
return [lo, hi];
|
|
12384
|
+
}
|
|
12385
|
+
function besideAssembly(placed, loose, gap = 10) {
|
|
12386
|
+
const lo = [Infinity, Infinity, Infinity];
|
|
12387
|
+
const hi = [-Infinity, -Infinity, -Infinity];
|
|
12388
|
+
for (const [a, b] of placed.map(worldBox))
|
|
12389
|
+
for (let k = 0; k < 3; k++) {
|
|
12390
|
+
lo[k] = Math.min(lo[k], a[k]);
|
|
12391
|
+
hi[k] = Math.max(hi[k], b[k]);
|
|
12392
|
+
}
|
|
12393
|
+
const sizes = loose.map((p) => bounds2(p.outline));
|
|
12394
|
+
const limit = sizes.reduce((w, [x0, , x1]) => Math.max(w, x1 - x0), hi[0] - lo[0]);
|
|
12395
|
+
let x = 0;
|
|
12396
|
+
let y = 0;
|
|
12397
|
+
let row = 0;
|
|
12398
|
+
return loose.map((p, i) => {
|
|
12399
|
+
const [x0, y0, x1, y1] = sizes[i];
|
|
12400
|
+
if (x > 0 && x + x1 - x0 > limit) {
|
|
12401
|
+
x = 0;
|
|
12402
|
+
y += row + gap;
|
|
12403
|
+
row = 0;
|
|
12404
|
+
}
|
|
12405
|
+
const matrix = [
|
|
12406
|
+
1,
|
|
12407
|
+
0,
|
|
12408
|
+
0,
|
|
12409
|
+
hi[0] + gap + x - x0,
|
|
12410
|
+
0,
|
|
12411
|
+
1,
|
|
12412
|
+
0,
|
|
12413
|
+
lo[1] + y - y0,
|
|
12414
|
+
0,
|
|
12415
|
+
0,
|
|
12416
|
+
1,
|
|
12417
|
+
lo[2],
|
|
12418
|
+
0,
|
|
12419
|
+
0,
|
|
12420
|
+
0,
|
|
12421
|
+
1
|
|
12422
|
+
];
|
|
12423
|
+
x += x1 - x0 + gap;
|
|
12424
|
+
row = Math.max(row, y1 - y0);
|
|
12425
|
+
return { ...p, matrix: matrix.map(clean) };
|
|
12426
|
+
});
|
|
12427
|
+
}
|
|
12428
|
+
var overlaps = (a, b, eps) => [0, 1, 2].every((k) => a[0][k] < b[1][k] - eps && b[0][k] < a[1][k] - eps);
|
|
12429
|
+
var dot = (a, b) => a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
12430
|
+
var cross = (a, b) => [
|
|
12431
|
+
a[1] * b[2] - a[2] * b[1],
|
|
12432
|
+
a[2] * b[0] - a[0] * b[2],
|
|
12433
|
+
a[0] * b[1] - a[1] * b[0]
|
|
12434
|
+
];
|
|
12435
|
+
var add = (a, b, k = 1) => [a[0] + b[0] * k, a[1] + b[1] * k, a[2] + b[2] * k];
|
|
12436
|
+
var normal = (m) => [m[2], m[6], m[10]];
|
|
12437
|
+
var origin = (m) => [m[3], m[7], m[11]];
|
|
12438
|
+
var turn = (m, v) => [
|
|
12439
|
+
m[0] * v[0] + m[1] * v[1] + m[2] * v[2],
|
|
12440
|
+
m[4] * v[0] + m[5] * v[1] + m[6] * v[2],
|
|
12441
|
+
m[8] * v[0] + m[9] * v[1] + m[10] * v[2]
|
|
12442
|
+
];
|
|
12443
|
+
function spans(regions, from, dir) {
|
|
12444
|
+
const len = dir[0] * dir[0] + dir[1] * dir[1];
|
|
12445
|
+
const hits = [];
|
|
12446
|
+
for (const ring of regions)
|
|
12447
|
+
for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
|
|
12448
|
+
const a = ring[j];
|
|
12449
|
+
const b = ring[i];
|
|
12450
|
+
const da = dir[0] * (a[1] - from[1]) - dir[1] * (a[0] - from[0]);
|
|
12451
|
+
const db = dir[0] * (b[1] - from[1]) - dir[1] * (b[0] - from[0]);
|
|
12452
|
+
if (da > 0 === db > 0) continue;
|
|
12453
|
+
const f = da / (da - db);
|
|
12454
|
+
const x = a[0] + (b[0] - a[0]) * f - from[0];
|
|
12455
|
+
const y = a[1] + (b[1] - a[1]) * f - from[1];
|
|
12456
|
+
hits.push((x * dir[0] + y * dir[1]) / len);
|
|
12457
|
+
}
|
|
12458
|
+
return hits.sort((p, q) => p - q);
|
|
12459
|
+
}
|
|
12460
|
+
function shared(a, b, eps) {
|
|
12461
|
+
let total = 0;
|
|
12462
|
+
let i = 0;
|
|
12463
|
+
let j = 0;
|
|
12464
|
+
while (i + 1 < a.length && j + 1 < b.length) {
|
|
12465
|
+
const length = Math.min(a[i + 1], b[j + 1]) - Math.max(a[i], b[j]);
|
|
12466
|
+
if (length > eps) total += length;
|
|
12467
|
+
if (a[i + 1] < b[j + 1]) i += 2;
|
|
12468
|
+
else j += 2;
|
|
12469
|
+
}
|
|
12470
|
+
return total;
|
|
12471
|
+
}
|
|
12472
|
+
function steps(lo, hi, eps, pitch) {
|
|
12473
|
+
const from = lo + eps;
|
|
12474
|
+
const to = hi - eps;
|
|
12475
|
+
if (to <= from) return { at: [], size: 0 };
|
|
12476
|
+
const n2 = Math.max(4, Math.ceil((to - from) / pitch));
|
|
12477
|
+
return {
|
|
12478
|
+
at: Array.from({ length: n2 }, (_, i) => from + (to - from) * (i + 0.5) / n2),
|
|
12479
|
+
size: (to - from) / n2
|
|
12480
|
+
};
|
|
12481
|
+
}
|
|
12482
|
+
function localLine(inverse, at, dir) {
|
|
12483
|
+
const p = apply(inverse, at[0], at[1], at[2]);
|
|
12484
|
+
const d2 = turn(inverse, dir);
|
|
12485
|
+
return [
|
|
12486
|
+
[p[0], p[1]],
|
|
12487
|
+
[d2[0], d2[1]]
|
|
12488
|
+
];
|
|
12489
|
+
}
|
|
12490
|
+
function crossing(A, B, invA, invB, eps, pitch, volume) {
|
|
12491
|
+
const nA = normal(A.matrix);
|
|
12492
|
+
const nB = normal(B.matrix);
|
|
12493
|
+
const raw = cross(nA, nB);
|
|
12494
|
+
const size = Math.hypot(...raw);
|
|
12495
|
+
const line = [raw[0] / size, raw[1] / size, raw[2] / size];
|
|
12496
|
+
const side = cross(line, nA);
|
|
12497
|
+
const tilt = dot(nB, side);
|
|
12498
|
+
const oA = origin(A.matrix);
|
|
12499
|
+
const bLevel = dot(nB, origin(B.matrix));
|
|
12500
|
+
const depths = steps(0, A.thickness, eps, pitch);
|
|
12501
|
+
let total = 0;
|
|
12502
|
+
for (const depth of depths.at) {
|
|
12503
|
+
const base = add(oA, nA, depth);
|
|
12504
|
+
const b0 = (bLevel - dot(nB, base)) / tilt;
|
|
12505
|
+
const b1 = (bLevel + B.thickness - dot(nB, base)) / tilt;
|
|
12506
|
+
const alongs = steps(Math.min(b0, b1), Math.max(b0, b1), eps, pitch);
|
|
12507
|
+
for (const along of alongs.at) {
|
|
12508
|
+
const at = add(base, side, along);
|
|
12509
|
+
const [fromA, dirA] = localLine(invA, at, line);
|
|
12510
|
+
const [fromB, dirB] = localLine(invB, at, line);
|
|
12511
|
+
total += shared(spans(A.outline, fromA, dirA), spans(B.outline, fromB, dirB), eps) * depths.size * alongs.size;
|
|
12512
|
+
if (total > volume) return true;
|
|
12513
|
+
}
|
|
12514
|
+
}
|
|
12515
|
+
return false;
|
|
12516
|
+
}
|
|
12517
|
+
function stacked(A, B, invA, eps, pitch, volume) {
|
|
12518
|
+
const rel = [0, 1, 2, 3].flatMap(
|
|
12519
|
+
(r) => [0, 1, 2, 3].map((c) => {
|
|
12520
|
+
let v = 0;
|
|
12521
|
+
for (let k = 0; k < 4; k++) v += invA[r * 4 + k] * B.matrix[k * 4 + c];
|
|
12522
|
+
return v;
|
|
12523
|
+
})
|
|
12524
|
+
);
|
|
12525
|
+
const z0 = rel[11];
|
|
12526
|
+
const z1 = rel[11] + rel[10] * B.thickness;
|
|
12527
|
+
const depth = Math.min(A.thickness, Math.max(z0, z1)) - Math.max(0, Math.min(z0, z1));
|
|
12528
|
+
if (depth <= eps) return false;
|
|
12529
|
+
const moved = B.outline.map(
|
|
12530
|
+
(ring) => ring.map(
|
|
12531
|
+
([x, y]) => [rel[0] * x + rel[1] * y + rel[3], rel[4] * x + rel[5] * y + rel[7]]
|
|
12532
|
+
)
|
|
12533
|
+
);
|
|
12534
|
+
const [ax0, ay0, ax1, ay1] = bounds2(A.outline);
|
|
12535
|
+
const [bx0, by0, bx1, by1] = bounds2(moved);
|
|
12536
|
+
const rows = steps(Math.max(ay0, by0), Math.min(ay1, by1), eps, pitch);
|
|
12537
|
+
let across = 0;
|
|
12538
|
+
for (const y of rows.at) {
|
|
12539
|
+
across += shared(spans(A.outline, [0, y], [1, 0]), spans(moved, [0, y], [1, 0]), eps) * rows.size * depth;
|
|
12540
|
+
if (across > volume) return true;
|
|
12541
|
+
}
|
|
12542
|
+
const columns = steps(Math.max(ax0, bx0), Math.min(ax1, bx1), eps, pitch);
|
|
12543
|
+
let down = 0;
|
|
12544
|
+
for (const x of columns.at) {
|
|
12545
|
+
down += shared(spans(A.outline, [x, 0], [0, 1]), spans(moved, [x, 0], [0, 1]), eps) * columns.size * depth;
|
|
12546
|
+
if (down > volume) return true;
|
|
12547
|
+
}
|
|
12548
|
+
return false;
|
|
12549
|
+
}
|
|
12550
|
+
function collisions(parts, maxPairs = Infinity, eps = 0.05, pitch = 0.25, volume = 1) {
|
|
12551
|
+
const boxes = parts.map(worldBox);
|
|
12552
|
+
const inverses = parts.map((p) => invertRigid(p.matrix));
|
|
12553
|
+
const order = parts.map((_, i) => i).sort((i, j) => boxes[i][0][0] - boxes[j][0][0]);
|
|
12554
|
+
const found = [];
|
|
12555
|
+
let checked = 0;
|
|
12556
|
+
for (let i = 0; i < order.length; i++)
|
|
12557
|
+
for (let j = i + 1; j < order.length; j++) {
|
|
12558
|
+
const a = order[i];
|
|
12559
|
+
const b = order[j];
|
|
12560
|
+
if (boxes[b][0][0] >= boxes[a][1][0] - eps) break;
|
|
12561
|
+
if (!overlaps(boxes[a], boxes[b], eps)) continue;
|
|
12562
|
+
if (++checked > maxPairs) return { found, complete: false };
|
|
12563
|
+
const [A, B] = a < b ? [parts[a], parts[b]] : [parts[b], parts[a]];
|
|
12564
|
+
const [invA, invB] = a < b ? [inverses[a], inverses[b]] : [inverses[b], inverses[a]];
|
|
12565
|
+
const parallel = Math.hypot(...cross(normal(A.matrix), normal(B.matrix))) < 1e-9;
|
|
12566
|
+
const hit = parallel ? stacked(A, B, invA, eps, pitch, volume) : crossing(A, B, invA, invB, eps, pitch, volume);
|
|
12567
|
+
if (hit) found.push([A, B]);
|
|
12568
|
+
}
|
|
12569
|
+
return { found, complete: true };
|
|
12570
|
+
}
|
|
12571
|
+
|
|
12305
12572
|
// src/values.ts
|
|
12306
12573
|
var isRange = (v) => typeof v === "object" && v !== null && !Array.isArray(v) && v.type === "range";
|
|
12307
12574
|
var isFn = (v) => typeof v === "object" && v !== null && !Array.isArray(v) && v.type === "function";
|
|
@@ -12440,7 +12707,7 @@ function fmt(n2) {
|
|
|
12440
12707
|
}
|
|
12441
12708
|
|
|
12442
12709
|
// src/functions.ts
|
|
12443
|
-
var
|
|
12710
|
+
var RAD2 = Math.PI / 180;
|
|
12444
12711
|
var def = (sig, run, order) => ({
|
|
12445
12712
|
params: sig.replace("...", "").split(",").map((p) => p.trim()).filter(Boolean),
|
|
12446
12713
|
rest: sig.endsWith("..."),
|
|
@@ -12506,8 +12773,8 @@ function argumentWork(name, args, max) {
|
|
|
12506
12773
|
}
|
|
12507
12774
|
return n2;
|
|
12508
12775
|
}
|
|
12509
|
-
var math1 = (f) => def("x", (a) => typeof a[0] === "number" ?
|
|
12510
|
-
function
|
|
12776
|
+
var math1 = (f) => def("x", (a) => typeof a[0] === "number" ? clean2(f(a[0])) : void 0);
|
|
12777
|
+
function clean2(x) {
|
|
12511
12778
|
const r = Math.round(x);
|
|
12512
12779
|
return Math.abs(x - r) < 1e-12 ? r : x;
|
|
12513
12780
|
}
|
|
@@ -12538,16 +12805,16 @@ var FUNCTIONS = {
|
|
|
12538
12805
|
// log(x) is base 10; log(base, x) takes the base first
|
|
12539
12806
|
log: def(
|
|
12540
12807
|
"x, base",
|
|
12541
|
-
(a, c) => c.given < 2 ?
|
|
12808
|
+
(a, c) => c.given < 2 ? clean2(Math.log10(num(a[0], "log"))) : Math.log(num(a[0], "log")) / Math.log(num(a[1], "log")),
|
|
12542
12809
|
(n2) => n2 >= 2 ? ["base", "x"] : ["x", "base"]
|
|
12543
12810
|
),
|
|
12544
|
-
sin: math1((x) => Math.sin(x *
|
|
12545
|
-
cos: math1((x) => Math.cos(x *
|
|
12546
|
-
tan: math1((x) => Math.tan(x *
|
|
12547
|
-
asin: math1((x) => Math.asin(x) /
|
|
12548
|
-
acos: math1((x) => Math.acos(x) /
|
|
12549
|
-
atan: math1((x) => Math.atan(x) /
|
|
12550
|
-
atan2: def("y, x", (a) =>
|
|
12811
|
+
sin: math1((x) => Math.sin(x * RAD2)),
|
|
12812
|
+
cos: math1((x) => Math.cos(x * RAD2)),
|
|
12813
|
+
tan: math1((x) => Math.tan(x * RAD2)),
|
|
12814
|
+
asin: math1((x) => Math.asin(x) / RAD2),
|
|
12815
|
+
acos: math1((x) => Math.acos(x) / RAD2),
|
|
12816
|
+
atan: math1((x) => Math.atan(x) / RAD2),
|
|
12817
|
+
atan2: def("y, x", (a) => clean2(Math.atan2(num(a[0], "atan2"), num(a[1], "atan2")) / RAD2)),
|
|
12551
12818
|
pow: def("x, y", (a) => Math.pow(num(a[0], "pow"), num(a[1], "pow"))),
|
|
12552
12819
|
min: def(
|
|
12553
12820
|
"values...",
|
|
@@ -14012,7 +14279,7 @@ var ClipperBase = class _ClipperBase {
|
|
|
14012
14279
|
next.prevInAEL = prev;
|
|
14013
14280
|
}
|
|
14014
14281
|
getBounds() {
|
|
14015
|
-
const
|
|
14282
|
+
const bounds3 = {
|
|
14016
14283
|
left: Number.MAX_SAFE_INTEGER,
|
|
14017
14284
|
top: Number.MAX_SAFE_INTEGER,
|
|
14018
14285
|
right: Number.MIN_SAFE_INTEGER,
|
|
@@ -14021,18 +14288,18 @@ var ClipperBase = class _ClipperBase {
|
|
|
14021
14288
|
for (const t of this.vertexList) {
|
|
14022
14289
|
let v = t;
|
|
14023
14290
|
do {
|
|
14024
|
-
if (v.pt.x <
|
|
14025
|
-
|
|
14026
|
-
if (v.pt.x >
|
|
14027
|
-
|
|
14028
|
-
if (v.pt.y <
|
|
14029
|
-
|
|
14030
|
-
if (v.pt.y >
|
|
14031
|
-
|
|
14291
|
+
if (v.pt.x < bounds3.left)
|
|
14292
|
+
bounds3.left = v.pt.x;
|
|
14293
|
+
if (v.pt.x > bounds3.right)
|
|
14294
|
+
bounds3.right = v.pt.x;
|
|
14295
|
+
if (v.pt.y < bounds3.top)
|
|
14296
|
+
bounds3.top = v.pt.y;
|
|
14297
|
+
if (v.pt.y > bounds3.bottom)
|
|
14298
|
+
bounds3.bottom = v.pt.y;
|
|
14032
14299
|
v = v.next;
|
|
14033
14300
|
} while (v !== t);
|
|
14034
14301
|
}
|
|
14035
|
-
return Rect64Utils.isEmpty(
|
|
14302
|
+
return Rect64Utils.isEmpty(bounds3) ? { left: 0, top: 0, right: 0, bottom: 0 } : bounds3;
|
|
14036
14303
|
}
|
|
14037
14304
|
executeInternal(ct, fillRule) {
|
|
14038
14305
|
if (ct === ClipType.NoClip)
|
|
@@ -15247,17 +15514,17 @@ var ClipperBase = class _ClipperBase {
|
|
|
15247
15514
|
return false;
|
|
15248
15515
|
const maxCoord = InternalClipper.maxCoordForSafeCrossSq;
|
|
15249
15516
|
if (Math.abs(a) < maxCoord && Math.abs(b) < maxCoord && Math.abs(c) < maxCoord && Math.abs(d2) < maxCoord) {
|
|
15250
|
-
const
|
|
15251
|
-
return
|
|
15517
|
+
const cross3 = a * d2 - c * b;
|
|
15518
|
+
return cross3 * cross3 / (c * c + d2 * d2) > 0.25;
|
|
15252
15519
|
}
|
|
15253
15520
|
if (Number.isSafeInteger(a) && Number.isSafeInteger(b) && Number.isSafeInteger(c) && Number.isSafeInteger(d2)) {
|
|
15254
|
-
const
|
|
15255
|
-
const crossSq =
|
|
15521
|
+
const cross3 = BigInt(a) * BigInt(d2) - BigInt(c) * BigInt(b);
|
|
15522
|
+
const crossSq = cross3 * cross3;
|
|
15256
15523
|
const denom = BigInt(c) * BigInt(c) + BigInt(d2) * BigInt(d2);
|
|
15257
15524
|
return B42 * crossSq > denom;
|
|
15258
15525
|
}
|
|
15259
|
-
const
|
|
15260
|
-
return
|
|
15526
|
+
const cross2 = a * d2 - c * b;
|
|
15527
|
+
return cross2 * cross2 / (c * c + d2 * d2) > 0.25;
|
|
15261
15528
|
}
|
|
15262
15529
|
intersectEdges(ae1, ae2, pt) {
|
|
15263
15530
|
let resultOp;
|
|
@@ -16442,8 +16709,8 @@ var ClipperOffset = class _ClipperOffset {
|
|
|
16442
16709
|
y: Math.round(pt.y + offsetVec.y),
|
|
16443
16710
|
z: ptz
|
|
16444
16711
|
});
|
|
16445
|
-
const
|
|
16446
|
-
for (let i = 1; i <
|
|
16712
|
+
const steps2 = Math.ceil(this.stepsPerRad * Math.abs(angle));
|
|
16713
|
+
for (let i = 1; i < steps2; i++) {
|
|
16447
16714
|
offsetVec = {
|
|
16448
16715
|
x: offsetVec.x * this.stepCos - this.stepSin * offsetVec.y,
|
|
16449
16716
|
y: offsetVec.x * this.stepSin + offsetVec.y * this.stepCos
|
|
@@ -16613,8 +16880,8 @@ var ClipperOffset = class _ClipperOffset {
|
|
|
16613
16880
|
}
|
|
16614
16881
|
const ptz = pt.z || 0;
|
|
16615
16882
|
if (group.endType === EndType.Round) {
|
|
16616
|
-
const
|
|
16617
|
-
this.pathOut = _ClipperOffset.ellipse(pt, Math.abs(this.groupDelta), Math.abs(this.groupDelta),
|
|
16883
|
+
const steps2 = Math.ceil(this.stepsPerRad * 2 * Math.PI);
|
|
16884
|
+
this.pathOut = _ClipperOffset.ellipse(pt, Math.abs(this.groupDelta), Math.abs(this.groupDelta), steps2);
|
|
16618
16885
|
if (ptz !== 0)
|
|
16619
16886
|
for (let i = 0; i < this.pathOut.length; i++)
|
|
16620
16887
|
this.pathOut[i].z = ptz;
|
|
@@ -16672,20 +16939,20 @@ var ClipperOffset = class _ClipperOffset {
|
|
|
16672
16939
|
static sqr(val) {
|
|
16673
16940
|
return val * val;
|
|
16674
16941
|
}
|
|
16675
|
-
static ellipse(center, radiusX, radiusY = 0,
|
|
16942
|
+
static ellipse(center, radiusX, radiusY = 0, steps2 = 0) {
|
|
16676
16943
|
if (radiusX <= 0)
|
|
16677
16944
|
return [];
|
|
16678
16945
|
if (radiusY <= 0)
|
|
16679
16946
|
radiusY = radiusX;
|
|
16680
|
-
if (
|
|
16681
|
-
|
|
16947
|
+
if (steps2 <= 2) {
|
|
16948
|
+
steps2 = Math.ceil(Math.PI * Math.sqrt((radiusX + radiusY) / 2));
|
|
16682
16949
|
}
|
|
16683
|
-
const si = Math.sin(2 * Math.PI /
|
|
16684
|
-
const co = Math.cos(2 * Math.PI /
|
|
16950
|
+
const si = Math.sin(2 * Math.PI / steps2);
|
|
16951
|
+
const co = Math.cos(2 * Math.PI / steps2);
|
|
16685
16952
|
let dx = co;
|
|
16686
16953
|
let dy = si;
|
|
16687
16954
|
const result = [{ x: Math.round(center.x + radiusX), y: center.y }];
|
|
16688
|
-
for (let i = 1; i <
|
|
16955
|
+
for (let i = 1; i < steps2; ++i) {
|
|
16689
16956
|
result.push({
|
|
16690
16957
|
x: Math.round(center.x + radiusX * dx),
|
|
16691
16958
|
y: Math.round(center.y + radiusY * dy)
|
|
@@ -16831,7 +17098,7 @@ function area2(p) {
|
|
|
16831
17098
|
a += (p[j][0] + p[i][0]) * (p[j][1] - p[i][1]);
|
|
16832
17099
|
return -a / 2;
|
|
16833
17100
|
}
|
|
16834
|
-
function
|
|
17101
|
+
function apply2(m, [x, y]) {
|
|
16835
17102
|
return [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
|
|
16836
17103
|
}
|
|
16837
17104
|
function transformLayers(layers, m) {
|
|
@@ -16840,10 +17107,10 @@ function transformLayers(layers, m) {
|
|
|
16840
17107
|
for (const [k, l] of layers) {
|
|
16841
17108
|
out.set(k, {
|
|
16842
17109
|
regions: l.regions.map((p) => {
|
|
16843
|
-
const q = p.map((pt) =>
|
|
17110
|
+
const q = p.map((pt) => apply2(m, pt));
|
|
16844
17111
|
return flip ? q.reverse() : q;
|
|
16845
17112
|
}),
|
|
16846
|
-
lines: l.lines.map((p) => p.map((pt) =>
|
|
17113
|
+
lines: l.lines.map((p) => p.map((pt) => apply2(m, pt)))
|
|
16847
17114
|
});
|
|
16848
17115
|
}
|
|
16849
17116
|
return out;
|
|
@@ -16907,17 +17174,17 @@ function layerBounds(layers, skip) {
|
|
|
16907
17174
|
function hull(points) {
|
|
16908
17175
|
const pts = [...points].sort((a, b) => a[0] - b[0] || a[1] - b[1]);
|
|
16909
17176
|
if (pts.length < 3) return pts;
|
|
16910
|
-
const
|
|
17177
|
+
const cross2 = (o, a, b) => (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
|
|
16911
17178
|
const lower = [];
|
|
16912
17179
|
for (const p of pts) {
|
|
16913
|
-
while (lower.length >= 2 &&
|
|
17180
|
+
while (lower.length >= 2 && cross2(lower[lower.length - 2], lower[lower.length - 1], p) <= 0)
|
|
16914
17181
|
lower.pop();
|
|
16915
17182
|
lower.push(p);
|
|
16916
17183
|
}
|
|
16917
17184
|
const upper = [];
|
|
16918
17185
|
for (let i = pts.length - 1; i >= 0; i--) {
|
|
16919
17186
|
const p = pts[i];
|
|
16920
|
-
while (upper.length >= 2 &&
|
|
17187
|
+
while (upper.length >= 2 && cross2(upper[upper.length - 2], upper[upper.length - 1], p) <= 0)
|
|
16921
17188
|
upper.pop();
|
|
16922
17189
|
upper.push(p);
|
|
16923
17190
|
}
|
|
@@ -17562,7 +17829,7 @@ var Parser = class _Parser {
|
|
|
17562
17829
|
|
|
17563
17830
|
// src/stdlib.ts
|
|
17564
17831
|
var LIBRARIES = {
|
|
17565
|
-
"kerf/box": '// kerf/box: finger-jointed boxes.\n// Copyright (c) 2026 MyLaserTools. AGPL-3.0-only or MyLaserTools commercial licence.\n\n// Box from its outer size [width, depth, height] in the current material.\n// Edges pair "out" with "in", and the bottom owns every bottom corner,\n// so the six panels interlock without gaps.\nmodule box(size, lid = false, finger = undef) {\n w = size[0];\n d = size[1];\n h = size[2];\n top = lid ? "in" : "flat";\n part("bottom") finger_rect([w, d], "out", finger = finger);\n if (lid) part("lid") finger_rect([w, d], "out", finger = finger);\n part("front")
|
|
17832
|
+
"kerf/box": '// kerf/box: finger-jointed boxes.\n// Copyright (c) 2026 MyLaserTools. AGPL-3.0-only or MyLaserTools commercial licence.\n\n// Box from its outer size [width, depth, height] in the current material.\n// Edges pair "out" with "in", and the bottom owns every bottom corner,\n// so the six panels interlock without gaps.\nmodule box(size, lid = false, finger = undef) {\n w = size[0];\n d = size[1];\n h = size[2];\n t = $thickness;\n top = lid ? "in" : "flat";\n part("bottom", at = [0, 0, 0]) finger_rect([w, d], "out", finger = finger);\n if (lid) part("lid", at = [0, 0, h - t]) finger_rect([w, d], "out", finger = finger);\n part("front", at = [0, t, 0], rotate = [90, 0, 0])\n finger_rect([w, h], ["in", "out", top, "out"], finger = finger);\n part("back", at = [0, d, 0], rotate = [90, 0, 0])\n finger_rect([w, h], ["in", "out", top, "out"], finger = finger);\n part("left", rotate = [90, 0, 90])\n finger_rect([d, h], ["in", "in", top, "in"], finger = finger);\n part("right", at = [w - t, 0, 0], rotate = [90, 0, 90])\n finger_rect([d, h], ["in", "in", top, "in"], finger = finger);\n}\n\n// Divider that slides between two walls: tabs on both sides drop into\n// finger_holes() cut in the walls.\nmodule divider(size, finger = undef) {\n finger_rect(size, ["flat", "out", "flat", "out"], finger = finger);\n}\n'
|
|
17566
17833
|
};
|
|
17567
17834
|
|
|
17568
17835
|
// src/paths.ts
|
|
@@ -17576,7 +17843,7 @@ function flatten(cmds, tolerance = 0.02) {
|
|
|
17576
17843
|
if (cur.length >= 2) (close ? closed : open).push(cur);
|
|
17577
17844
|
cur = [];
|
|
17578
17845
|
};
|
|
17579
|
-
const
|
|
17846
|
+
const steps2 = (len) => Math.max(2, Math.min(256, Math.ceil(Math.sqrt(len / tolerance))));
|
|
17580
17847
|
for (const c of cmds) {
|
|
17581
17848
|
if (c.type === "M") {
|
|
17582
17849
|
finish(false);
|
|
@@ -17587,7 +17854,7 @@ function flatten(cmds, tolerance = 0.02) {
|
|
|
17587
17854
|
cur.push(last);
|
|
17588
17855
|
} else if (c.type === "Q") {
|
|
17589
17856
|
const [x0, y0] = last;
|
|
17590
|
-
const n2 =
|
|
17857
|
+
const n2 = steps2(Math.hypot(c.x1 - x0, c.y1 - y0) + Math.hypot(c.x - c.x1, c.y - c.y1));
|
|
17591
17858
|
for (let i = 1; i <= n2; i++) {
|
|
17592
17859
|
const t = i / n2, u = 1 - t;
|
|
17593
17860
|
cur.push([
|
|
@@ -17598,7 +17865,7 @@ function flatten(cmds, tolerance = 0.02) {
|
|
|
17598
17865
|
last = [c.x, c.y];
|
|
17599
17866
|
} else if (c.type === "C") {
|
|
17600
17867
|
const [x0, y0] = last;
|
|
17601
|
-
const n2 =
|
|
17868
|
+
const n2 = steps2(
|
|
17602
17869
|
Math.hypot(c.x1 - x0, c.y1 - y0) + Math.hypot(c.x2 - c.x1, c.y2 - c.y1) + Math.hypot(c.x - c.x2, c.y - c.y2)
|
|
17603
17870
|
);
|
|
17604
17871
|
for (let i = 1; i <= n2; i++) {
|
|
@@ -17869,21 +18136,22 @@ var DEFAULT_LIMITS = {
|
|
|
17869
18136
|
maxTextLength: 2e3,
|
|
17870
18137
|
maxPoints: 2e6,
|
|
17871
18138
|
maxOutputPoints: 1e6,
|
|
17872
|
-
maxSheets: 200
|
|
18139
|
+
maxSheets: 200,
|
|
18140
|
+
maxCollisionPairs: 2e4
|
|
17873
18141
|
};
|
|
17874
18142
|
var SHAPE_COST = 100;
|
|
17875
18143
|
var LIST_COST = 4;
|
|
17876
18144
|
var CHARS_PER_ITEM = 8;
|
|
17877
18145
|
var shapePoints = (s) => {
|
|
17878
18146
|
let n2 = SHAPE_COST;
|
|
17879
|
-
const
|
|
18147
|
+
const add2 = (layers) => {
|
|
17880
18148
|
for (const l of layers.values()) {
|
|
17881
18149
|
for (const p of l.regions) n2 += p.length;
|
|
17882
18150
|
for (const p of l.lines) n2 += p.length;
|
|
17883
18151
|
}
|
|
17884
18152
|
};
|
|
17885
|
-
|
|
17886
|
-
for (const p of s.parts)
|
|
18153
|
+
add2(s.layers);
|
|
18154
|
+
for (const p of s.parts) add2(p.layers);
|
|
17887
18155
|
return n2;
|
|
17888
18156
|
};
|
|
17889
18157
|
var Env = class {
|
|
@@ -18397,7 +18665,7 @@ var Evaluator = class {
|
|
|
18397
18665
|
const max = this.limits.maxListLength;
|
|
18398
18666
|
const parts = [];
|
|
18399
18667
|
let n2 = 0;
|
|
18400
|
-
const
|
|
18668
|
+
const add2 = (label, v, quote) => {
|
|
18401
18669
|
if (parts.length) n2 += 2;
|
|
18402
18670
|
const r = write(v, max - n2 - label.length, quote);
|
|
18403
18671
|
n2 += label.length + r.text.length;
|
|
@@ -18408,8 +18676,8 @@ var Evaluator = class {
|
|
|
18408
18676
|
);
|
|
18409
18677
|
parts.push(label + r.text);
|
|
18410
18678
|
};
|
|
18411
|
-
for (const v of a.pos)
|
|
18412
|
-
for (const [k, v] of a.named)
|
|
18679
|
+
for (const v of a.pos) add2("", v, false);
|
|
18680
|
+
for (const [k, v] of a.named) add2(`${k} = `, v, true);
|
|
18413
18681
|
return parts.join(", ");
|
|
18414
18682
|
}
|
|
18415
18683
|
arith(op, a, b, at) {
|
|
@@ -18512,6 +18780,34 @@ var Evaluator = class {
|
|
|
18512
18780
|
return [v[0], v[1] ?? 0];
|
|
18513
18781
|
throw new Error(`${name} must be a number or [x, y], got ${show(v)}`);
|
|
18514
18782
|
}
|
|
18783
|
+
vec3(v, name) {
|
|
18784
|
+
const ok = (x) => typeof x === "number" && Number.isFinite(x);
|
|
18785
|
+
if (Array.isArray(v) && (v.length === 2 || v.length === 3) && v.every(ok))
|
|
18786
|
+
return [v[0], v[1], v[2] ?? 0];
|
|
18787
|
+
throw new Error(`${name} must be [x, y, z], got ${show(v)}`);
|
|
18788
|
+
}
|
|
18789
|
+
placements(at, turn2, qty) {
|
|
18790
|
+
const list2 = (v, name) => {
|
|
18791
|
+
if (v === void 0) return [[0, 0, 0]];
|
|
18792
|
+
if (Array.isArray(v) && v.length > 0 && Array.isArray(v[0]))
|
|
18793
|
+
return v.map((item, i) => this.vec3(item, `${name}[${i}]`));
|
|
18794
|
+
return [this.vec3(v, name)];
|
|
18795
|
+
};
|
|
18796
|
+
const ats = list2(at, "at");
|
|
18797
|
+
const turns = list2(turn2, "rotate");
|
|
18798
|
+
for (const [items, name] of [
|
|
18799
|
+
[ats, "at"],
|
|
18800
|
+
[turns, "rotate"]
|
|
18801
|
+
])
|
|
18802
|
+
if (items.length !== 1 && items.length !== qty)
|
|
18803
|
+
throw new Error(
|
|
18804
|
+
`${name} needs one placement per copy: qty is ${qty} but ${name} has ${items.length}`
|
|
18805
|
+
);
|
|
18806
|
+
return Array.from({ length: qty }, (_, i) => ({
|
|
18807
|
+
at: ats[ats.length === 1 ? 0 : i],
|
|
18808
|
+
rotate: turns[turns.length === 1 ? 0 : i]
|
|
18809
|
+
}));
|
|
18810
|
+
}
|
|
18515
18811
|
points(v, name) {
|
|
18516
18812
|
if (!Array.isArray(v)) throw new Error(`${name} must be a list of [x, y] points`);
|
|
18517
18813
|
return v.map((p, i) => {
|
|
@@ -18832,6 +19128,9 @@ var Evaluator = class {
|
|
|
18832
19128
|
this.copies += qty;
|
|
18833
19129
|
if (!(this.copies <= this.limits.maxParts))
|
|
18834
19130
|
throw new Error(`more than ${this.limits.maxParts} part copies in total, the limit`);
|
|
19131
|
+
const at = this.arg(c.args, "at", -1);
|
|
19132
|
+
const turn2 = this.arg(c.args, "rotate", -1);
|
|
19133
|
+
const placements = at === void 0 && turn2 === void 0 ? void 0 : this.placements(at, turn2, qty);
|
|
18835
19134
|
const s = c.children();
|
|
18836
19135
|
return {
|
|
18837
19136
|
layers: /* @__PURE__ */ new Map(),
|
|
@@ -18843,7 +19142,8 @@ var Evaluator = class {
|
|
|
18843
19142
|
layers: s.layers,
|
|
18844
19143
|
thickness: this.thickness(c.env),
|
|
18845
19144
|
kerf: toNumber(this.dyn(c.env, "$kerf")) || 0,
|
|
18846
|
-
material: toText(this.dyn(c.env, "$material") ?? "material")
|
|
19145
|
+
material: toText(this.dyn(c.env, "$material") ?? "material"),
|
|
19146
|
+
...placements ? { placements } : {}
|
|
18847
19147
|
}
|
|
18848
19148
|
]
|
|
18849
19149
|
};
|
|
@@ -19189,6 +19489,9 @@ function render(source, options = {}) {
|
|
|
19189
19489
|
});
|
|
19190
19490
|
if (!parts.length) warnings.push("Nothing to cut: the program made no shapes.");
|
|
19191
19491
|
const infos = [];
|
|
19492
|
+
const assembly = [];
|
|
19493
|
+
const loose = [];
|
|
19494
|
+
const stackedCopies = /* @__PURE__ */ new Set();
|
|
19192
19495
|
const ready = [];
|
|
19193
19496
|
for (const p of parts) {
|
|
19194
19497
|
const material = union2(
|
|
@@ -19209,6 +19512,30 @@ function render(source, options = {}) {
|
|
|
19209
19512
|
}
|
|
19210
19513
|
if (regions.length || lines.length) layers.set(k, { regions, lines });
|
|
19211
19514
|
}
|
|
19515
|
+
if (material.length) {
|
|
19516
|
+
const flat = { name: p.name, thickness: p.thickness, outline: material };
|
|
19517
|
+
if (p.placements) {
|
|
19518
|
+
const seen = /* @__PURE__ */ new Set();
|
|
19519
|
+
p.placements.forEach((placement, i) => {
|
|
19520
|
+
const part = { ...flat, copy: i + 1, matrix: placementMatrix(placement), placed: true };
|
|
19521
|
+
assembly.push(part);
|
|
19522
|
+
const key = part.matrix.map((v) => v.toFixed(6)).join(",");
|
|
19523
|
+
if (seen.has(key)) stackedCopies.add(part);
|
|
19524
|
+
seen.add(key);
|
|
19525
|
+
});
|
|
19526
|
+
if (seen.size < p.placements.length)
|
|
19527
|
+
warnings.push(
|
|
19528
|
+
`Copies of part "${p.name}" are in the same place in the assembly. Give at a list with one placement per copy to spread them out.`
|
|
19529
|
+
);
|
|
19530
|
+
} else
|
|
19531
|
+
for (let i = 0; i < p.qty; i++)
|
|
19532
|
+
loose.push({
|
|
19533
|
+
...flat,
|
|
19534
|
+
copy: i + 1,
|
|
19535
|
+
matrix: placementMatrix({ at: [0, 0, 0], rotate: [0, 0, 0] }),
|
|
19536
|
+
placed: false
|
|
19537
|
+
});
|
|
19538
|
+
}
|
|
19212
19539
|
const n2 = pieces(material).length;
|
|
19213
19540
|
if (n2 > 1)
|
|
19214
19541
|
warnings.push(
|
|
@@ -19250,6 +19577,27 @@ function render(source, options = {}) {
|
|
|
19250
19577
|
infos.push(info);
|
|
19251
19578
|
ready.push({ info, layers });
|
|
19252
19579
|
}
|
|
19580
|
+
const { found: clashes, complete } = collisions(
|
|
19581
|
+
assembly.filter((part) => !stackedCopies.has(part)),
|
|
19582
|
+
limits.maxCollisionPairs
|
|
19583
|
+
);
|
|
19584
|
+
if (!complete)
|
|
19585
|
+
warnings.push(
|
|
19586
|
+
`The assembly has more than ${limits.maxCollisionPairs} pairs of touching parts, the limit, so only those were checked for collisions.`
|
|
19587
|
+
);
|
|
19588
|
+
for (const [a, b] of clashes.slice(0, 5))
|
|
19589
|
+
warnings.push(
|
|
19590
|
+
`Parts "${a.name}"${a.copy > 1 ? ` (copy ${a.copy})` : ""} and "${b.name}"${b.copy > 1 ? ` (copy ${b.copy})` : ""} collide in the assembly. Check their edges and where they are placed.`
|
|
19591
|
+
);
|
|
19592
|
+
if (clashes.length > 5)
|
|
19593
|
+
warnings.push(`${clashes.length - 5} more pairs of parts collide in the assembly.`);
|
|
19594
|
+
if (assembly.length && loose.length) {
|
|
19595
|
+
const names = [...new Set(loose.map((p) => `"${p.name}"`))];
|
|
19596
|
+
warnings.push(
|
|
19597
|
+
`${names.length === 1 ? "Part" : "Parts"} ${names.slice(0, 5).join(", ")}${names.length > 5 ? ` and ${names.length - 5} more` : ""} ${names.length === 1 ? "has" : "have"} no at or rotate, so ${names.length === 1 ? "it lies" : "they lie"} flat beside the assembly.`
|
|
19598
|
+
);
|
|
19599
|
+
assembly.push(...besideAssembly(assembly, loose));
|
|
19600
|
+
}
|
|
19253
19601
|
let outputPoints = 0;
|
|
19254
19602
|
for (const r of ready) {
|
|
19255
19603
|
let n2 = 0;
|
|
@@ -19396,7 +19744,7 @@ function render(source, options = {}) {
|
|
|
19396
19744
|
};
|
|
19397
19745
|
}
|
|
19398
19746
|
const single = sheets.length === 1 ? sheets[0] : void 0;
|
|
19399
|
-
const
|
|
19747
|
+
const stacked2 = single ? [] : sheets.flatMap((s, i) => {
|
|
19400
19748
|
const dy = sheets.slice(0, i).reduce((acc, p) => acc + p.height + 10, 0);
|
|
19401
19749
|
return s.items.map((it) => ({ ...it, layers: moved(it.layers, [1, 0, 0, 1, 0, dy]) }));
|
|
19402
19750
|
});
|
|
@@ -19404,8 +19752,8 @@ function render(source, options = {}) {
|
|
|
19404
19752
|
const height = round2(
|
|
19405
19753
|
Math.max(1, sheets.reduce((acc, s) => acc + s.height, 0) + 10 * Math.max(0, sheets.length - 1))
|
|
19406
19754
|
);
|
|
19407
|
-
const svg = single ? single.svg : toSvg(
|
|
19408
|
-
const paths = single ? single.paths : layerPaths(
|
|
19755
|
+
const svg = single ? single.svg : toSvg(stacked2, width, height, layerList);
|
|
19756
|
+
const paths = single ? single.paths : layerPaths(stacked2, layerList);
|
|
19409
19757
|
return {
|
|
19410
19758
|
sheets,
|
|
19411
19759
|
width: single?.width ?? width,
|
|
@@ -19413,6 +19761,7 @@ function render(source, options = {}) {
|
|
|
19413
19761
|
paths,
|
|
19414
19762
|
svg,
|
|
19415
19763
|
parts: infos,
|
|
19764
|
+
assembly,
|
|
19416
19765
|
layers: layerList,
|
|
19417
19766
|
warnings,
|
|
19418
19767
|
echoes: res.echoes
|
|
@@ -19503,7 +19852,7 @@ function parameters(source) {
|
|
|
19503
19852
|
}
|
|
19504
19853
|
|
|
19505
19854
|
// src/index.ts
|
|
19506
|
-
var VERSION = "0.
|
|
19855
|
+
var VERSION = "0.4.0";
|
|
19507
19856
|
var LANGUAGE_VERSION = "0.1";
|
|
19508
19857
|
|
|
19509
19858
|
// fonts/AtkinsonHyperlegible-Regular.ttf
|