@willcgage/module-schematic 0.32.0 → 0.34.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 +51 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.js +51 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -438,6 +438,19 @@ declare function sectionBreaksFromSections(doc: {
|
|
|
438
438
|
* a module like One Mile expressible: straight boards with two 24″ curved ones
|
|
439
439
|
* in the middle, which no single module-level geometry can describe (#108).
|
|
440
440
|
* Returns [] when the module has no sections with lengths. */
|
|
441
|
+
/** Where the chained boards finish, and on what heading — computed from the
|
|
442
|
+
* section geometry itself rather than read off the sampled polyline. A curve
|
|
443
|
+
* is sampled in steps, so the last chord lags the true tangent by half a step
|
|
444
|
+
* (a 90° board sampled 12 ways reads 86.25°). That error would land straight
|
|
445
|
+
* in endplate B's heading and throw off face-to-face snapping, so the exact
|
|
446
|
+
* value is accumulated here instead. Null when there are no sections. */
|
|
447
|
+
declare function sectionedEndPose(doc: {
|
|
448
|
+
sections?: SchematicSection[] | null;
|
|
449
|
+
} | null | undefined): {
|
|
450
|
+
x: number;
|
|
451
|
+
y: number;
|
|
452
|
+
heading: number;
|
|
453
|
+
} | null;
|
|
441
454
|
declare function sectionedCenterline(doc: {
|
|
442
455
|
sections?: SchematicSection[] | null;
|
|
443
456
|
} | null | undefined): BenchworkPoint[];
|
|
@@ -949,6 +962,10 @@ interface ModuleGeometryInput {
|
|
|
949
962
|
/** Half the spacing between the two tracks of a double endplate (Free-mo ≈ 1",
|
|
950
963
|
* Free-moN ≈ 9/16"). */
|
|
951
964
|
trackHalfSpacingInches?: number;
|
|
965
|
+
/** The module's sections. When present they define the module's real shape,
|
|
966
|
+
* so endplate B lands at the end of the CHAINED boards rather than where a
|
|
967
|
+
* single module-level geometry would have put it (#108). */
|
|
968
|
+
sections?: SchematicSection[] | null;
|
|
952
969
|
}
|
|
953
970
|
/** Signed turn a module applies to the through track (CCW/left positive). */
|
|
954
971
|
declare function geometryTurnDegrees(geometryType?: string | null, geometryDegrees?: number | null): number;
|
|
@@ -971,4 +988,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
971
988
|
heading: number;
|
|
972
989
|
}>;
|
|
973
990
|
|
|
974
|
-
export { type BenchworkPoint, type BranchConnector, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, type EndplateWidthIssue, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, type GeometryType, type IndustryLabelMode, type IndustrySpot, MAIN2_TRACK_ID, MAIN_TRACK_ID, type ModuleFeatures, type ModuleFootprint, type ModuleFootprintInput, type ModuleGeometryInput, type ModuleSchematicDoc, type ModuleTrackRow, N_CAR_LENGTH_INCHES, N_SCALE_RATIO, type OutlineFace, type SchematicBlock, type SchematicControlPoint, type SchematicCrossing, type SchematicEndplate, type SchematicEndplateTrack, type SchematicIndustry, type SchematicSection, type SchematicSignal, type SchematicTrack, type SchematicTurnout, type SectionAdjacency, type SectionFootprint, type SignalFacing, type SignalSide, type TrackConfig, type TrackRole, type TurnoutKind, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionedCenterline, sliceCenterline, stateToDoc, trackPath };
|
|
991
|
+
export { type BenchworkPoint, type BranchConnector, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, type EndplateWidthIssue, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, type GeometryType, type IndustryLabelMode, type IndustrySpot, MAIN2_TRACK_ID, MAIN_TRACK_ID, type ModuleFeatures, type ModuleFootprint, type ModuleFootprintInput, type ModuleGeometryInput, type ModuleSchematicDoc, type ModuleTrackRow, N_CAR_LENGTH_INCHES, N_SCALE_RATIO, type OutlineFace, type SchematicBlock, type SchematicControlPoint, type SchematicCrossing, type SchematicEndplate, type SchematicEndplateTrack, type SchematicIndustry, type SchematicSection, type SchematicSignal, type SchematicTrack, type SchematicTurnout, type SectionAdjacency, type SectionFootprint, type SignalFacing, type SignalSide, type TrackConfig, type TrackRole, type TurnoutKind, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionedCenterline, sectionedEndPose, sliceCenterline, stateToDoc, trackPath };
|
package/dist/index.d.ts
CHANGED
|
@@ -438,6 +438,19 @@ declare function sectionBreaksFromSections(doc: {
|
|
|
438
438
|
* a module like One Mile expressible: straight boards with two 24″ curved ones
|
|
439
439
|
* in the middle, which no single module-level geometry can describe (#108).
|
|
440
440
|
* Returns [] when the module has no sections with lengths. */
|
|
441
|
+
/** Where the chained boards finish, and on what heading — computed from the
|
|
442
|
+
* section geometry itself rather than read off the sampled polyline. A curve
|
|
443
|
+
* is sampled in steps, so the last chord lags the true tangent by half a step
|
|
444
|
+
* (a 90° board sampled 12 ways reads 86.25°). That error would land straight
|
|
445
|
+
* in endplate B's heading and throw off face-to-face snapping, so the exact
|
|
446
|
+
* value is accumulated here instead. Null when there are no sections. */
|
|
447
|
+
declare function sectionedEndPose(doc: {
|
|
448
|
+
sections?: SchematicSection[] | null;
|
|
449
|
+
} | null | undefined): {
|
|
450
|
+
x: number;
|
|
451
|
+
y: number;
|
|
452
|
+
heading: number;
|
|
453
|
+
} | null;
|
|
441
454
|
declare function sectionedCenterline(doc: {
|
|
442
455
|
sections?: SchematicSection[] | null;
|
|
443
456
|
} | null | undefined): BenchworkPoint[];
|
|
@@ -949,6 +962,10 @@ interface ModuleGeometryInput {
|
|
|
949
962
|
/** Half the spacing between the two tracks of a double endplate (Free-mo ≈ 1",
|
|
950
963
|
* Free-moN ≈ 9/16"). */
|
|
951
964
|
trackHalfSpacingInches?: number;
|
|
965
|
+
/** The module's sections. When present they define the module's real shape,
|
|
966
|
+
* so endplate B lands at the end of the CHAINED boards rather than where a
|
|
967
|
+
* single module-level geometry would have put it (#108). */
|
|
968
|
+
sections?: SchematicSection[] | null;
|
|
952
969
|
}
|
|
953
970
|
/** Signed turn a module applies to the through track (CCW/left positive). */
|
|
954
971
|
declare function geometryTurnDegrees(geometryType?: string | null, geometryDegrees?: number | null): number;
|
|
@@ -971,4 +988,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
971
988
|
heading: number;
|
|
972
989
|
}>;
|
|
973
990
|
|
|
974
|
-
export { type BenchworkPoint, type BranchConnector, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, type EndplateWidthIssue, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, type GeometryType, type IndustryLabelMode, type IndustrySpot, MAIN2_TRACK_ID, MAIN_TRACK_ID, type ModuleFeatures, type ModuleFootprint, type ModuleFootprintInput, type ModuleGeometryInput, type ModuleSchematicDoc, type ModuleTrackRow, N_CAR_LENGTH_INCHES, N_SCALE_RATIO, type OutlineFace, type SchematicBlock, type SchematicControlPoint, type SchematicCrossing, type SchematicEndplate, type SchematicEndplateTrack, type SchematicIndustry, type SchematicSection, type SchematicSignal, type SchematicTrack, type SchematicTurnout, type SectionAdjacency, type SectionFootprint, type SignalFacing, type SignalSide, type TrackConfig, type TrackRole, type TurnoutKind, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionedCenterline, sliceCenterline, stateToDoc, trackPath };
|
|
991
|
+
export { type BenchworkPoint, type BranchConnector, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, type EndplateWidthIssue, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, type GeometryType, type IndustryLabelMode, type IndustrySpot, MAIN2_TRACK_ID, MAIN_TRACK_ID, type ModuleFeatures, type ModuleFootprint, type ModuleFootprintInput, type ModuleGeometryInput, type ModuleSchematicDoc, type ModuleTrackRow, N_CAR_LENGTH_INCHES, N_SCALE_RATIO, type OutlineFace, type SchematicBlock, type SchematicControlPoint, type SchematicCrossing, type SchematicEndplate, type SchematicEndplateTrack, type SchematicIndustry, type SchematicSection, type SchematicSignal, type SchematicTrack, type SchematicTurnout, type SectionAdjacency, type SectionFootprint, type SignalFacing, type SignalSide, type TrackConfig, type TrackRole, type TurnoutKind, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionedCenterline, sectionedEndPose, sliceCenterline, stateToDoc, trackPath };
|
package/dist/index.js
CHANGED
|
@@ -209,6 +209,24 @@ function sectionBreaksFromSections(doc) {
|
|
|
209
209
|
const spans = sectionSpans(doc);
|
|
210
210
|
return spans.slice(0, -1).map((sp) => sp.toPos);
|
|
211
211
|
}
|
|
212
|
+
function sectionedEndPose(doc) {
|
|
213
|
+
const secs = moduleSections(doc).filter(
|
|
214
|
+
(sec) => typeof sec.lengthInches === "number" && sec.lengthInches > 0
|
|
215
|
+
);
|
|
216
|
+
if (!secs.length) return null;
|
|
217
|
+
let ox = 0;
|
|
218
|
+
let oy = 0;
|
|
219
|
+
let heading = 0;
|
|
220
|
+
for (const sec of secs) {
|
|
221
|
+
const local = sectionCenterlineLocal(sec);
|
|
222
|
+
const c = Math.cos(heading * DEG_FP);
|
|
223
|
+
const sn = Math.sin(heading * DEG_FP);
|
|
224
|
+
ox += local.endX * c - local.endY * sn;
|
|
225
|
+
oy += local.endX * sn + local.endY * c;
|
|
226
|
+
heading += local.endHeadingDeg;
|
|
227
|
+
}
|
|
228
|
+
return { x: ox, y: oy, heading };
|
|
229
|
+
}
|
|
212
230
|
function sectionedCenterline(doc) {
|
|
213
231
|
const secs = moduleSections(doc).filter(
|
|
214
232
|
(sec) => typeof sec.lengthInches === "number" && sec.lengthInches > 0
|
|
@@ -535,18 +553,22 @@ function main1Track(state) {
|
|
|
535
553
|
}
|
|
536
554
|
function main2Track(state) {
|
|
537
555
|
const bothDouble = state.configA === "double" && state.configB === "double";
|
|
538
|
-
const
|
|
556
|
+
const sws = state.turnouts.filter((t) => isTransitionTurnout(t) && t.divergeTrack === MAIN2_TRACK_ID).sort((a, b) => a.pos - b.pos);
|
|
539
557
|
const lane = state.mainsSwapped ? 0 : 1;
|
|
540
|
-
if (bothDouble || !
|
|
558
|
+
if (bothDouble || !sws.length) {
|
|
541
559
|
return { id: MAIN2_TRACK_ID, role: "main", lane, from: "A", to: "B" };
|
|
542
560
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
);
|
|
561
|
+
const track = (fromPos, toPos) => ({
|
|
562
|
+
id: MAIN2_TRACK_ID,
|
|
563
|
+
role: "main",
|
|
564
|
+
lane,
|
|
565
|
+
fromPos,
|
|
566
|
+
toPos
|
|
567
|
+
});
|
|
568
|
+
if (state.configA === "double") return track(0, sws[0].pos);
|
|
569
|
+
if (state.configB === "double") return track(sws[0].pos, state.lengthInches);
|
|
570
|
+
if (sws.length >= 2) return track(sws[0].pos, sws[sws.length - 1].pos);
|
|
571
|
+
return track(sws[0].pos, state.lengthInches);
|
|
550
572
|
}
|
|
551
573
|
function buildTransition(state) {
|
|
552
574
|
const aDouble = state.configA === "double";
|
|
@@ -664,7 +686,12 @@ function stateToDoc(state, recordNumber) {
|
|
|
664
686
|
// double) Main 2 only runs from the mainline turnout to the double end —
|
|
665
687
|
// the turnout that diverges to main2 is the single source of truth for
|
|
666
688
|
// where the transition sits (fd#175 / FMN-0038).
|
|
667
|
-
|
|
689
|
+
// …and on a module that's SINGLE at both ends but goes double in the
|
|
690
|
+
// middle to form a siding: the turnouts are what make Main 2 exist, so a
|
|
691
|
+
// pair of them is reason enough to emit it (#118). Without this the
|
|
692
|
+
// second main simply wasn't in the doc, and neither the board nor the
|
|
693
|
+
// dispatcher panel could draw it.
|
|
694
|
+
...!state.loop && (state.configA === "double" || state.configB === "double" || state.turnouts.some((t) => isTransitionTurnout(t) && t.divergeTrack === MAIN2_TRACK_ID)) ? [main2Track(state)] : [],
|
|
668
695
|
...state.loop && state.loopReturn === "main2" ? [{ id: MAIN2_TRACK_ID, role: "main", lane: 1, fromPos: 0, toPos: state.lengthInches }] : [],
|
|
669
696
|
...state.extraTracks.map((t) => ({
|
|
670
697
|
id: t.id,
|
|
@@ -1281,7 +1308,19 @@ function deriveEndplatePoses(geo) {
|
|
|
1281
1308
|
})
|
|
1282
1309
|
);
|
|
1283
1310
|
const noB = geo.geometryType === "dead_end";
|
|
1284
|
-
|
|
1311
|
+
const end = sectionedEndPose({ sections: geo.sections });
|
|
1312
|
+
if (!noB && end) {
|
|
1313
|
+
poses.push(
|
|
1314
|
+
withOverride({
|
|
1315
|
+
id: "B",
|
|
1316
|
+
x: end.x,
|
|
1317
|
+
y: end.y,
|
|
1318
|
+
heading: norm360(end.heading),
|
|
1319
|
+
trackConfig: cfg(1),
|
|
1320
|
+
trackOffsets: offsetsFor(cfg(1), half)
|
|
1321
|
+
})
|
|
1322
|
+
);
|
|
1323
|
+
} else if (!noB) {
|
|
1285
1324
|
const turn = geometryTurnDegrees(geo.geometryType, geo.geometryDegrees);
|
|
1286
1325
|
let bx;
|
|
1287
1326
|
let by;
|
|
@@ -1342,6 +1381,6 @@ function poseOverridesFromDoc(doc) {
|
|
|
1342
1381
|
return out;
|
|
1343
1382
|
}
|
|
1344
1383
|
|
|
1345
|
-
export { 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, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionedCenterline, sliceCenterline, stateToDoc, trackPath };
|
|
1384
|
+
export { 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, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionedCenterline, sectionedEndPose, sliceCenterline, stateToDoc, trackPath };
|
|
1346
1385
|
//# sourceMappingURL=index.js.map
|
|
1347
1386
|
//# sourceMappingURL=index.js.map
|