@willcgage/module-schematic 0.48.0 → 0.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +43 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +43 -30
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -253,6 +253,10 @@ interface ModuleSchematicDoc {
|
|
|
253
253
|
* +y up). Stored as an open ring; renderers close it. Absent = derive an
|
|
254
254
|
* approximate band from the endplate widths. */
|
|
255
255
|
outline?: BenchworkPoint[];
|
|
256
|
+
/** Benchwork HOLE — an inner boundary punched out of `outline`, making the
|
|
257
|
+
* board a DONUT (a return loop's open middle). Same frame as `outline`; stored
|
|
258
|
+
* as an open ring, renderers close it. Absent = a solid board. */
|
|
259
|
+
outlineInner?: BenchworkPoint[];
|
|
256
260
|
/** Internal section joints — inches from endplate A where the module's boards
|
|
257
261
|
* split into sections. Operationally one unit; these mark construction/transport
|
|
258
262
|
* seams (exempt from the end-interface standards). Empty/absent = one section.
|
|
@@ -405,6 +409,9 @@ interface ModuleFootprintInput {
|
|
|
405
409
|
endplateTrackOffsets?: Record<string, number>;
|
|
406
410
|
/** Authored benchwork outline (module-local inches), or absent for the band. */
|
|
407
411
|
outline?: BenchworkPoint[] | null;
|
|
412
|
+
/** Authored benchwork HOLE — the inner boundary punched out of `outline` to
|
|
413
|
+
* make a donut. Absent/short = a solid board. */
|
|
414
|
+
outlineInner?: BenchworkPoint[] | null;
|
|
408
415
|
/** The module's sections (#96 phase 2). When any carries an outline, the
|
|
409
416
|
* module's footprint is the union of those — `outline` is then ignored. */
|
|
410
417
|
sections?: SchematicSection[] | null;
|
|
@@ -432,6 +439,9 @@ interface ModuleFootprint {
|
|
|
432
439
|
/** Authored outline (arc-sampled closed ring) or null → render the band.
|
|
433
440
|
* Null too when `sectionOutlines` is non-empty — the sections ARE the shape. */
|
|
434
441
|
outline: BenchworkPoint[] | null;
|
|
442
|
+
/** Authored HOLE (arc-sampled closed ring) punched out of `outline` → a donut
|
|
443
|
+
* board. Null = solid. Renderers fill `outline` with `outlineInner` cut out. */
|
|
444
|
+
outlineInner: BenchworkPoint[] | null;
|
|
435
445
|
/** Per-section footprints, arc-sampled (#96 phase 2b). Draw every one: together
|
|
436
446
|
* they are the module's footprint. Empty = this module doesn't use sections,
|
|
437
447
|
* so fall back to `outline ?? band` exactly as before. */
|
|
@@ -793,6 +803,9 @@ interface EditorState {
|
|
|
793
803
|
* (endplate A's track point at the origin, mainline +x, perpendicular +y up).
|
|
794
804
|
* Empty = no authored outline (fall back to the endplate-width band). */
|
|
795
805
|
outline: BenchworkPoint[];
|
|
806
|
+
/** Benchwork HOLE (donut inner boundary), module-local inches. Empty = a solid
|
|
807
|
+
* board. Set by the return-loop generator; punched out of `outline`. */
|
|
808
|
+
outlineInner: BenchworkPoint[];
|
|
796
809
|
/** Internal section joints — inches from endplate A where the boards split
|
|
797
810
|
* into sections. Empty = a single section (#48). */
|
|
798
811
|
sectionBreaks: number[];
|
package/dist/index.d.ts
CHANGED
|
@@ -253,6 +253,10 @@ interface ModuleSchematicDoc {
|
|
|
253
253
|
* +y up). Stored as an open ring; renderers close it. Absent = derive an
|
|
254
254
|
* approximate band from the endplate widths. */
|
|
255
255
|
outline?: BenchworkPoint[];
|
|
256
|
+
/** Benchwork HOLE — an inner boundary punched out of `outline`, making the
|
|
257
|
+
* board a DONUT (a return loop's open middle). Same frame as `outline`; stored
|
|
258
|
+
* as an open ring, renderers close it. Absent = a solid board. */
|
|
259
|
+
outlineInner?: BenchworkPoint[];
|
|
256
260
|
/** Internal section joints — inches from endplate A where the module's boards
|
|
257
261
|
* split into sections. Operationally one unit; these mark construction/transport
|
|
258
262
|
* seams (exempt from the end-interface standards). Empty/absent = one section.
|
|
@@ -405,6 +409,9 @@ interface ModuleFootprintInput {
|
|
|
405
409
|
endplateTrackOffsets?: Record<string, number>;
|
|
406
410
|
/** Authored benchwork outline (module-local inches), or absent for the band. */
|
|
407
411
|
outline?: BenchworkPoint[] | null;
|
|
412
|
+
/** Authored benchwork HOLE — the inner boundary punched out of `outline` to
|
|
413
|
+
* make a donut. Absent/short = a solid board. */
|
|
414
|
+
outlineInner?: BenchworkPoint[] | null;
|
|
408
415
|
/** The module's sections (#96 phase 2). When any carries an outline, the
|
|
409
416
|
* module's footprint is the union of those — `outline` is then ignored. */
|
|
410
417
|
sections?: SchematicSection[] | null;
|
|
@@ -432,6 +439,9 @@ interface ModuleFootprint {
|
|
|
432
439
|
/** Authored outline (arc-sampled closed ring) or null → render the band.
|
|
433
440
|
* Null too when `sectionOutlines` is non-empty — the sections ARE the shape. */
|
|
434
441
|
outline: BenchworkPoint[] | null;
|
|
442
|
+
/** Authored HOLE (arc-sampled closed ring) punched out of `outline` → a donut
|
|
443
|
+
* board. Null = solid. Renderers fill `outline` with `outlineInner` cut out. */
|
|
444
|
+
outlineInner: BenchworkPoint[] | null;
|
|
435
445
|
/** Per-section footprints, arc-sampled (#96 phase 2b). Draw every one: together
|
|
436
446
|
* they are the module's footprint. Empty = this module doesn't use sections,
|
|
437
447
|
* so fall back to `outline ?? band` exactly as before. */
|
|
@@ -793,6 +803,9 @@ interface EditorState {
|
|
|
793
803
|
* (endplate A's track point at the origin, mainline +x, perpendicular +y up).
|
|
794
804
|
* Empty = no authored outline (fall back to the endplate-width band). */
|
|
795
805
|
outline: BenchworkPoint[];
|
|
806
|
+
/** Benchwork HOLE (donut inner boundary), module-local inches. Empty = a solid
|
|
807
|
+
* board. Set by the return-loop generator; punched out of `outline`. */
|
|
808
|
+
outlineInner: BenchworkPoint[];
|
|
796
809
|
/** Internal section joints — inches from endplate A where the boards split
|
|
797
810
|
* into sections. Empty = a single section (#48). */
|
|
798
811
|
sectionBreaks: number[];
|
package/dist/index.js
CHANGED
|
@@ -476,6 +476,9 @@ function moduleFootprint(input) {
|
|
|
476
476
|
// endplate A's face (the far face would be a spurious plate at the throat).
|
|
477
477
|
endplateFaces: input.loop ? endplateFaceSegments(centerline, widthA, widthB, offA, offB).slice(0, 1) : endplateFaceSegments(centerline, widthA, widthB, offA, offB),
|
|
478
478
|
outline: sectionOutlines.length || !authored ? null : sampleBenchworkOutline(authored),
|
|
479
|
+
// The donut hole, arc-sampled — only when there's a solid outline to punch it
|
|
480
|
+
// out of (a sectioned module isn't a donut). Renderers cut it from `outline`.
|
|
481
|
+
outlineInner: sectionOutlines.length || !authored || !input.outlineInner || input.outlineInner.length < 3 ? null : sampleBenchworkOutline(input.outlineInner),
|
|
479
482
|
sectionOutlines
|
|
480
483
|
};
|
|
481
484
|
}
|
|
@@ -557,6 +560,7 @@ function emptyEditorState(lengthInches) {
|
|
|
557
560
|
endplateWidths: {},
|
|
558
561
|
endplateTrackOffsets: {},
|
|
559
562
|
outline: [],
|
|
563
|
+
outlineInner: [],
|
|
560
564
|
sectionBreaks: [],
|
|
561
565
|
sections: [],
|
|
562
566
|
controlPoints: [],
|
|
@@ -793,6 +797,8 @@ function stateToDoc(state, recordNumber) {
|
|
|
793
797
|
// Benchwork footprint outline (module-local inches); only when it's a real
|
|
794
798
|
// ring (≥ 3 vertices).
|
|
795
799
|
...state.outline.length >= 3 ? { outline: state.outline } : {},
|
|
800
|
+
// Benchwork hole (donut inner boundary), when it's a real ring.
|
|
801
|
+
...state.outlineInner.length >= 3 ? { outlineInner: state.outlineInner } : {},
|
|
796
802
|
// Internal section joints (inches from A), when the module has more than one.
|
|
797
803
|
...state.sectionBreaks.length ? { sectionBreaks: state.sectionBreaks } : {},
|
|
798
804
|
// Sections as objects — emitted only once the owner has some, so a module
|
|
@@ -884,6 +890,11 @@ function docToState(doc, fallbackLength, moduleTracks = []) {
|
|
|
884
890
|
y: p.y,
|
|
885
891
|
...Number.isFinite(p.bulge) && p.bulge ? { bulge: p.bulge } : {}
|
|
886
892
|
}));
|
|
893
|
+
const outlineInner = (d.outlineInner ?? []).filter((p) => p && Number.isFinite(p.x) && Number.isFinite(p.y)).map((p) => ({
|
|
894
|
+
x: p.x,
|
|
895
|
+
y: p.y,
|
|
896
|
+
...Number.isFinite(p.bulge) && p.bulge ? { bulge: p.bulge } : {}
|
|
897
|
+
}));
|
|
887
898
|
const mainPath = trackPath(d.mainPath) ?? [];
|
|
888
899
|
const main2Track_ = (d.tracks ?? []).find((t) => t.id === MAIN2_TRACK_ID);
|
|
889
900
|
const main2Path = trackPath(d.main2Path ?? main2Track_?.path) ?? [];
|
|
@@ -907,6 +918,7 @@ function docToState(doc, fallbackLength, moduleTracks = []) {
|
|
|
907
918
|
endplateWidths,
|
|
908
919
|
endplateTrackOffsets,
|
|
909
920
|
outline,
|
|
921
|
+
outlineInner,
|
|
910
922
|
sectionBreaks: (d.sectionBreaks ?? []).filter((n) => Number.isFinite(n)).map((n) => sc(n)),
|
|
911
923
|
sections: moduleSections(d),
|
|
912
924
|
mainPath,
|
|
@@ -1332,36 +1344,7 @@ function returnLoop(shape, opts) {
|
|
|
1332
1344
|
for (let i = 0; i <= steps; i++) out.push({ x: cx + r * Math.cos(a0 + (a12 - a0) * i / steps), y: cy + r * Math.sin(a0 + (a12 - a0) * i / steps) });
|
|
1333
1345
|
return out;
|
|
1334
1346
|
};
|
|
1335
|
-
|
|
1336
|
-
const s = 2 * R;
|
|
1337
|
-
const loop2 = [
|
|
1338
|
-
{ x: L, y: 0 },
|
|
1339
|
-
{ x: L, y: R },
|
|
1340
|
-
{ x: L + s, y: R },
|
|
1341
|
-
{ x: L + s, y: -R },
|
|
1342
|
-
{ x: L, y: -R },
|
|
1343
|
-
{ x: L, y: 0 }
|
|
1344
|
-
];
|
|
1345
|
-
return {
|
|
1346
|
-
throat: T,
|
|
1347
|
-
loop: rd(loop2),
|
|
1348
|
-
wyeLegs: [rd([T, { x: L, y: R }]), rd([T, { x: L, y: -R }])],
|
|
1349
|
-
wyeHalfAngleDeg: 90,
|
|
1350
|
-
outlineOuter: rd([
|
|
1351
|
-
{ x: 0, y: hw },
|
|
1352
|
-
{ x: L + s + hw, y: hw },
|
|
1353
|
-
{ x: L + s + hw, y: -R - hw },
|
|
1354
|
-
{ x: 0, y: -R - hw }
|
|
1355
|
-
]),
|
|
1356
|
-
outlineInner: rd([
|
|
1357
|
-
{ x: L + hw, y: R - hw },
|
|
1358
|
-
{ x: L + s - hw, y: R - hw },
|
|
1359
|
-
{ x: L + s - hw, y: -R + hw },
|
|
1360
|
-
{ x: L + hw, y: -R + hw }
|
|
1361
|
-
])
|
|
1362
|
-
};
|
|
1363
|
-
}
|
|
1364
|
-
const D = shape === "circle" ? R * 1.15 : R * 1.6;
|
|
1347
|
+
const D = shape === "circle" || shape === "square" ? R * 1.15 : R * 1.6;
|
|
1365
1348
|
const offY = shape === "offset-teardrop" ? R * 0.7 : 0;
|
|
1366
1349
|
const C = { x: L + D, y: offY };
|
|
1367
1350
|
const dist = Math.hypot(C.x - T.x, C.y - T.y);
|
|
@@ -1388,6 +1371,36 @@ function returnLoop(shape, opts) {
|
|
|
1388
1371
|
];
|
|
1389
1372
|
};
|
|
1390
1373
|
const Ri = R - hw;
|
|
1374
|
+
if (shape === "square") {
|
|
1375
|
+
const xL = C.x - R - hw;
|
|
1376
|
+
const xR = C.x + R + hw;
|
|
1377
|
+
const yT = R + hw;
|
|
1378
|
+
const outerSquare = [
|
|
1379
|
+
{ x: 0, y: hw },
|
|
1380
|
+
{ x: xL, y: hw },
|
|
1381
|
+
{ x: xL, y: yT },
|
|
1382
|
+
{ x: xR, y: yT },
|
|
1383
|
+
{ x: xR, y: -yT },
|
|
1384
|
+
{ x: xL, y: -yT },
|
|
1385
|
+
{ x: xL, y: -hw },
|
|
1386
|
+
{ x: 0, y: -hw }
|
|
1387
|
+
];
|
|
1388
|
+
const iHalf = (R - hw) / Math.SQRT2;
|
|
1389
|
+
const holeSquare = iHalf > 2 ? [
|
|
1390
|
+
{ x: C.x - iHalf, y: iHalf },
|
|
1391
|
+
{ x: C.x + iHalf, y: iHalf },
|
|
1392
|
+
{ x: C.x + iHalf, y: -iHalf },
|
|
1393
|
+
{ x: C.x - iHalf, y: -iHalf }
|
|
1394
|
+
] : [];
|
|
1395
|
+
return {
|
|
1396
|
+
throat: T,
|
|
1397
|
+
loop: rd(loop),
|
|
1398
|
+
wyeLegs: [rd([T, P1]), rd([T, P2])],
|
|
1399
|
+
wyeHalfAngleDeg: r2(half * 180 / Math.PI),
|
|
1400
|
+
outlineOuter: rd(outerSquare),
|
|
1401
|
+
outlineInner: rd(holeSquare)
|
|
1402
|
+
};
|
|
1403
|
+
}
|
|
1391
1404
|
return {
|
|
1392
1405
|
throat: T,
|
|
1393
1406
|
loop: rd(loop),
|