@willcgage/module-schematic 0.95.1 → 0.96.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 +45 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -2
- package/dist/index.d.ts +35 -2
- package/dist/index.js +44 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1703,11 +1703,22 @@ var FAST_TRACKS_N_ME55_CROSSOVERS = [
|
|
|
1703
1703
|
};
|
|
1704
1704
|
});
|
|
1705
1705
|
var DEFAULT_FLEX_PART_ID = "atlas-c55-n-flex";
|
|
1706
|
+
var GENERIC_END_OF_TRACK = [
|
|
1707
|
+
{
|
|
1708
|
+
id: "generic-bumper",
|
|
1709
|
+
manufacturer: "Generic",
|
|
1710
|
+
line: "N scale",
|
|
1711
|
+
scale: "N",
|
|
1712
|
+
name: "Bumper",
|
|
1713
|
+
kind: "bumper"
|
|
1714
|
+
}
|
|
1715
|
+
];
|
|
1706
1716
|
var BUILT_IN_TRACK_PARTS = [
|
|
1707
1717
|
...ATLAS_CODE55_N,
|
|
1708
1718
|
...FAST_TRACKS_N_ME55,
|
|
1709
1719
|
...FAST_TRACKS_N_ME55_CROSSOVERS,
|
|
1710
|
-
...FLEX_TRACK_PARTS
|
|
1720
|
+
...FLEX_TRACK_PARTS,
|
|
1721
|
+
...GENERIC_END_OF_TRACK
|
|
1711
1722
|
];
|
|
1712
1723
|
function flexParts(library = BUILT_IN_TRACK_PARTS) {
|
|
1713
1724
|
return library.filter((p) => p.kind === "flex");
|
|
@@ -2162,6 +2173,7 @@ function turnoutClosure(size, opts = {}) {
|
|
|
2162
2173
|
}
|
|
2163
2174
|
function partGeometryGap(part) {
|
|
2164
2175
|
if (part.kind === "flex") return null;
|
|
2176
|
+
if (part.kind === "bumper") return null;
|
|
2165
2177
|
if (part.kind === "crossover")
|
|
2166
2178
|
return "a crossover fixture builds one HALF of the assembly (piecesPerAssembly), so its published lengths describe a piece, not the finished part \u2014 the geometry of the whole crossover is not yet derivable from them";
|
|
2167
2179
|
if (part.kind === "crossing") return "crossing geometry is not modelled yet";
|
|
@@ -2175,6 +2187,14 @@ function partGeometryGap(part) {
|
|
|
2175
2187
|
}
|
|
2176
2188
|
function partGeometry(part, library = BUILT_IN_TRACK_PARTS) {
|
|
2177
2189
|
if (partGeometryGap(part)) return null;
|
|
2190
|
+
if (part.kind === "bumper") {
|
|
2191
|
+
return {
|
|
2192
|
+
joints: [{ id: "a", role: "throat", x: 0, y: 0, angleDeg: 180 }],
|
|
2193
|
+
routes: [],
|
|
2194
|
+
source: part.overallLength?.source ?? "unverified",
|
|
2195
|
+
divergingEndMeasured: false
|
|
2196
|
+
};
|
|
2197
|
+
}
|
|
2178
2198
|
if (part.kind === "flex") {
|
|
2179
2199
|
return {
|
|
2180
2200
|
joints: [
|
|
@@ -2265,6 +2285,12 @@ function pieceRoutePaths(piece, library = BUILT_IN_TRACK_PARTS) {
|
|
|
2265
2285
|
return { x: piece.x + x * c - ly * s, y: piece.y + x * s + ly * c };
|
|
2266
2286
|
};
|
|
2267
2287
|
const out = [];
|
|
2288
|
+
if (part.kind === "bumper") {
|
|
2289
|
+
const at2 = joints[0];
|
|
2290
|
+
if (!at2) return out;
|
|
2291
|
+
const len = part.overallLength?.inches ?? BUMPER_DRAWN_INCHES;
|
|
2292
|
+
return [{ route: ["a", "a"], points: [{ x: at2.x, y: at2.y }, place(len, 0)] }];
|
|
2293
|
+
}
|
|
2268
2294
|
for (const route of geo.routes) {
|
|
2269
2295
|
const a = at(route[0]);
|
|
2270
2296
|
const b = at(route[1]);
|
|
@@ -2328,6 +2354,7 @@ function partsPlaceable(library = BUILT_IN_TRACK_PARTS) {
|
|
|
2328
2354
|
return { placeable, blocked };
|
|
2329
2355
|
}
|
|
2330
2356
|
var JOINT_SNAP_INCHES = 0.01;
|
|
2357
|
+
var BUMPER_DRAWN_INCHES = 0.75;
|
|
2331
2358
|
function flexRunEnd(lengthInches, radiusInches) {
|
|
2332
2359
|
const L = lengthInches;
|
|
2333
2360
|
const R = radiusInches;
|
|
@@ -2519,6 +2546,7 @@ function walkTrackGraph(graph, pieces, startAt, library = BUILT_IN_TRACK_PARTS)
|
|
|
2519
2546
|
toPos: startPos,
|
|
2520
2547
|
bornAt,
|
|
2521
2548
|
endsAt: null,
|
|
2549
|
+
closedBy: null,
|
|
2522
2550
|
pieces: [],
|
|
2523
2551
|
spans: [],
|
|
2524
2552
|
lateral: 0
|
|
@@ -2533,7 +2561,11 @@ function walkTrackGraph(graph, pieces, startAt, library = BUILT_IN_TRACK_PARTS)
|
|
|
2533
2561
|
const geo = geoOf(here.piece);
|
|
2534
2562
|
if (!geo) break;
|
|
2535
2563
|
const opts = geo.routes.filter((r) => r.includes(here.joint));
|
|
2536
|
-
if (!opts.length)
|
|
2564
|
+
if (!opts.length) {
|
|
2565
|
+
route.pieces.push(here.piece);
|
|
2566
|
+
route.closedBy = here.piece;
|
|
2567
|
+
break;
|
|
2568
|
+
}
|
|
2537
2569
|
const pick = opts.find((r) => r.includes("through")) ?? opts[0];
|
|
2538
2570
|
const exitJoint = pick[0] === here.joint ? pick[1] : pick[0];
|
|
2539
2571
|
const exit = byKey.get(`${here.piece}.${exitJoint}`);
|
|
@@ -2691,7 +2723,10 @@ function graphToDoc(pieces, input) {
|
|
|
2691
2723
|
role: "main",
|
|
2692
2724
|
lane: 0,
|
|
2693
2725
|
from: epA?.id ?? "A",
|
|
2694
|
-
...epB ? { to: epB.id } : {}
|
|
2726
|
+
...epB ? { to: epB.id } : {},
|
|
2727
|
+
// A main can be closed too — that is a pocket module, where the track
|
|
2728
|
+
// runs in and stops rather than crossing to a second endplate.
|
|
2729
|
+
...main.closedBy ? { bumperAt: "to" } : {}
|
|
2695
2730
|
},
|
|
2696
2731
|
...twoMains ? [
|
|
2697
2732
|
{
|
|
@@ -2718,6 +2753,11 @@ function graphToDoc(pieces, input) {
|
|
|
2718
2753
|
lane: laneOf(r, uniqueBranches),
|
|
2719
2754
|
fromPos: round(Math.min(r.fromPos, r.toPos)),
|
|
2720
2755
|
toPos: round(Math.max(r.fromPos, r.toPos)),
|
|
2756
|
+
// ⚠️ ALWAYS THE `to` END, and not because of an assumption: a branch's
|
|
2757
|
+
// positions are ARC LENGTH FROM ITS THROAT, so they only ever grow — a
|
|
2758
|
+
// spur running physically back toward endplate A still ends at the larger
|
|
2759
|
+
// number. The closed end is the far one from the turnout, by definition.
|
|
2760
|
+
...r.closedBy ? { bumperAt: "to" } : {},
|
|
2721
2761
|
...meta.trackName ? { trackName: meta.trackName } : {},
|
|
2722
2762
|
...meta.capacityFeet != null ? { capacityFeet: meta.capacityFeet } : {},
|
|
2723
2763
|
...meta.moduleTrackId != null ? { moduleTrackId: meta.moduleTrackId } : {}
|
|
@@ -3477,6 +3517,7 @@ function poseOverridesFromDoc(doc) {
|
|
|
3477
3517
|
|
|
3478
3518
|
exports.ATLAS_CODE55_N = ATLAS_CODE55_N;
|
|
3479
3519
|
exports.BUILT_IN_TRACK_PARTS = BUILT_IN_TRACK_PARTS;
|
|
3520
|
+
exports.BUMPER_DRAWN_INCHES = BUMPER_DRAWN_INCHES;
|
|
3480
3521
|
exports.CLEARANCE_SPACING_INCHES = CLEARANCE_SPACING_INCHES;
|
|
3481
3522
|
exports.CODE55_RAIL_HEIGHT_INCHES = CODE55_RAIL_HEIGHT_INCHES;
|
|
3482
3523
|
exports.DEFAULT_FLEX_PART_ID = DEFAULT_FLEX_PART_ID;
|
|
@@ -3491,6 +3532,7 @@ exports.FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES = FREEMO_ENDPLATE_WIDTH_RECOMME
|
|
|
3491
3532
|
exports.FREEMO_MAIN_MIN_RADIUS_INCHES = FREEMO_MAIN_MIN_RADIUS_INCHES;
|
|
3492
3533
|
exports.FREEMO_REVERSE_CURVE_STRAIGHT_INCHES = FREEMO_REVERSE_CURVE_STRAIGHT_INCHES;
|
|
3493
3534
|
exports.FREEMO_TRACK_SPACING_INCHES = FREEMO_TRACK_SPACING_INCHES;
|
|
3535
|
+
exports.GENERIC_END_OF_TRACK = GENERIC_END_OF_TRACK;
|
|
3494
3536
|
exports.JOINT_SNAP_INCHES = JOINT_SNAP_INCHES;
|
|
3495
3537
|
exports.MAIN2_TRACK_ID = MAIN2_TRACK_ID;
|
|
3496
3538
|
exports.MAIN_TRACK_ID = MAIN_TRACK_ID;
|