@willcgage/module-schematic 0.83.2 → 0.85.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 +214 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +143 -1
- package/dist/index.d.ts +143 -1
- package/dist/index.js +211 -40
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -869,6 +869,10 @@ function withPoses(endplates, overrides) {
|
|
|
869
869
|
(e) => overrides[e.id] ? { ...e, pose: overrides[e.id], poseAuthored: true } : e
|
|
870
870
|
);
|
|
871
871
|
}
|
|
872
|
+
function withEdges(endplates, edges) {
|
|
873
|
+
if (!edges) return endplates;
|
|
874
|
+
return endplates.map((e) => edges[e.id] ? { ...e, edge: edges[e.id] } : e);
|
|
875
|
+
}
|
|
872
876
|
function withWidths(endplates, widths, offsets = {}) {
|
|
873
877
|
return endplates.map((e) => {
|
|
874
878
|
const w = widths[e.id];
|
|
@@ -900,46 +904,49 @@ function stateToDoc(state, recordNumber) {
|
|
|
900
904
|
...state.loop && state.loopReturn === "main2" ? { loopReturn: "main2" } : {},
|
|
901
905
|
...state.mainsSwapped ? { mainsSwapped: true } : {},
|
|
902
906
|
endplates: withWidths(
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
907
|
+
withEdges(
|
|
908
|
+
withPoses(
|
|
909
|
+
[
|
|
910
|
+
...state.loop ? (
|
|
911
|
+
// Balloon loop: A is the entry. A standard endplate B on the balloon
|
|
912
|
+
// makes it an INTERCHANGE (second route connects at the loop, e.g.
|
|
913
|
+
// Seaford); configB "none" makes it a pure turnback.
|
|
914
|
+
[
|
|
915
|
+
{ id: "A", label: "Entry", tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: state.configA }] },
|
|
916
|
+
...state.configB !== "none" ? [{ id: "B", label: "Interchange", tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: state.configB }] }] : []
|
|
917
|
+
]
|
|
918
|
+
) : [
|
|
919
|
+
{ id: "A", label: "West", tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: state.configA }] },
|
|
920
|
+
// ⚠️ `configB: "none"` means the module HAS NO FAR ENDPLATE, and
|
|
921
|
+
// that is not loop-only (#184). An *end of the line* or a *pocket*
|
|
922
|
+
// presents one conforming face and the track simply stops. The
|
|
923
|
+
// standard governs the ends a module offers for joining; it never
|
|
924
|
+
// required a module to offer two. This used to coerce "none" to
|
|
925
|
+
// "single" and emit a B regardless, so a single-ended module was
|
|
926
|
+
// impossible to author.
|
|
927
|
+
...state.configB !== "none" ? [
|
|
928
|
+
{
|
|
929
|
+
id: "B",
|
|
930
|
+
label: "East",
|
|
931
|
+
tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: state.configB }]
|
|
932
|
+
}
|
|
933
|
+
] : []
|
|
934
|
+
],
|
|
935
|
+
// Branch endplates C, D, … — junction connections at pos, off one side
|
|
936
|
+
// (#170). A set can carry several (e.g. a second railroad through).
|
|
937
|
+
...state.branches.map((b, i) => ({
|
|
938
|
+
id: String.fromCharCode(67 + i),
|
|
939
|
+
// C, D, E…
|
|
940
|
+
label: b.label || `Branch ${i + 1}`,
|
|
941
|
+
tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: b.config }],
|
|
942
|
+
at: { pos: b.pos, side: b.side },
|
|
943
|
+
kind: b.kind ?? "branch",
|
|
944
|
+
...b.trackId ? { trackId: b.trackId } : {}
|
|
945
|
+
}))
|
|
929
946
|
],
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
id: String.fromCharCode(67 + i),
|
|
934
|
-
// C, D, E…
|
|
935
|
-
label: b.label || `Branch ${i + 1}`,
|
|
936
|
-
tracks: [{ trackId: MAIN_TRACK_ID, lane: 0, config: b.config }],
|
|
937
|
-
at: { pos: b.pos, side: b.side },
|
|
938
|
-
kind: b.kind ?? "branch",
|
|
939
|
-
...b.trackId ? { trackId: b.trackId } : {}
|
|
940
|
-
}))
|
|
941
|
-
],
|
|
942
|
-
state.poseOverrides
|
|
947
|
+
state.poseOverrides
|
|
948
|
+
),
|
|
949
|
+
state.endplateEdges
|
|
943
950
|
),
|
|
944
951
|
state.endplateWidths,
|
|
945
952
|
state.endplateTrackOffsets
|
|
@@ -1135,7 +1142,15 @@ function docToState(doc, fallbackLength, moduleTracks = []) {
|
|
|
1135
1142
|
const poseOverrides = poseOverridesFromDoc(d);
|
|
1136
1143
|
const endplateWidths = {};
|
|
1137
1144
|
const endplateTrackOffsets = {};
|
|
1145
|
+
const endplateEdges = {};
|
|
1138
1146
|
for (const e of d.endplates ?? []) {
|
|
1147
|
+
if (e.edge && Number.isFinite(e.edge.index) && e.edge.index >= 0)
|
|
1148
|
+
endplateEdges[e.id] = {
|
|
1149
|
+
index: Math.trunc(e.edge.index),
|
|
1150
|
+
...e.edge.section ? { section: e.edge.section } : {},
|
|
1151
|
+
...Number.isFinite(e.edge.fromT) ? { fromT: e.edge.fromT } : {},
|
|
1152
|
+
...Number.isFinite(e.edge.toT) ? { toT: e.edge.toT } : {}
|
|
1153
|
+
};
|
|
1139
1154
|
if (typeof e.widthInches === "number" && e.widthInches > 0)
|
|
1140
1155
|
endplateWidths[e.id] = e.widthInches;
|
|
1141
1156
|
if (typeof e.trackOffsetInches === "number" && Number.isFinite(e.trackOffsetInches))
|
|
@@ -1186,6 +1201,7 @@ function docToState(doc, fallbackLength, moduleTracks = []) {
|
|
|
1186
1201
|
flexByTrack,
|
|
1187
1202
|
endplateWidths,
|
|
1188
1203
|
endplateTrackOffsets,
|
|
1204
|
+
endplateEdges,
|
|
1189
1205
|
outline,
|
|
1190
1206
|
outlineInner,
|
|
1191
1207
|
sectionBreaks: (d.sectionBreaks ?? []).filter((n) => Number.isFinite(n)).map((n) => sc(n)),
|
|
@@ -2126,6 +2142,107 @@ function turnoutClosure(size, opts = {}) {
|
|
|
2126
2142
|
}
|
|
2127
2143
|
};
|
|
2128
2144
|
}
|
|
2145
|
+
function partGeometryGap(part) {
|
|
2146
|
+
if (part.kind === "flex") return null;
|
|
2147
|
+
if (part.kind === "crossover")
|
|
2148
|
+
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";
|
|
2149
|
+
if (part.kind === "crossing") return "crossing geometry is not modelled yet";
|
|
2150
|
+
if (part.kind === "curved-turnout")
|
|
2151
|
+
return "a curved turnout needs both radii AND its points/frog landmarks; only the radii are published";
|
|
2152
|
+
if (!part.pointsOffset)
|
|
2153
|
+
return "no points offset \u2014 without it there is nowhere for the diverging route to begin";
|
|
2154
|
+
if (!part.overallLength) return "no overall length \u2014 the part has no end to put a joint on";
|
|
2155
|
+
if (part.frogNumber == null) return "no frog number \u2014 the diverging angle is unknown";
|
|
2156
|
+
return null;
|
|
2157
|
+
}
|
|
2158
|
+
function partGeometry(part, library = BUILT_IN_TRACK_PARTS) {
|
|
2159
|
+
if (partGeometryGap(part)) return null;
|
|
2160
|
+
if (part.kind === "flex") {
|
|
2161
|
+
return {
|
|
2162
|
+
joints: [
|
|
2163
|
+
{ id: "a", role: "throat", x: 0, y: 0, angleDeg: 180 },
|
|
2164
|
+
{ id: "b", role: "through", x: 0, y: 0, angleDeg: 0 }
|
|
2165
|
+
],
|
|
2166
|
+
routes: [["a", "b"]],
|
|
2167
|
+
source: "derived",
|
|
2168
|
+
divergingEndMeasured: false
|
|
2169
|
+
};
|
|
2170
|
+
}
|
|
2171
|
+
const N = part.frogNumber;
|
|
2172
|
+
const points = part.pointsOffset;
|
|
2173
|
+
const overall = part.overallLength;
|
|
2174
|
+
const frog = part.frogOffset;
|
|
2175
|
+
const lead = part.lead?.inches ?? (frog ? frog.inches - points.inches : void 0);
|
|
2176
|
+
if (lead == null || !(lead > 0)) return null;
|
|
2177
|
+
const isWye = part.kind === "wye";
|
|
2178
|
+
const effN = isWye ? N * 2 : N;
|
|
2179
|
+
const closure = turnoutClosure(effN, { leadInches: lead });
|
|
2180
|
+
const divergingEnd = () => {
|
|
2181
|
+
const frogX = frog ? frog.inches : points.inches + lead;
|
|
2182
|
+
const slope = closure.frogSlope;
|
|
2183
|
+
const dir = 1 / Math.hypot(1, slope);
|
|
2184
|
+
if (part.divergingLength) {
|
|
2185
|
+
const L = part.divergingLength.inches;
|
|
2186
|
+
return {
|
|
2187
|
+
x: frogX + L * dir,
|
|
2188
|
+
y: closure.offsetAt(frogX - points.inches) + L * slope * dir,
|
|
2189
|
+
measured: true
|
|
2190
|
+
};
|
|
2191
|
+
}
|
|
2192
|
+
return {
|
|
2193
|
+
x: overall.inches,
|
|
2194
|
+
y: closure.offsetAt(overall.inches - points.inches),
|
|
2195
|
+
measured: false
|
|
2196
|
+
};
|
|
2197
|
+
};
|
|
2198
|
+
const weakest = (...ds) => {
|
|
2199
|
+
const rank = ["measured", "manufacturer", "derived", "unverified"];
|
|
2200
|
+
let worst = 0;
|
|
2201
|
+
for (const d of ds) if (d) worst = Math.max(worst, rank.indexOf(d.source));
|
|
2202
|
+
return rank[worst];
|
|
2203
|
+
};
|
|
2204
|
+
const de = divergingEnd();
|
|
2205
|
+
const legAngle = Math.atan(closure.frogSlope) * 180 / Math.PI;
|
|
2206
|
+
if (isWye) {
|
|
2207
|
+
return {
|
|
2208
|
+
joints: [
|
|
2209
|
+
{ id: "throat", role: "throat", x: 0, y: 0, angleDeg: 180 },
|
|
2210
|
+
{ id: "legA", role: "diverge", x: de.x, y: de.y, angleDeg: legAngle },
|
|
2211
|
+
{ id: "legB", role: "divergeB", x: de.x, y: -de.y, angleDeg: -legAngle }
|
|
2212
|
+
],
|
|
2213
|
+
routes: [
|
|
2214
|
+
["throat", "legA"],
|
|
2215
|
+
["throat", "legB"]
|
|
2216
|
+
],
|
|
2217
|
+
source: weakest(points, overall, frog, part.divergingLength),
|
|
2218
|
+
divergingEndMeasured: de.measured
|
|
2219
|
+
};
|
|
2220
|
+
}
|
|
2221
|
+
return {
|
|
2222
|
+
joints: [
|
|
2223
|
+
{ id: "throat", role: "throat", x: 0, y: 0, angleDeg: 180 },
|
|
2224
|
+
{ id: "through", role: "through", x: overall.inches, y: 0, angleDeg: 0 },
|
|
2225
|
+
{ id: "diverge", role: "diverge", x: de.x, y: de.y, angleDeg: legAngle }
|
|
2226
|
+
],
|
|
2227
|
+
routes: [
|
|
2228
|
+
["throat", "through"],
|
|
2229
|
+
["throat", "diverge"]
|
|
2230
|
+
],
|
|
2231
|
+
source: weakest(points, overall, frog, part.divergingLength),
|
|
2232
|
+
divergingEndMeasured: de.measured
|
|
2233
|
+
};
|
|
2234
|
+
}
|
|
2235
|
+
function partsPlaceable(library = BUILT_IN_TRACK_PARTS) {
|
|
2236
|
+
const placeable = [];
|
|
2237
|
+
const blocked = [];
|
|
2238
|
+
for (const p of library) {
|
|
2239
|
+
const why = partGeometryGap(p);
|
|
2240
|
+
if (why) blocked.push({ part: p, why });
|
|
2241
|
+
else if (partGeometry(p, library)) placeable.push(p);
|
|
2242
|
+
else blocked.push({ part: p, why: "dimensions present but inconsistent" });
|
|
2243
|
+
}
|
|
2244
|
+
return { placeable, blocked };
|
|
2245
|
+
}
|
|
2129
2246
|
function frogCasting(cl, opts = {}) {
|
|
2130
2247
|
const g = opts.gaugeInches ?? RAIL_GAUGE_INCHES;
|
|
2131
2248
|
const w = opts.reachInches ?? g * 1.5;
|
|
@@ -2431,6 +2548,45 @@ function moduleFeatures(doc) {
|
|
|
2431
2548
|
laneMax: Math.max(...allLanes)
|
|
2432
2549
|
};
|
|
2433
2550
|
}
|
|
2551
|
+
function endplateEdgePose(outline, edge) {
|
|
2552
|
+
if (!outline || outline.length < 3) return null;
|
|
2553
|
+
const n = outline.length;
|
|
2554
|
+
const i = Math.trunc(edge.index);
|
|
2555
|
+
if (!Number.isFinite(i) || i < 0 || i >= n) return null;
|
|
2556
|
+
const p0 = outline[i];
|
|
2557
|
+
const p1 = outline[(i + 1) % n];
|
|
2558
|
+
if (p0.bulge) return null;
|
|
2559
|
+
const t0 = Math.max(0, Math.min(1, edge.fromT ?? 0));
|
|
2560
|
+
const t1 = Math.max(0, Math.min(1, edge.toT ?? 1));
|
|
2561
|
+
const a = { x: p0.x + (p1.x - p0.x) * Math.min(t0, t1), y: p0.y + (p1.y - p0.y) * Math.min(t0, t1) };
|
|
2562
|
+
const b = { x: p0.x + (p1.x - p0.x) * Math.max(t0, t1), y: p0.y + (p1.y - p0.y) * Math.max(t0, t1) };
|
|
2563
|
+
const w = Math.hypot(b.x - a.x, b.y - a.y);
|
|
2564
|
+
if (!(w > 0)) return null;
|
|
2565
|
+
let cx = 0;
|
|
2566
|
+
let cy = 0;
|
|
2567
|
+
for (const v of outline) {
|
|
2568
|
+
cx += v.x;
|
|
2569
|
+
cy += v.y;
|
|
2570
|
+
}
|
|
2571
|
+
cx /= n;
|
|
2572
|
+
cy /= n;
|
|
2573
|
+
const mid = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };
|
|
2574
|
+
const ex = (b.x - a.x) / w;
|
|
2575
|
+
const ey = (b.y - a.y) / w;
|
|
2576
|
+
let nx = ey;
|
|
2577
|
+
let ny = -ex;
|
|
2578
|
+
if ((mid.x - cx) * nx + (mid.y - cy) * ny < 0) {
|
|
2579
|
+
nx = -nx;
|
|
2580
|
+
ny = -ny;
|
|
2581
|
+
}
|
|
2582
|
+
return {
|
|
2583
|
+
x: mid.x,
|
|
2584
|
+
y: mid.y,
|
|
2585
|
+
heading: norm360(Math.atan2(ny, nx) * 180 / Math.PI),
|
|
2586
|
+
widthInches: w,
|
|
2587
|
+
face: [a, b]
|
|
2588
|
+
};
|
|
2589
|
+
}
|
|
2434
2590
|
function returnLoop(shape, opts) {
|
|
2435
2591
|
const L = Math.max(1, opts.leadInches);
|
|
2436
2592
|
const R = Math.max(1, opts.radius);
|
|
@@ -2534,6 +2690,21 @@ function deriveEndplatePoses(geo) {
|
|
|
2534
2690
|
const half = geo.trackHalfSpacingInches ?? 1;
|
|
2535
2691
|
const cfg = (i) => geo.endplateConfigs?.[i] === "double" ? "double" : "single";
|
|
2536
2692
|
const withOverride = (p) => {
|
|
2693
|
+
const bound = geo.endplateEdges?.[p.id];
|
|
2694
|
+
if (bound) {
|
|
2695
|
+
const outline = (bound.section ? geo.sections?.find((s) => s.id === bound.section)?.outline : geo.outline) ?? geo.outline;
|
|
2696
|
+
const e = endplateEdgePose(outline, bound);
|
|
2697
|
+
if (e)
|
|
2698
|
+
return {
|
|
2699
|
+
...p,
|
|
2700
|
+
x: e.x,
|
|
2701
|
+
y: e.y,
|
|
2702
|
+
heading: e.heading,
|
|
2703
|
+
widthInches: e.widthInches,
|
|
2704
|
+
face: e.face,
|
|
2705
|
+
boundToEdge: true
|
|
2706
|
+
};
|
|
2707
|
+
}
|
|
2537
2708
|
const o = geo.poseOverrides?.[p.id];
|
|
2538
2709
|
return o ? { ...p, x: o.x, y: o.y, heading: norm360(o.heading), manual: true } : p;
|
|
2539
2710
|
};
|
|
@@ -2705,6 +2876,6 @@ function poseOverridesFromDoc(doc) {
|
|
|
2705
2876
|
return out;
|
|
2706
2877
|
}
|
|
2707
2878
|
|
|
2708
|
-
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, CLEARANCE_SPACING_INCHES, CODE55_RAIL_HEIGHT_INCHES, DEFAULT_FLEX_PART_ID, ENDPLATE_FASCIA_CLEAR_INCHES, ENDPLATE_LEAD_INCHES, FAST_TRACKS_N_ME55, FAST_TRACKS_N_ME55_CROSSOVERS, FLEX_TRACK_PARTS, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, MAIN2_TRACK_ID, MAIN_TRACK_ID, N_CAR_LENGTH_INCHES, N_SCALE_RATIO, PINCH_EASE_INCHES, RAIL_GAUGE_INCHES, TIE_HALF_LENGTH_INCHES, TURNOUT_LEAD_INCHES_PER_FROG, WHOLE_MODULE_SECTION_ID, asModuleSchematic, assessSectionEnd, assessSectionJoint, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, clearancePointPastFrogInches, crossoverPinches, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateCentreOffsetInches, endplateFaceSegments, endplateLead, endplateTrackOffsetInches, endplateWidthInches, flexPartFor, flexParts, flexPieces, flexUsage, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, hasNoFarEndplate, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, laneOffsetAt, leadInchesForSize, maxFlexPieceInches, mergeImportedParts, mergeStoredParts, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, parseXtpLibrary, partExtent, partExtentForSize, partOutlineAtFrog, pastFrogInchesForSize, pathLengthInches, poseNeedsManual, poseOverridesFromDoc, remapPos, resizeFlexPiece, returnLoop, sampleBenchworkOutline, samplePartSegments, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, spanOverhang, stateToDoc, storedPartToTrackPart, toSectionRelative, trackMeetsEndplateIssues, trackPart, trackPath, turnoutClosure, turnoutFacing, turnoutOccupiedSpan, turnoutPartForSize, usableCapacity };
|
|
2879
|
+
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, CLEARANCE_SPACING_INCHES, CODE55_RAIL_HEIGHT_INCHES, DEFAULT_FLEX_PART_ID, ENDPLATE_FASCIA_CLEAR_INCHES, ENDPLATE_LEAD_INCHES, FAST_TRACKS_N_ME55, FAST_TRACKS_N_ME55_CROSSOVERS, FLEX_TRACK_PARTS, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, MAIN2_TRACK_ID, MAIN_TRACK_ID, N_CAR_LENGTH_INCHES, N_SCALE_RATIO, PINCH_EASE_INCHES, RAIL_GAUGE_INCHES, TIE_HALF_LENGTH_INCHES, TURNOUT_LEAD_INCHES_PER_FROG, WHOLE_MODULE_SECTION_ID, asModuleSchematic, assessSectionEnd, assessSectionJoint, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, clearancePointPastFrogInches, crossoverPinches, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateCentreOffsetInches, endplateEdgePose, endplateFaceSegments, endplateLead, endplateTrackOffsetInches, endplateWidthInches, flexPartFor, flexParts, flexPieces, flexUsage, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, hasNoFarEndplate, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, laneOffsetAt, leadInchesForSize, maxFlexPieceInches, mergeImportedParts, mergeStoredParts, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, parseXtpLibrary, partExtent, partExtentForSize, partGeometry, partGeometryGap, partOutlineAtFrog, partsPlaceable, pastFrogInchesForSize, pathLengthInches, poseNeedsManual, poseOverridesFromDoc, remapPos, resizeFlexPiece, returnLoop, sampleBenchworkOutline, samplePartSegments, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, spanOverhang, stateToDoc, storedPartToTrackPart, toSectionRelative, trackMeetsEndplateIssues, trackPart, trackPath, turnoutClosure, turnoutFacing, turnoutOccupiedSpan, turnoutPartForSize, usableCapacity };
|
|
2709
2880
|
//# sourceMappingURL=index.js.map
|
|
2710
2881
|
//# sourceMappingURL=index.js.map
|