@willcgage/module-schematic 0.59.0 → 0.61.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 +69 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +86 -3
- package/dist/index.d.ts +86 -3
- package/dist/index.js +68 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -117,6 +117,15 @@ function samplePath(pts, segsPerArc = 20) {
|
|
|
117
117
|
out.push({ x: pts[n - 1].x, y: pts[n - 1].y });
|
|
118
118
|
return out;
|
|
119
119
|
}
|
|
120
|
+
function pathLengthInches(path) {
|
|
121
|
+
const pts = trackPath(path);
|
|
122
|
+
if (!pts) return 0;
|
|
123
|
+
const poly = samplePath(pts);
|
|
124
|
+
let total = 0;
|
|
125
|
+
for (let i = 1; i < poly.length; i++)
|
|
126
|
+
total += Math.hypot(poly[i].x - poly[i - 1].x, poly[i].y - poly[i - 1].y);
|
|
127
|
+
return total;
|
|
128
|
+
}
|
|
120
129
|
function trackPath(path) {
|
|
121
130
|
const pts = (path ?? []).filter((p) => p && Number.isFinite(p.x) && Number.isFinite(p.y)).map((p) => ({
|
|
122
131
|
x: p.x,
|
|
@@ -1475,6 +1484,32 @@ function turnoutClosure(size, opts = {}) {
|
|
|
1475
1484
|
}
|
|
1476
1485
|
};
|
|
1477
1486
|
}
|
|
1487
|
+
function frogCasting(cl, opts = {}) {
|
|
1488
|
+
const g = opts.gaugeInches ?? RAIL_GAUGE_INCHES;
|
|
1489
|
+
const w = opts.reachInches ?? g * 1.5;
|
|
1490
|
+
const fw = opts.flangewayInches ?? g * 0.12;
|
|
1491
|
+
const m = cl.frogSlope;
|
|
1492
|
+
const lead = cl.lead;
|
|
1493
|
+
const apex = { x: lead, y: g / 2 };
|
|
1494
|
+
const point = [
|
|
1495
|
+
{ x: lead + w, y: g / 2 },
|
|
1496
|
+
apex,
|
|
1497
|
+
{ x: lead + w, y: g / 2 + m * w }
|
|
1498
|
+
];
|
|
1499
|
+
const wings = [
|
|
1500
|
+
[
|
|
1501
|
+
{ x: lead - w, y: g / 2 - fw },
|
|
1502
|
+
{ x: lead - w * 0.35, y: g / 2 - fw },
|
|
1503
|
+
{ x: lead + w * 0.35, y: g / 2 - fw * 0.5 }
|
|
1504
|
+
],
|
|
1505
|
+
[
|
|
1506
|
+
{ x: lead - w, y: g / 2 + m * -w + fw },
|
|
1507
|
+
{ x: lead - w * 0.35, y: g / 2 + m * -w * 0.35 + fw },
|
|
1508
|
+
{ x: lead + w * 0.35, y: g / 2 + m * w * 0.35 + fw * 0.5 }
|
|
1509
|
+
]
|
|
1510
|
+
];
|
|
1511
|
+
return { point, wings, apex };
|
|
1512
|
+
}
|
|
1478
1513
|
function divergeSideForHand(kind, stubDir, flipped) {
|
|
1479
1514
|
if (kind !== "left" && kind !== "right") return 0;
|
|
1480
1515
|
const s = (stubDir >= 0 ? 1 : -1) * (flipped ? -1 : 1);
|
|
@@ -1541,7 +1576,7 @@ function moduleFeatures(doc) {
|
|
|
1541
1576
|
if (parentLane === 0) {
|
|
1542
1577
|
const [from, to] = ext;
|
|
1543
1578
|
const far = Math.abs(to - sw.pos) >= Math.abs(from - sw.pos) ? to : from;
|
|
1544
|
-
const s = divergeSideForHand(sw.kind, far - sw.pos);
|
|
1579
|
+
const s = divergeSideForHand(sw.kind, far - sw.pos, sw.flipped);
|
|
1545
1580
|
sign = s !== 0 ? s : Math.sign(trk.lane) || 1;
|
|
1546
1581
|
} else {
|
|
1547
1582
|
sign = Math.sign(parentLane) || 1;
|
|
@@ -1656,15 +1691,43 @@ function moduleFeatures(doc) {
|
|
|
1656
1691
|
laneA: trackLane.get(x.tracks?.[0] ?? "") ?? 0,
|
|
1657
1692
|
laneB: trackLane.get(x.tracks?.[1] ?? "") ?? 1
|
|
1658
1693
|
}));
|
|
1694
|
+
const main2Lane = trackLane.has(MAIN2_TRACK_ID) ? trackLane.get(MAIN2_TRACK_ID) : null;
|
|
1695
|
+
const baseLanes = [
|
|
1696
|
+
0,
|
|
1697
|
+
main2Lane ?? (doubleMain ? 1 : 0),
|
|
1698
|
+
...extraTracks.map((t) => t.lane),
|
|
1699
|
+
...signals.map((s) => s.lane),
|
|
1700
|
+
...crossings.flatMap((x) => [x.laneA, x.laneB]),
|
|
1701
|
+
...crossovers.flatMap((x) => [x.fromLane, x.toLane])
|
|
1702
|
+
];
|
|
1703
|
+
let upLane = Math.max(...baseLanes, 0);
|
|
1704
|
+
let downLane = Math.min(...baseLanes, 0);
|
|
1659
1705
|
const branchConnectors = doc.endplates.filter(
|
|
1660
1706
|
(e) => e.id !== "A" && e.id !== "B" && e.at && !!e.trackId && (doc.tracks ?? []).some((t) => t.id === e.trackId)
|
|
1661
1707
|
).map((e) => {
|
|
1708
|
+
const trk = (doc.tracks ?? []).find((t) => t.id === e.trackId);
|
|
1662
1709
|
const sw = (doc.turnouts ?? []).find((t) => t.divergeTrack === e.trackId);
|
|
1710
|
+
const startPos = sw ? sw.pos : e.at.pos;
|
|
1711
|
+
const side = e.at.side === "down" ? "down" : "up";
|
|
1712
|
+
const lane = side === "down" ? --downLane : ++upLane;
|
|
1713
|
+
const runInches = pathLengthInches(trk.path) || Math.abs(e.at.pos - startPos) || FREEMO_ENDPLATE_WIDTH_MIN_INCHES;
|
|
1714
|
+
const toB = e.at.pos >= startPos;
|
|
1715
|
+
const fits = (p) => p >= 0 && p <= len;
|
|
1716
|
+
const ahead = startPos + runInches;
|
|
1717
|
+
const behind = startPos - runInches;
|
|
1718
|
+
const endPos = toB && fits(ahead) ? ahead : !toB && fits(behind) ? behind : fits(toB ? behind : ahead) ? toB ? behind : ahead : ahead;
|
|
1663
1719
|
return {
|
|
1664
1720
|
id: e.id,
|
|
1665
1721
|
label: e.label ?? e.id,
|
|
1666
|
-
|
|
1667
|
-
|
|
1722
|
+
name: trk.trackName ?? "",
|
|
1723
|
+
trackId: trk.id,
|
|
1724
|
+
kind: e.kind === "main" ? "main" : "branch",
|
|
1725
|
+
posFrac: clampFrac(startPos),
|
|
1726
|
+
fromLane: sw ? trackLane.get(sw.onTrack) ?? 0 : 0,
|
|
1727
|
+
side,
|
|
1728
|
+
lane,
|
|
1729
|
+
endFrac: clampFrac(endPos),
|
|
1730
|
+
lengthInches: runInches
|
|
1668
1731
|
};
|
|
1669
1732
|
});
|
|
1670
1733
|
const industries = (doc.industries ?? []).flatMap((ind) => {
|
|
@@ -1689,15 +1752,7 @@ function moduleFeatures(doc) {
|
|
|
1689
1752
|
};
|
|
1690
1753
|
});
|
|
1691
1754
|
});
|
|
1692
|
-
const
|
|
1693
|
-
const allLanes = [
|
|
1694
|
-
0,
|
|
1695
|
-
main2Lane ?? (doubleMain ? 1 : 0),
|
|
1696
|
-
...extraTracks.map((t) => t.lane),
|
|
1697
|
-
...signals.map((s) => s.lane),
|
|
1698
|
-
...crossings.flatMap((x) => [x.laneA, x.laneB]),
|
|
1699
|
-
...crossovers.flatMap((x) => [x.fromLane, x.toLane])
|
|
1700
|
-
];
|
|
1755
|
+
const allLanes = [...baseLanes, ...branchConnectors.map((b) => b.lane)];
|
|
1701
1756
|
const loop = isLoopDoc(doc);
|
|
1702
1757
|
const main2 = doc.tracks.find((t) => t.id === MAIN2_TRACK_ID);
|
|
1703
1758
|
const main2Positioned = !!main2 && (main2.fromPos != null || main2.toPos != null) && !loop;
|
|
@@ -2021,6 +2076,7 @@ exports.endplateLead = endplateLead;
|
|
|
2021
2076
|
exports.endplateTrackOffsetFor = endplateTrackOffsetFor;
|
|
2022
2077
|
exports.endplateTrackOffsetInches = endplateTrackOffsetInches;
|
|
2023
2078
|
exports.endplateWidthInches = endplateWidthInches;
|
|
2079
|
+
exports.frogCasting = frogCasting;
|
|
2024
2080
|
exports.frogNumberFromName = frogNumberFromName;
|
|
2025
2081
|
exports.fromSectionRelative = fromSectionRelative;
|
|
2026
2082
|
exports.geometryTurnDegrees = geometryTurnDegrees;
|
|
@@ -2038,6 +2094,7 @@ exports.moduleSections = moduleSections;
|
|
|
2038
2094
|
exports.nextId = nextId;
|
|
2039
2095
|
exports.parseXtpLibrary = parseXtpLibrary;
|
|
2040
2096
|
exports.partOutlineAtFrog = partOutlineAtFrog;
|
|
2097
|
+
exports.pathLengthInches = pathLengthInches;
|
|
2041
2098
|
exports.poseNeedsManual = poseNeedsManual;
|
|
2042
2099
|
exports.poseOverridesFromDoc = poseOverridesFromDoc;
|
|
2043
2100
|
exports.remapPos = remapPos;
|