@willcgage/module-schematic 0.69.0 → 0.71.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 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +71 -12
- package/dist/index.d.ts +71 -12
- package/dist/index.js +44 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -428,10 +428,18 @@ interface ModuleFootprintInput {
|
|
|
428
428
|
/** Where each endplate's CENTRE sits relative to the main centre-line at that
|
|
429
429
|
* end, inches (signed, along the +normal). Free-moN puts a **double**-track
|
|
430
430
|
* plate's two tracks 9/16″ either side of its centre, so with Main 1 on the
|
|
431
|
-
* centre-line the plate centre is half a track spacing
|
|
432
|
-
*
|
|
433
|
-
*
|
|
431
|
+
* centre-line the plate centre is half a track spacing toward Main 2. Single
|
|
432
|
+
* track crosses at the centre ⇒ 0, and an off-centre track is a signed value.
|
|
433
|
+
* {@link endplateCentreOffsetInches} computes it from what the owner authored.
|
|
434
|
+
*
|
|
435
|
+
* ⚠️ OMITTING an end no longer means 0 — it means "use §2.0", which is a
|
|
436
|
+
* straddle on a double end. Centring a double plate on Main 1 drew its pair
|
|
437
|
+
* wholly to one side, which is what the read-only and catalog views did by
|
|
438
|
+
* passing nothing at all (#190). Pass an explicit number to place a plate. */
|
|
434
439
|
endplateTrackOffsets?: Record<string, number>;
|
|
440
|
+
/** Whether Main 2 runs BELOW Main 1 (`mainsSwapped`, #131). Only affects which
|
|
441
|
+
* way an unauthored double plate straddles. */
|
|
442
|
+
mainsSwapped?: boolean;
|
|
435
443
|
/** Authored benchwork outline (module-local inches), or absent for the band. */
|
|
436
444
|
outline?: BenchworkPoint[] | null;
|
|
437
445
|
/** Authored benchwork HOLE — the inner boundary punched out of `outline` to
|
|
@@ -447,6 +455,10 @@ interface ModuleFootprintInput {
|
|
|
447
455
|
/** A balloon / return loop — the centre-line turns back on itself, so its far
|
|
448
456
|
* end is the THROAT, not an endplate; only endplate A's face is emitted (#loop). */
|
|
449
457
|
loop?: boolean;
|
|
458
|
+
/** Axial endplate configs (A first, then B), same as
|
|
459
|
+
* {@link ModuleGeometryInput.endplateConfigs}. `"none"` at B means the module
|
|
460
|
+
* presents no far endplate, so no face is emitted there (#184/#191). */
|
|
461
|
+
endplateConfigs?: ("single" | "double" | "none" | null | undefined)[];
|
|
450
462
|
}
|
|
451
463
|
interface OutlineFace {
|
|
452
464
|
/** The endplate face's two corners + midpoint (the track point). */
|
|
@@ -633,23 +645,45 @@ declare function endplateFaceSegments(center: BenchworkPoint[], widthA?: number,
|
|
|
633
645
|
*/
|
|
634
646
|
declare function moduleFootprint(input: ModuleFootprintInput): ModuleFootprint;
|
|
635
647
|
/**
|
|
636
|
-
*
|
|
637
|
-
*
|
|
638
|
-
*
|
|
639
|
-
*
|
|
648
|
+
* Where an endplate's CENTRE sits relative to MAIN 1 — the renderer's framing,
|
|
649
|
+
* and the one number a drawing needs to place the plate.
|
|
650
|
+
*
|
|
651
|
+
* ⭐ THE single definition. Two callers had their own: the builder computed it
|
|
652
|
+
* inline (swap-aware), and the read-only/catalog footprint **passed nothing at
|
|
653
|
+
* all**, so every plate there was centred on Main 1 — a double end drew its pair
|
|
654
|
+
* entirely to one side of the plate instead of straddling it (#190).
|
|
655
|
+
*
|
|
656
|
+
* §2.0 puts a double end's two tracks 0.5625″ either side of the plate centre,
|
|
657
|
+
* so the plate centre is half a track spacing away from Main 1 — **toward Main
|
|
658
|
+
* 2**, which is why the swap matters: with Main 2 below, the plate centre is
|
|
659
|
+
* below too. An authored offset always wins (an off-centre end is legal since
|
|
660
|
+
* the 20220628 revision), and is given in the standard's own framing — Main 1's
|
|
661
|
+
* distance from the plate centre — so it comes back negated here.
|
|
640
662
|
*/
|
|
641
|
-
declare function
|
|
663
|
+
declare function endplateCentreOffsetInches(input: {
|
|
664
|
+
config?: TrackConfig | "none" | null;
|
|
665
|
+
/** Main 1's signed distance from the plate centre, as authored. */
|
|
666
|
+
authoredTrackOffsetInches?: number | null;
|
|
667
|
+
/** Whether Main 2 runs below Main 1 (the mains are swapped). */
|
|
668
|
+
main2Below?: boolean;
|
|
669
|
+
}): number;
|
|
642
670
|
/**
|
|
643
671
|
* Where an endplate's PRIMARY track (Main 1) crosses, as a signed distance from
|
|
644
672
|
* the plate's CENTRE — the standard's own framing. Authored value wins; absent
|
|
645
673
|
* falls back to the §2.0 recommendations: a single track centred (0), a double
|
|
646
674
|
* straddling so its two tracks land ∓ half the track spacing (Main 1 low).
|
|
647
675
|
*/
|
|
648
|
-
declare function endplateTrackOffsetInches(authored: number | null | undefined, config: TrackConfig | "none" | undefined
|
|
676
|
+
declare function endplateTrackOffsetInches(authored: number | null | undefined, config: TrackConfig | "none" | undefined,
|
|
677
|
+
/** Whether Main 2 runs BELOW Main 1 (the mains are swapped). The pair
|
|
678
|
+
* straddles the plate centre either way, so Main 1 sits on the side AWAY from
|
|
679
|
+
* Main 2 — low when Main 2 is high, high when it's low. Omitting this
|
|
680
|
+
* hard-coded "Main 2 is above", which is the assumption behind #190. */
|
|
681
|
+
main2Below?: boolean): number;
|
|
649
682
|
/** A Free-moN conformance problem with an endplate's width/track placement. */
|
|
650
683
|
interface EndplateWidthIssue {
|
|
651
|
-
/** "narrow" = below the 12″ minimum; "clearance" = a track too near a fascia
|
|
652
|
-
|
|
684
|
+
/** "narrow" = below the 12″ minimum; "clearance" = a track too near a fascia;
|
|
685
|
+
* "offcentre" = a double end whose pair doesn't straddle the plate centre. */
|
|
686
|
+
code: "narrow" | "clearance" | "offcentre";
|
|
653
687
|
/** Plain-language problem, for the author. */
|
|
654
688
|
message: string;
|
|
655
689
|
/** The width that would satisfy this rule, inches. */
|
|
@@ -672,7 +706,32 @@ declare function checkEndplateWidth(input: {
|
|
|
672
706
|
widthInches?: number | null;
|
|
673
707
|
config?: TrackConfig | "none" | null;
|
|
674
708
|
trackOffsetInches?: number | null;
|
|
709
|
+
/** Whether Main 2 runs BELOW Main 1 (the mains are swapped). Without it a
|
|
710
|
+
* double end's second track was assumed to be one spacing ABOVE Main 1, so a
|
|
711
|
+
* swapped pair was measured on the wrong side of the plate (#190). */
|
|
712
|
+
main2Below?: boolean;
|
|
675
713
|
}): EndplateWidthIssue[];
|
|
714
|
+
/**
|
|
715
|
+
* Whether a module presents NO far endplate — one conforming face only.
|
|
716
|
+
*
|
|
717
|
+
* ⭐ THE single definition. Three places had grown their own answer to this and
|
|
718
|
+
* drifted: `deriveEndplatePoses` (which knew about `dead_end` and `"none"`), the
|
|
719
|
+
* operations preview's end label, and `moduleFootprint`'s endplate faces — the
|
|
720
|
+
* last two using "is it a loop?" as a stand-in for "has it got two ends?", which
|
|
721
|
+
* was true until #184 and silently wrong after. Anything asking this must call
|
|
722
|
+
* THIS.
|
|
723
|
+
*
|
|
724
|
+
* Three ways to have one end, and they are genuinely different things: the
|
|
725
|
+
* geometry is a dead end; it's a balloon loop, whose far end is the throat and
|
|
726
|
+
* not a plate at all; or the owner said this end has no plate, which is how an
|
|
727
|
+
* *end of the line* or a *pocket* is authored — ordinary straight boards that
|
|
728
|
+
* simply stop, so no geometry type would ever say it for them.
|
|
729
|
+
*/
|
|
730
|
+
declare function hasNoFarEndplate(input: {
|
|
731
|
+
geometryType?: string | null;
|
|
732
|
+
loop?: boolean;
|
|
733
|
+
endplateConfigs?: ("single" | "double" | "none" | null | undefined)[];
|
|
734
|
+
}): boolean;
|
|
676
735
|
/**
|
|
677
736
|
* Whether a doc is a balloon loop — **the authored flag, and only that**.
|
|
678
737
|
*
|
|
@@ -1785,4 +1844,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
1785
1844
|
heading: number;
|
|
1786
1845
|
}>;
|
|
1787
1846
|
|
|
1788
|
-
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, type BenchworkPoint, type BranchConnector, CODE55_RAIL_HEIGHT_INCHES, type DimensionSource, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, ENDPLATE_FASCIA_CLEAR_INCHES, ENDPLATE_LEAD_INCHES, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, type EndplateTrackIssue, type EndplateWidthIssue, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, type FrogCasting, type GeometryType, type ImportedPart, 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 PartAngle, type PartDimension, type PartEnd, type PartExtent, type PartSegment, RAIL_GAUGE_INCHES, type ReturnLoopGeometry, type ReturnLoopShape, 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 SectionRelativePos, type SignalFacing, type SignalSide, type StoredTrackPart, TIE_HALF_LENGTH_INCHES, TURNOUT_LEAD_INCHES_PER_FROG, type TrackConfig, type TrackPart, type TrackRole, type TurnoutClosure, type TurnoutKind, WHOLE_MODULE_SECTION_ID, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateLead,
|
|
1847
|
+
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, type BenchworkPoint, type BranchConnector, CODE55_RAIL_HEIGHT_INCHES, type DimensionSource, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, ENDPLATE_FASCIA_CLEAR_INCHES, ENDPLATE_LEAD_INCHES, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, type EndplateTrackIssue, type EndplateWidthIssue, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, type FrogCasting, type GeometryType, type ImportedPart, 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 PartAngle, type PartDimension, type PartEnd, type PartExtent, type PartSegment, RAIL_GAUGE_INCHES, type ReturnLoopGeometry, type ReturnLoopShape, 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 SectionRelativePos, type SignalFacing, type SignalSide, type StoredTrackPart, TIE_HALF_LENGTH_INCHES, TURNOUT_LEAD_INCHES_PER_FROG, type TrackConfig, type TrackPart, type TrackRole, type TurnoutClosure, type TurnoutKind, WHOLE_MODULE_SECTION_ID, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateCentreOffsetInches, endplateFaceSegments, endplateLead, endplateTrackOffsetInches, endplateWidthInches, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, hasNoFarEndplate, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, leadInchesForSize, mergeImportedParts, mergeStoredParts, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, parseXtpLibrary, partExtent, partExtentForSize, partOutlineAtFrog, pastFrogInchesForSize, pathLengthInches, poseNeedsManual, poseOverridesFromDoc, remapPos, returnLoop, sampleBenchworkOutline, samplePartSegments, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, stateToDoc, storedPartToTrackPart, toSectionRelative, trackMeetsEndplateIssues, trackPart, trackPath, turnoutClosure, turnoutPartForSize };
|
package/dist/index.d.ts
CHANGED
|
@@ -428,10 +428,18 @@ interface ModuleFootprintInput {
|
|
|
428
428
|
/** Where each endplate's CENTRE sits relative to the main centre-line at that
|
|
429
429
|
* end, inches (signed, along the +normal). Free-moN puts a **double**-track
|
|
430
430
|
* plate's two tracks 9/16″ either side of its centre, so with Main 1 on the
|
|
431
|
-
* centre-line the plate centre is half a track spacing
|
|
432
|
-
*
|
|
433
|
-
*
|
|
431
|
+
* centre-line the plate centre is half a track spacing toward Main 2. Single
|
|
432
|
+
* track crosses at the centre ⇒ 0, and an off-centre track is a signed value.
|
|
433
|
+
* {@link endplateCentreOffsetInches} computes it from what the owner authored.
|
|
434
|
+
*
|
|
435
|
+
* ⚠️ OMITTING an end no longer means 0 — it means "use §2.0", which is a
|
|
436
|
+
* straddle on a double end. Centring a double plate on Main 1 drew its pair
|
|
437
|
+
* wholly to one side, which is what the read-only and catalog views did by
|
|
438
|
+
* passing nothing at all (#190). Pass an explicit number to place a plate. */
|
|
434
439
|
endplateTrackOffsets?: Record<string, number>;
|
|
440
|
+
/** Whether Main 2 runs BELOW Main 1 (`mainsSwapped`, #131). Only affects which
|
|
441
|
+
* way an unauthored double plate straddles. */
|
|
442
|
+
mainsSwapped?: boolean;
|
|
435
443
|
/** Authored benchwork outline (module-local inches), or absent for the band. */
|
|
436
444
|
outline?: BenchworkPoint[] | null;
|
|
437
445
|
/** Authored benchwork HOLE — the inner boundary punched out of `outline` to
|
|
@@ -447,6 +455,10 @@ interface ModuleFootprintInput {
|
|
|
447
455
|
/** A balloon / return loop — the centre-line turns back on itself, so its far
|
|
448
456
|
* end is the THROAT, not an endplate; only endplate A's face is emitted (#loop). */
|
|
449
457
|
loop?: boolean;
|
|
458
|
+
/** Axial endplate configs (A first, then B), same as
|
|
459
|
+
* {@link ModuleGeometryInput.endplateConfigs}. `"none"` at B means the module
|
|
460
|
+
* presents no far endplate, so no face is emitted there (#184/#191). */
|
|
461
|
+
endplateConfigs?: ("single" | "double" | "none" | null | undefined)[];
|
|
450
462
|
}
|
|
451
463
|
interface OutlineFace {
|
|
452
464
|
/** The endplate face's two corners + midpoint (the track point). */
|
|
@@ -633,23 +645,45 @@ declare function endplateFaceSegments(center: BenchworkPoint[], widthA?: number,
|
|
|
633
645
|
*/
|
|
634
646
|
declare function moduleFootprint(input: ModuleFootprintInput): ModuleFootprint;
|
|
635
647
|
/**
|
|
636
|
-
*
|
|
637
|
-
*
|
|
638
|
-
*
|
|
639
|
-
*
|
|
648
|
+
* Where an endplate's CENTRE sits relative to MAIN 1 — the renderer's framing,
|
|
649
|
+
* and the one number a drawing needs to place the plate.
|
|
650
|
+
*
|
|
651
|
+
* ⭐ THE single definition. Two callers had their own: the builder computed it
|
|
652
|
+
* inline (swap-aware), and the read-only/catalog footprint **passed nothing at
|
|
653
|
+
* all**, so every plate there was centred on Main 1 — a double end drew its pair
|
|
654
|
+
* entirely to one side of the plate instead of straddling it (#190).
|
|
655
|
+
*
|
|
656
|
+
* §2.0 puts a double end's two tracks 0.5625″ either side of the plate centre,
|
|
657
|
+
* so the plate centre is half a track spacing away from Main 1 — **toward Main
|
|
658
|
+
* 2**, which is why the swap matters: with Main 2 below, the plate centre is
|
|
659
|
+
* below too. An authored offset always wins (an off-centre end is legal since
|
|
660
|
+
* the 20220628 revision), and is given in the standard's own framing — Main 1's
|
|
661
|
+
* distance from the plate centre — so it comes back negated here.
|
|
640
662
|
*/
|
|
641
|
-
declare function
|
|
663
|
+
declare function endplateCentreOffsetInches(input: {
|
|
664
|
+
config?: TrackConfig | "none" | null;
|
|
665
|
+
/** Main 1's signed distance from the plate centre, as authored. */
|
|
666
|
+
authoredTrackOffsetInches?: number | null;
|
|
667
|
+
/** Whether Main 2 runs below Main 1 (the mains are swapped). */
|
|
668
|
+
main2Below?: boolean;
|
|
669
|
+
}): number;
|
|
642
670
|
/**
|
|
643
671
|
* Where an endplate's PRIMARY track (Main 1) crosses, as a signed distance from
|
|
644
672
|
* the plate's CENTRE — the standard's own framing. Authored value wins; absent
|
|
645
673
|
* falls back to the §2.0 recommendations: a single track centred (0), a double
|
|
646
674
|
* straddling so its two tracks land ∓ half the track spacing (Main 1 low).
|
|
647
675
|
*/
|
|
648
|
-
declare function endplateTrackOffsetInches(authored: number | null | undefined, config: TrackConfig | "none" | undefined
|
|
676
|
+
declare function endplateTrackOffsetInches(authored: number | null | undefined, config: TrackConfig | "none" | undefined,
|
|
677
|
+
/** Whether Main 2 runs BELOW Main 1 (the mains are swapped). The pair
|
|
678
|
+
* straddles the plate centre either way, so Main 1 sits on the side AWAY from
|
|
679
|
+
* Main 2 — low when Main 2 is high, high when it's low. Omitting this
|
|
680
|
+
* hard-coded "Main 2 is above", which is the assumption behind #190. */
|
|
681
|
+
main2Below?: boolean): number;
|
|
649
682
|
/** A Free-moN conformance problem with an endplate's width/track placement. */
|
|
650
683
|
interface EndplateWidthIssue {
|
|
651
|
-
/** "narrow" = below the 12″ minimum; "clearance" = a track too near a fascia
|
|
652
|
-
|
|
684
|
+
/** "narrow" = below the 12″ minimum; "clearance" = a track too near a fascia;
|
|
685
|
+
* "offcentre" = a double end whose pair doesn't straddle the plate centre. */
|
|
686
|
+
code: "narrow" | "clearance" | "offcentre";
|
|
653
687
|
/** Plain-language problem, for the author. */
|
|
654
688
|
message: string;
|
|
655
689
|
/** The width that would satisfy this rule, inches. */
|
|
@@ -672,7 +706,32 @@ declare function checkEndplateWidth(input: {
|
|
|
672
706
|
widthInches?: number | null;
|
|
673
707
|
config?: TrackConfig | "none" | null;
|
|
674
708
|
trackOffsetInches?: number | null;
|
|
709
|
+
/** Whether Main 2 runs BELOW Main 1 (the mains are swapped). Without it a
|
|
710
|
+
* double end's second track was assumed to be one spacing ABOVE Main 1, so a
|
|
711
|
+
* swapped pair was measured on the wrong side of the plate (#190). */
|
|
712
|
+
main2Below?: boolean;
|
|
675
713
|
}): EndplateWidthIssue[];
|
|
714
|
+
/**
|
|
715
|
+
* Whether a module presents NO far endplate — one conforming face only.
|
|
716
|
+
*
|
|
717
|
+
* ⭐ THE single definition. Three places had grown their own answer to this and
|
|
718
|
+
* drifted: `deriveEndplatePoses` (which knew about `dead_end` and `"none"`), the
|
|
719
|
+
* operations preview's end label, and `moduleFootprint`'s endplate faces — the
|
|
720
|
+
* last two using "is it a loop?" as a stand-in for "has it got two ends?", which
|
|
721
|
+
* was true until #184 and silently wrong after. Anything asking this must call
|
|
722
|
+
* THIS.
|
|
723
|
+
*
|
|
724
|
+
* Three ways to have one end, and they are genuinely different things: the
|
|
725
|
+
* geometry is a dead end; it's a balloon loop, whose far end is the throat and
|
|
726
|
+
* not a plate at all; or the owner said this end has no plate, which is how an
|
|
727
|
+
* *end of the line* or a *pocket* is authored — ordinary straight boards that
|
|
728
|
+
* simply stop, so no geometry type would ever say it for them.
|
|
729
|
+
*/
|
|
730
|
+
declare function hasNoFarEndplate(input: {
|
|
731
|
+
geometryType?: string | null;
|
|
732
|
+
loop?: boolean;
|
|
733
|
+
endplateConfigs?: ("single" | "double" | "none" | null | undefined)[];
|
|
734
|
+
}): boolean;
|
|
676
735
|
/**
|
|
677
736
|
* Whether a doc is a balloon loop — **the authored flag, and only that**.
|
|
678
737
|
*
|
|
@@ -1785,4 +1844,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
1785
1844
|
heading: number;
|
|
1786
1845
|
}>;
|
|
1787
1846
|
|
|
1788
|
-
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, type BenchworkPoint, type BranchConnector, CODE55_RAIL_HEIGHT_INCHES, type DimensionSource, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, ENDPLATE_FASCIA_CLEAR_INCHES, ENDPLATE_LEAD_INCHES, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, type EndplateTrackIssue, type EndplateWidthIssue, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, type FrogCasting, type GeometryType, type ImportedPart, 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 PartAngle, type PartDimension, type PartEnd, type PartExtent, type PartSegment, RAIL_GAUGE_INCHES, type ReturnLoopGeometry, type ReturnLoopShape, 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 SectionRelativePos, type SignalFacing, type SignalSide, type StoredTrackPart, TIE_HALF_LENGTH_INCHES, TURNOUT_LEAD_INCHES_PER_FROG, type TrackConfig, type TrackPart, type TrackRole, type TurnoutClosure, type TurnoutKind, WHOLE_MODULE_SECTION_ID, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateLead,
|
|
1847
|
+
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, type BenchworkPoint, type BranchConnector, CODE55_RAIL_HEIGHT_INCHES, type DimensionSource, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, ENDPLATE_FASCIA_CLEAR_INCHES, ENDPLATE_LEAD_INCHES, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, type EndplateTrackIssue, type EndplateWidthIssue, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, type FrogCasting, type GeometryType, type ImportedPart, 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 PartAngle, type PartDimension, type PartEnd, type PartExtent, type PartSegment, RAIL_GAUGE_INCHES, type ReturnLoopGeometry, type ReturnLoopShape, 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 SectionRelativePos, type SignalFacing, type SignalSide, type StoredTrackPart, TIE_HALF_LENGTH_INCHES, TURNOUT_LEAD_INCHES_PER_FROG, type TrackConfig, type TrackPart, type TrackRole, type TurnoutClosure, type TurnoutKind, WHOLE_MODULE_SECTION_ID, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateCentreOffsetInches, endplateFaceSegments, endplateLead, endplateTrackOffsetInches, endplateWidthInches, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, hasNoFarEndplate, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, leadInchesForSize, mergeImportedParts, mergeStoredParts, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, parseXtpLibrary, partExtent, partExtentForSize, partOutlineAtFrog, pastFrogInchesForSize, pathLengthInches, poseNeedsManual, poseOverridesFromDoc, remapPos, returnLoop, sampleBenchworkOutline, samplePartSegments, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, stateToDoc, storedPartToTrackPart, toSectionRelative, trackMeetsEndplateIssues, trackPart, trackPath, turnoutClosure, turnoutPartForSize };
|
package/dist/index.js
CHANGED
|
@@ -469,8 +469,12 @@ function moduleFootprint(input) {
|
|
|
469
469
|
const widthA = endplateWidthFor(input.endplateWidths, "A");
|
|
470
470
|
const widthB = endplateWidthFor(input.endplateWidths, "B");
|
|
471
471
|
const authored = benchworkOutline(input);
|
|
472
|
-
const
|
|
473
|
-
|
|
472
|
+
const offOf = (i, id) => input.endplateTrackOffsets?.[id] ?? endplateCentreOffsetInches({
|
|
473
|
+
config: input.endplateConfigs?.[i],
|
|
474
|
+
main2Below: input.mainsSwapped === true
|
|
475
|
+
});
|
|
476
|
+
const offA = offOf(0, "A");
|
|
477
|
+
const offB = offOf(1, "B");
|
|
474
478
|
const secs = input.sections ?? [];
|
|
475
479
|
const sectionsOwnShape = secs.length > 1 || secs.some((s) => (s.outline?.length ?? 0) >= 3);
|
|
476
480
|
const sectionOutlines = sectionsOwnShape ? sectionFootprints(input, {
|
|
@@ -483,9 +487,10 @@ function moduleFootprint(input) {
|
|
|
483
487
|
return {
|
|
484
488
|
centerline,
|
|
485
489
|
band: benchworkBand(centerline, widthA, widthB, offA, offB),
|
|
486
|
-
//
|
|
487
|
-
//
|
|
488
|
-
|
|
490
|
+
// Only emit a face where the module actually presents one. A loop's
|
|
491
|
+
// centre-line ends at the THROAT, and an end of the line / pocket simply
|
|
492
|
+
// stops — a far face there is a plate the module hasn't got (#191).
|
|
493
|
+
endplateFaces: hasNoFarEndplate(input) ? endplateFaceSegments(centerline, widthA, widthB, offA, offB).slice(0, 1) : endplateFaceSegments(centerline, widthA, widthB, offA, offB),
|
|
489
494
|
outline: sectionOutlines.length || !authored ? null : sampleBenchworkOutline(authored),
|
|
490
495
|
// The donut hole, arc-sampled — only when there's a solid outline to punch it
|
|
491
496
|
// out of (a sectioned module isn't a donut). Renderers cut it from `outline`.
|
|
@@ -493,13 +498,19 @@ function moduleFootprint(input) {
|
|
|
493
498
|
sectionOutlines
|
|
494
499
|
};
|
|
495
500
|
}
|
|
496
|
-
function
|
|
497
|
-
const v = -endplateTrackOffsetInches(
|
|
501
|
+
function endplateCentreOffsetInches(input) {
|
|
502
|
+
const v = -endplateTrackOffsetInches(
|
|
503
|
+
input.authoredTrackOffsetInches,
|
|
504
|
+
input.config ?? void 0,
|
|
505
|
+
input.main2Below
|
|
506
|
+
);
|
|
498
507
|
return v === 0 ? 0 : v;
|
|
499
508
|
}
|
|
500
|
-
function endplateTrackOffsetInches(authored, config) {
|
|
509
|
+
function endplateTrackOffsetInches(authored, config, main2Below = false) {
|
|
501
510
|
if (typeof authored === "number" && Number.isFinite(authored)) return authored;
|
|
502
|
-
|
|
511
|
+
if (config !== "double") return 0;
|
|
512
|
+
const half = FREEMO_TRACK_SPACING_INCHES / 2;
|
|
513
|
+
return main2Below ? half : -half;
|
|
503
514
|
}
|
|
504
515
|
function checkEndplateWidth(input) {
|
|
505
516
|
const width = endplateWidthInches(input);
|
|
@@ -511,8 +522,13 @@ function checkEndplateWidth(input) {
|
|
|
511
522
|
requiredInches: FREEMO_ENDPLATE_WIDTH_MIN_INCHES
|
|
512
523
|
});
|
|
513
524
|
}
|
|
514
|
-
const off = endplateTrackOffsetInches(
|
|
515
|
-
|
|
525
|
+
const off = endplateTrackOffsetInches(
|
|
526
|
+
input.trackOffsetInches,
|
|
527
|
+
input.config ?? void 0,
|
|
528
|
+
input.main2Below
|
|
529
|
+
);
|
|
530
|
+
const second = off + (input.main2Below ? -1 : 1) * FREEMO_TRACK_SPACING_INCHES;
|
|
531
|
+
const centres = input.config === "double" ? [off, second] : [off];
|
|
516
532
|
const worst = Math.max(...centres.map((c) => Math.abs(c)));
|
|
517
533
|
const clearance = width / 2 - worst;
|
|
518
534
|
if (clearance < FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES) {
|
|
@@ -523,6 +539,18 @@ function checkEndplateWidth(input) {
|
|
|
523
539
|
requiredInches: required
|
|
524
540
|
});
|
|
525
541
|
}
|
|
542
|
+
if (input.config === "double") {
|
|
543
|
+
const mid = (off + second) / 2;
|
|
544
|
+
if (Math.abs(mid) > 0.01) {
|
|
545
|
+
issues.push({
|
|
546
|
+
code: "offcentre",
|
|
547
|
+
message: `The two tracks sit ${round2(Math.abs(mid))}\u2033 off the centre of this endplate. The standard recommends they straddle it \u2014 Main 1 at ${round2((input.main2Below ? 1 : -1) * (FREEMO_TRACK_SPACING_INCHES / 2))}\u2033. Clear the offset to use that.`,
|
|
548
|
+
// Not a width problem — no wider plate fixes it — so hand back the
|
|
549
|
+
// width unchanged rather than imply one would.
|
|
550
|
+
requiredInches: width
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
}
|
|
526
554
|
return issues;
|
|
527
555
|
}
|
|
528
556
|
var round2 = (n) => Math.round(n * 100) / 100;
|
|
@@ -531,6 +559,9 @@ function endplateWidthFor(widths, id) {
|
|
|
531
559
|
const w = widths?.[id];
|
|
532
560
|
return typeof w === "number" && w > 0 ? w : FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES;
|
|
533
561
|
}
|
|
562
|
+
function hasNoFarEndplate(input) {
|
|
563
|
+
return input.geometryType === "dead_end" || input.loop === true || input.endplateConfigs?.[1] === "none";
|
|
564
|
+
}
|
|
534
565
|
function isLoopDoc(doc) {
|
|
535
566
|
return doc.loop === true;
|
|
536
567
|
}
|
|
@@ -1991,7 +2022,7 @@ function deriveEndplatePoses(geo) {
|
|
|
1991
2022
|
trackOffsets: offsetsFor(cfg(0), half)
|
|
1992
2023
|
})
|
|
1993
2024
|
);
|
|
1994
|
-
const noB = geo
|
|
2025
|
+
const noB = hasNoFarEndplate(geo);
|
|
1995
2026
|
const end = sectionedEndPose({ sections: geo.sections });
|
|
1996
2027
|
if (!noB && end) {
|
|
1997
2028
|
poses.push(
|
|
@@ -2142,6 +2173,6 @@ function poseOverridesFromDoc(doc) {
|
|
|
2142
2173
|
return out;
|
|
2143
2174
|
}
|
|
2144
2175
|
|
|
2145
|
-
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, CODE55_RAIL_HEIGHT_INCHES, ENDPLATE_FASCIA_CLEAR_INCHES, ENDPLATE_LEAD_INCHES, 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, RAIL_GAUGE_INCHES, TIE_HALF_LENGTH_INCHES, TURNOUT_LEAD_INCHES_PER_FROG, WHOLE_MODULE_SECTION_ID, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateLead,
|
|
2176
|
+
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, CODE55_RAIL_HEIGHT_INCHES, ENDPLATE_FASCIA_CLEAR_INCHES, ENDPLATE_LEAD_INCHES, 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, RAIL_GAUGE_INCHES, TIE_HALF_LENGTH_INCHES, TURNOUT_LEAD_INCHES_PER_FROG, WHOLE_MODULE_SECTION_ID, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateCentreOffsetInches, endplateFaceSegments, endplateLead, endplateTrackOffsetInches, endplateWidthInches, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, hasNoFarEndplate, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, leadInchesForSize, mergeImportedParts, mergeStoredParts, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, parseXtpLibrary, partExtent, partExtentForSize, partOutlineAtFrog, pastFrogInchesForSize, pathLengthInches, poseNeedsManual, poseOverridesFromDoc, remapPos, returnLoop, sampleBenchworkOutline, samplePartSegments, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, stateToDoc, storedPartToTrackPart, toSectionRelative, trackMeetsEndplateIssues, trackPart, trackPath, turnoutClosure, turnoutPartForSize };
|
|
2146
2177
|
//# sourceMappingURL=index.js.map
|
|
2147
2178
|
//# sourceMappingURL=index.js.map
|