@willcgage/module-schematic 0.51.0 → 0.53.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 +197 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +171 -6
- package/dist/index.d.ts +171 -6
- package/dist/index.js +190 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1092,6 +1092,195 @@ function buildCrossover(state) {
|
|
|
1092
1092
|
}
|
|
1093
1093
|
var RAIL_GAUGE_INCHES = 0.354;
|
|
1094
1094
|
var TURNOUT_LEAD_INCHES_PER_FROG = 0.482;
|
|
1095
|
+
var CODE55_RAIL_HEIGHT_INCHES = 0.055;
|
|
1096
|
+
var ATLAS_CODE55_N = [
|
|
1097
|
+
{
|
|
1098
|
+
id: "atlas-c55-n-5",
|
|
1099
|
+
manufacturer: "Atlas",
|
|
1100
|
+
line: "Code 55",
|
|
1101
|
+
scale: "N",
|
|
1102
|
+
name: "#5 Turnout",
|
|
1103
|
+
kind: "turnout",
|
|
1104
|
+
partNumbers: { left: "2050", right: "2051" },
|
|
1105
|
+
frogNumber: 5,
|
|
1106
|
+
lead: {
|
|
1107
|
+
inches: 5 * TURNOUT_LEAD_INCHES_PER_FROG,
|
|
1108
|
+
source: "derived",
|
|
1109
|
+
note: "scaled from the measured #7 by frog number \u2014 not measured, BUT now corroborated: a photo read of Will's physical 2050 puts points\u2192frog at ~2.4\u2033, i.e. 0.48/frog against the #7's 0.482. Replace with a real measurement when someone puts a rule on it."
|
|
1110
|
+
},
|
|
1111
|
+
overallLength: {
|
|
1112
|
+
inches: 6,
|
|
1113
|
+
source: "measured",
|
|
1114
|
+
note: "Will Gage, physical Atlas 2050 (#5 LH), end tie to end tie"
|
|
1115
|
+
},
|
|
1116
|
+
actualAngle: {
|
|
1117
|
+
deg: 11.25,
|
|
1118
|
+
source: "unverified",
|
|
1119
|
+
note: "CORROBORATED: XTrkCAD N-atlasn55.xtp gives 11.250152\xB0, and AnyRail-forum trial-and-error (glakedylan, 2012) gives 11.25\xB0. Theory atan(1/5) = 11.310\xB0. 11.25\xB0 is exactly 1/32 turn \u2014 Atlas appear to build to sectional angles."
|
|
1120
|
+
}
|
|
1121
|
+
},
|
|
1122
|
+
{
|
|
1123
|
+
id: "atlas-c55-n-7",
|
|
1124
|
+
manufacturer: "Atlas",
|
|
1125
|
+
line: "Code 55",
|
|
1126
|
+
scale: "N",
|
|
1127
|
+
name: "#7 Turnout",
|
|
1128
|
+
kind: "turnout",
|
|
1129
|
+
partNumbers: { left: "2052", right: "2053" },
|
|
1130
|
+
frogNumber: 7,
|
|
1131
|
+
lead: {
|
|
1132
|
+
inches: 3.375,
|
|
1133
|
+
source: "measured",
|
|
1134
|
+
note: "Steve Branton, physical Atlas code 55 #7, 3\u215C\u2033 points\u2192frog (#173)"
|
|
1135
|
+
},
|
|
1136
|
+
overallLength: {
|
|
1137
|
+
inches: 6,
|
|
1138
|
+
source: "measured",
|
|
1139
|
+
note: "Will Gage, physical Atlas 2052 (#7), end tie to end tie \u2014 the SAME 6\u2033 as the #5, which is what proves length is not a function of frog number"
|
|
1140
|
+
},
|
|
1141
|
+
actualAngle: {
|
|
1142
|
+
deg: 8.13,
|
|
1143
|
+
source: "unverified",
|
|
1144
|
+
note: "DISPUTED: XTrkCAD .xtp says 8.1818\xB0, AnyRail forum says 8.125\xB0, theory atan(1/7) = 8.130\xB0. The sources disagree, so theory is used here."
|
|
1145
|
+
}
|
|
1146
|
+
},
|
|
1147
|
+
{
|
|
1148
|
+
id: "atlas-c55-n-10",
|
|
1149
|
+
manufacturer: "Atlas",
|
|
1150
|
+
line: "Code 55",
|
|
1151
|
+
scale: "N",
|
|
1152
|
+
name: "#10 Turnout",
|
|
1153
|
+
kind: "turnout",
|
|
1154
|
+
partNumbers: { left: "2054", right: "2055" },
|
|
1155
|
+
frogNumber: 10,
|
|
1156
|
+
lead: {
|
|
1157
|
+
inches: 4.1875,
|
|
1158
|
+
source: "measured",
|
|
1159
|
+
note: "Will Gage, physical Atlas 2054 (#10): points at 9/16\u2033 from the end, frog at 4.75\u2033 \u21D2 4\xB3\u2044\u2081\u2086\u2033. THIS IS THE MEASUREMENT THAT REFUTED the lead-per-frog rule \u2014 it predicted 4.82\u2033, 13% over."
|
|
1160
|
+
},
|
|
1161
|
+
pointsOffset: {
|
|
1162
|
+
inches: 0.5625,
|
|
1163
|
+
source: "measured",
|
|
1164
|
+
note: "Will Gage, physical Atlas 2054 (#10) \u2014 end of tie strip to point tips"
|
|
1165
|
+
},
|
|
1166
|
+
overallLength: {
|
|
1167
|
+
inches: 8,
|
|
1168
|
+
source: "measured",
|
|
1169
|
+
note: "Will Gage, physical Atlas 2054 (#10), end tie to end tie"
|
|
1170
|
+
},
|
|
1171
|
+
actualAngle: {
|
|
1172
|
+
deg: 5.74,
|
|
1173
|
+
source: "unverified",
|
|
1174
|
+
note: "CORROBORATED: XTrkCAD .xtp gives 5.739\xB0, AnyRail forum 5.75\xB0 \u2014 they agree with each other and not with theory atan(1/10) = 5.711\xB0."
|
|
1175
|
+
}
|
|
1176
|
+
},
|
|
1177
|
+
{
|
|
1178
|
+
id: "atlas-c55-n-wye",
|
|
1179
|
+
manufacturer: "Atlas",
|
|
1180
|
+
line: "Code 55",
|
|
1181
|
+
scale: "N",
|
|
1182
|
+
name: "#2.5 Wye",
|
|
1183
|
+
kind: "wye",
|
|
1184
|
+
partNumbers: { single: "2056" },
|
|
1185
|
+
frogNumber: 2.5,
|
|
1186
|
+
lead: {
|
|
1187
|
+
inches: 2.5 * TURNOUT_LEAD_INCHES_PER_FROG,
|
|
1188
|
+
source: "derived",
|
|
1189
|
+
note: "scaled from the measured #7 by frog number \u2014 not measured"
|
|
1190
|
+
}
|
|
1191
|
+
},
|
|
1192
|
+
{
|
|
1193
|
+
id: "atlas-c55-n-curved-21-15",
|
|
1194
|
+
manufacturer: "Atlas",
|
|
1195
|
+
line: "Code 55",
|
|
1196
|
+
scale: "N",
|
|
1197
|
+
name: 'Curved Turnout 21\xBC" / 15"',
|
|
1198
|
+
kind: "curved-turnout",
|
|
1199
|
+
partNumbers: { left: "2058", right: "2059" },
|
|
1200
|
+
outerRadius: { inches: 21.25, source: "manufacturer", note: "Atlas product listing" },
|
|
1201
|
+
innerRadius: { inches: 15, source: "manufacturer", note: "Atlas product listing" }
|
|
1202
|
+
}
|
|
1203
|
+
];
|
|
1204
|
+
var BUILT_IN_TRACK_PARTS = [...ATLAS_CODE55_N];
|
|
1205
|
+
function trackPart(id, library = BUILT_IN_TRACK_PARTS) {
|
|
1206
|
+
return library.find((p) => p.id === id) ?? null;
|
|
1207
|
+
}
|
|
1208
|
+
function turnoutPartForSize(size, library = BUILT_IN_TRACK_PARTS) {
|
|
1209
|
+
const turnouts = library.filter((p) => p.kind === "turnout" && p.frogNumber != null);
|
|
1210
|
+
if (!turnouts.length) return null;
|
|
1211
|
+
return turnouts.reduce(
|
|
1212
|
+
(best, p) => Math.abs(p.frogNumber - size) < Math.abs(best.frogNumber - size) ? p : best
|
|
1213
|
+
);
|
|
1214
|
+
}
|
|
1215
|
+
function leadInchesForSize(size, library = BUILT_IN_TRACK_PARTS) {
|
|
1216
|
+
const part = turnoutPartForSize(size, library);
|
|
1217
|
+
if (part?.lead && part.frogNumber === size) return part.lead.inches;
|
|
1218
|
+
return size * TURNOUT_LEAD_INCHES_PER_FROG;
|
|
1219
|
+
}
|
|
1220
|
+
function parseXtpLibrary(text) {
|
|
1221
|
+
const parts = [];
|
|
1222
|
+
let cur = null;
|
|
1223
|
+
for (const raw of text.split(/\r?\n/)) {
|
|
1224
|
+
const line = raw.trim();
|
|
1225
|
+
if (!line || line.startsWith("#")) continue;
|
|
1226
|
+
if (line.startsWith("TURNOUT")) {
|
|
1227
|
+
const quoted = line.match(/"([^"]*)"/);
|
|
1228
|
+
const scale = line.split(/\s+/)[1];
|
|
1229
|
+
const title = quoted?.[1] ?? "";
|
|
1230
|
+
const bits = title.split(" ").map((s) => s.trim()).filter(Boolean);
|
|
1231
|
+
cur = {
|
|
1232
|
+
title,
|
|
1233
|
+
scale,
|
|
1234
|
+
manufacturer: bits[0],
|
|
1235
|
+
name: bits[1],
|
|
1236
|
+
partNumber: bits[2],
|
|
1237
|
+
ends: [],
|
|
1238
|
+
segments: []
|
|
1239
|
+
};
|
|
1240
|
+
continue;
|
|
1241
|
+
}
|
|
1242
|
+
if (!cur) continue;
|
|
1243
|
+
if (line === "END") {
|
|
1244
|
+
if (cur.ends.length || cur.segments.length) parts.push(cur);
|
|
1245
|
+
cur = null;
|
|
1246
|
+
continue;
|
|
1247
|
+
}
|
|
1248
|
+
const n = line.split(/\s+/);
|
|
1249
|
+
const num = (i) => Number(n[i]);
|
|
1250
|
+
if (n[0] === "E" && n.length >= 4) {
|
|
1251
|
+
cur.ends.push({ x: num(1), y: num(2), angleDeg: num(3) });
|
|
1252
|
+
} else if (n[0] === "S" && n.length >= 7) {
|
|
1253
|
+
cur.segments.push({ kind: "straight", x0: num(3), y0: num(4), x1: num(5), y1: num(6) });
|
|
1254
|
+
} else if (n[0] === "C" && n.length >= 8) {
|
|
1255
|
+
cur.segments.push({
|
|
1256
|
+
kind: "curve",
|
|
1257
|
+
radius: num(3),
|
|
1258
|
+
cx: num(4),
|
|
1259
|
+
cy: num(5),
|
|
1260
|
+
startDeg: num(6),
|
|
1261
|
+
extentDeg: num(7)
|
|
1262
|
+
});
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
return parts;
|
|
1266
|
+
}
|
|
1267
|
+
function samplePartSegments(segments, stepsPerCurve = 16) {
|
|
1268
|
+
return segments.map((s) => {
|
|
1269
|
+
if (s.kind === "straight") {
|
|
1270
|
+
return [
|
|
1271
|
+
{ x: s.x0, y: s.y0 },
|
|
1272
|
+
{ x: s.x1, y: s.y1 }
|
|
1273
|
+
];
|
|
1274
|
+
}
|
|
1275
|
+
const r = Math.abs(s.radius);
|
|
1276
|
+
const out = [];
|
|
1277
|
+
for (let i = 0; i <= stepsPerCurve; i++) {
|
|
1278
|
+
const a = (s.startDeg + s.extentDeg * i / stepsPerCurve) * Math.PI / 180;
|
|
1279
|
+
out.push({ x: s.cx + r * Math.sin(a), y: s.cy + r * Math.cos(a) });
|
|
1280
|
+
}
|
|
1281
|
+
return out;
|
|
1282
|
+
});
|
|
1283
|
+
}
|
|
1095
1284
|
function turnoutClosure(size, opts = {}) {
|
|
1096
1285
|
const N = size > 0 ? size : 6;
|
|
1097
1286
|
const g = opts.gaugeInches ?? RAIL_GAUGE_INCHES;
|
|
@@ -1621,6 +1810,9 @@ function poseOverridesFromDoc(doc) {
|
|
|
1621
1810
|
return out;
|
|
1622
1811
|
}
|
|
1623
1812
|
|
|
1813
|
+
exports.ATLAS_CODE55_N = ATLAS_CODE55_N;
|
|
1814
|
+
exports.BUILT_IN_TRACK_PARTS = BUILT_IN_TRACK_PARTS;
|
|
1815
|
+
exports.CODE55_RAIL_HEIGHT_INCHES = CODE55_RAIL_HEIGHT_INCHES;
|
|
1624
1816
|
exports.ENDPLATE_FASCIA_CLEAR_INCHES = ENDPLATE_FASCIA_CLEAR_INCHES;
|
|
1625
1817
|
exports.ENDPLATE_LEAD_INCHES = ENDPLATE_LEAD_INCHES;
|
|
1626
1818
|
exports.FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES = FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES;
|
|
@@ -1656,17 +1848,20 @@ exports.geometryTurnDegrees = geometryTurnDegrees;
|
|
|
1656
1848
|
exports.inchesToScaleFeet = inchesToScaleFeet;
|
|
1657
1849
|
exports.isLoopDoc = isLoopDoc;
|
|
1658
1850
|
exports.isTransitionTurnout = isTransitionTurnout;
|
|
1851
|
+
exports.leadInchesForSize = leadInchesForSize;
|
|
1659
1852
|
exports.moduleCenterline = moduleCenterline;
|
|
1660
1853
|
exports.moduleFeatures = moduleFeatures;
|
|
1661
1854
|
exports.moduleFootprint = moduleFootprint;
|
|
1662
1855
|
exports.moduleLengthFromSections = moduleLengthFromSections;
|
|
1663
1856
|
exports.moduleSections = moduleSections;
|
|
1664
1857
|
exports.nextId = nextId;
|
|
1858
|
+
exports.parseXtpLibrary = parseXtpLibrary;
|
|
1665
1859
|
exports.poseNeedsManual = poseNeedsManual;
|
|
1666
1860
|
exports.poseOverridesFromDoc = poseOverridesFromDoc;
|
|
1667
1861
|
exports.remapPos = remapPos;
|
|
1668
1862
|
exports.returnLoop = returnLoop;
|
|
1669
1863
|
exports.sampleBenchworkOutline = sampleBenchworkOutline;
|
|
1864
|
+
exports.samplePartSegments = samplePartSegments;
|
|
1670
1865
|
exports.samplePath = samplePath;
|
|
1671
1866
|
exports.scaleFeetToInches = scaleFeetToInches;
|
|
1672
1867
|
exports.sectionAdjacency = sectionAdjacency;
|
|
@@ -1683,7 +1878,9 @@ exports.sliceCenterline = sliceCenterline;
|
|
|
1683
1878
|
exports.stateToDoc = stateToDoc;
|
|
1684
1879
|
exports.toSectionRelative = toSectionRelative;
|
|
1685
1880
|
exports.trackMeetsEndplateIssues = trackMeetsEndplateIssues;
|
|
1881
|
+
exports.trackPart = trackPart;
|
|
1686
1882
|
exports.trackPath = trackPath;
|
|
1687
1883
|
exports.turnoutClosure = turnoutClosure;
|
|
1884
|
+
exports.turnoutPartForSize = turnoutPartForSize;
|
|
1688
1885
|
//# sourceMappingURL=index.cjs.map
|
|
1689
1886
|
//# sourceMappingURL=index.cjs.map
|