@willcgage/module-schematic 0.75.0 → 0.77.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 +64 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +90 -1
- package/dist/index.d.ts +90 -1
- package/dist/index.js +63 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -366,6 +366,35 @@ interface SchematicSection {
|
|
|
366
366
|
geometryDegrees?: number | null;
|
|
367
367
|
/** Lateral jog, for offset sections. */
|
|
368
368
|
geometryOffsetInches?: number | null;
|
|
369
|
+
/** This board's WEST end (the A side) — see {@link SectionEnd}. */
|
|
370
|
+
endA?: SectionEnd | null;
|
|
371
|
+
/** This board's EAST end (the B side). */
|
|
372
|
+
endB?: SectionEnd | null;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* One end of a board (#130).
|
|
376
|
+
*
|
|
377
|
+
* Owner's question was *"how would I update my section joints to be endplates
|
|
378
|
+
* from within MR?"* — and until now nothing could say it: a section had a
|
|
379
|
+
* length, a shape and an outline, but nothing about its ends.
|
|
380
|
+
*
|
|
381
|
+
* ⚠️ **There is deliberately no "this is an endplate" flag.** An owner could
|
|
382
|
+
* tick it wrongly and the registry would then tell Free-Dispatcher that two
|
|
383
|
+
* boards will physically mate when they won't. The geometry decides — describe
|
|
384
|
+
* the end and {@link assessSectionEnd} works out whether it conforms.
|
|
385
|
+
*
|
|
386
|
+
* Absent means **not described**, which is an ordinary internal joint, not a
|
|
387
|
+
* failing endplate: the standard exempts internal boundaries from the
|
|
388
|
+
* end-interface rules (#96).
|
|
389
|
+
*/
|
|
390
|
+
interface SectionEnd {
|
|
391
|
+
/** What this end presents. `"none"` = a closed end (a bumper). */
|
|
392
|
+
config?: TrackConfig | "none" | null;
|
|
393
|
+
/** Face width, inches. Absent = the recommended default. */
|
|
394
|
+
widthInches?: number | null;
|
|
395
|
+
/** Main 1's signed distance from the face centre — the standard's own
|
|
396
|
+
* framing, same as an endplate's (see {@link endplateTrackOffsetInches}). */
|
|
397
|
+
trackOffsetInches?: number | null;
|
|
369
398
|
}
|
|
370
399
|
/** The authored benchwork outline, or null when a module hasn't drawn one
|
|
371
400
|
* (renderers then fall back to a band derived from the endplate widths). A
|
|
@@ -843,6 +872,62 @@ declare function usableCapacity(input: {
|
|
|
843
872
|
library?: TrackPart[];
|
|
844
873
|
carLengthInches?: number;
|
|
845
874
|
}): UsableCapacity;
|
|
875
|
+
/** What a board's end is, once the geometry has been asked (#130). */
|
|
876
|
+
interface SectionEndAssessment {
|
|
877
|
+
/** Has the owner described this end at all? Undescribed is an ordinary
|
|
878
|
+
* internal joint — exempt from the end-interface rules (#96) — not a failure. */
|
|
879
|
+
described: boolean;
|
|
880
|
+
/** Does it meet the standard's end-interface rules? Only a described end can. */
|
|
881
|
+
conforming: boolean;
|
|
882
|
+
/** Why it doesn't, when it doesn't. Empty for a conforming or undescribed end. */
|
|
883
|
+
issues: EndplateWidthIssue[];
|
|
884
|
+
/** The resolved values the assessment was made against. */
|
|
885
|
+
config: TrackConfig | "none";
|
|
886
|
+
widthInches: number;
|
|
887
|
+
trackOffsetInches: number;
|
|
888
|
+
}
|
|
889
|
+
/**
|
|
890
|
+
* Is this end of a board a standard endplate? (#130)
|
|
891
|
+
*
|
|
892
|
+
* ⭐ **Derived, never declared.** The issue is emphatic and the reason is good:
|
|
893
|
+
* a checkbox could be ticked wrongly, and the registry would then promise
|
|
894
|
+
* Free-Dispatcher a mating surface that doesn't exist. So the answer comes from
|
|
895
|
+
* the same rules {@link checkEndplateWidth} already applies to a module's own
|
|
896
|
+
* plates — §1.1's 12″ minimum, and §2.0's 4″ fascia clearance and 1.125″ pair.
|
|
897
|
+
*
|
|
898
|
+
* Two of the standard's conditions aren't checked because they can't be false
|
|
899
|
+
* here: track crosses the face **perpendicular** and a double end's two tracks
|
|
900
|
+
* sit **1.125″ apart** are both true by construction in this model. Inventing
|
|
901
|
+
* fields for them would be inventing ways to be wrong.
|
|
902
|
+
*
|
|
903
|
+
* An end with no config is **undescribed**, which is the ordinary case — most
|
|
904
|
+
* joints inside a module are just joints.
|
|
905
|
+
*/
|
|
906
|
+
declare function assessSectionEnd(end: SectionEnd | null | undefined, opts?: {
|
|
907
|
+
main2Below?: boolean;
|
|
908
|
+
}): SectionEndAssessment;
|
|
909
|
+
/** Two board ends meeting at a joint, and whether that joint is a standard
|
|
910
|
+
* interface (#130). */
|
|
911
|
+
interface SectionJointAssessment {
|
|
912
|
+
west: SectionEndAssessment;
|
|
913
|
+
east: SectionEndAssessment;
|
|
914
|
+
/** Both ends conform AND present the same number of tracks — so these two
|
|
915
|
+
* boards could be separated and each used against any other module. */
|
|
916
|
+
standardInterface: boolean;
|
|
917
|
+
/** Plain-language reason it isn't one, or null when it is. */
|
|
918
|
+
reason: string | null;
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Assess a joint — the two board ends that meet there (#130).
|
|
922
|
+
*
|
|
923
|
+
* ⚠️ Track COUNT is the only compatibility rule. Two conforming ends of
|
|
924
|
+
* differing face WIDTH still mate: the standard lets plates differ in width and
|
|
925
|
+
* be offset, so long as the track lines up. That's a deliberate non-check — see
|
|
926
|
+
* the note on endplate width authoring.
|
|
927
|
+
*/
|
|
928
|
+
declare function assessSectionJoint(west: SectionEnd | null | undefined, east: SectionEnd | null | undefined, opts?: {
|
|
929
|
+
main2Below?: boolean;
|
|
930
|
+
}): SectionJointAssessment;
|
|
846
931
|
/** How much of a car-spot span has no rail under it (#194). */
|
|
847
932
|
interface SpanOverhang {
|
|
848
933
|
/** Inches the span runs past the track's near end (0 = it starts on track). */
|
|
@@ -2047,6 +2132,10 @@ interface ModuleGeometryInput {
|
|
|
2047
2132
|
y: number;
|
|
2048
2133
|
heading: number;
|
|
2049
2134
|
}>;
|
|
2135
|
+
/** Authored endplate FACE widths by id ("A"/"B"), inches — the board's depth.
|
|
2136
|
+
* Needed to place a branch endplate on the benchwork edge rather than on the
|
|
2137
|
+
* centre line; absent ends use the recommended default. */
|
|
2138
|
+
endplateWidths?: Record<string, number>;
|
|
2050
2139
|
/** Half the spacing between the two tracks of a double endplate (Free-mo ≈ 1",
|
|
2051
2140
|
* Free-moN ≈ 9/16"). */
|
|
2052
2141
|
trackHalfSpacingInches?: number;
|
|
@@ -2125,4 +2214,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
2125
2214
|
heading: number;
|
|
2126
2215
|
}>;
|
|
2127
2216
|
|
|
2128
|
-
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, type BenchworkPoint, type BranchConnector, CLEARANCE_SPACING_INCHES, CODE55_RAIL_HEIGHT_INCHES, DEFAULT_FLEX_PART_ID, 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, FLEX_TRACK_PARTS, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, type FlexPiece, type FlexPieceEnd, 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 OccupiedSpan, 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 SpanOverhang, type StoredTrackPart, TIE_HALF_LENGTH_INCHES, TURNOUT_LEAD_INCHES_PER_FROG, type TrackConfig, type TrackPart, type TrackRole, type TurnoutClosure, type TurnoutKind, type UsableCapacity, WHOLE_MODULE_SECTION_ID, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, clearancePointPastFrogInches, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateCentreOffsetInches, endplateFaceSegments, endplateLead, endplateTrackOffsetInches, endplateWidthInches, flexPartFor, flexParts, flexPieces, flexUsage, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, hasNoFarEndplate, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, 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 };
|
|
2217
|
+
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, type BenchworkPoint, type BranchConnector, CLEARANCE_SPACING_INCHES, CODE55_RAIL_HEIGHT_INCHES, DEFAULT_FLEX_PART_ID, 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, FLEX_TRACK_PARTS, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, type FlexPiece, type FlexPieceEnd, 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 OccupiedSpan, 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 SectionEnd, type SectionEndAssessment, type SectionFootprint, type SectionJointAssessment, type SectionRelativePos, type SignalFacing, type SignalSide, type SpanOverhang, type StoredTrackPart, TIE_HALF_LENGTH_INCHES, TURNOUT_LEAD_INCHES_PER_FROG, type TrackConfig, type TrackPart, type TrackRole, type TurnoutClosure, type TurnoutKind, type UsableCapacity, WHOLE_MODULE_SECTION_ID, asModuleSchematic, assessSectionEnd, assessSectionJoint, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, clearancePointPastFrogInches, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateCentreOffsetInches, endplateFaceSegments, endplateLead, endplateTrackOffsetInches, endplateWidthInches, flexPartFor, flexParts, flexPieces, flexUsage, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, hasNoFarEndplate, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, 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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -366,6 +366,35 @@ interface SchematicSection {
|
|
|
366
366
|
geometryDegrees?: number | null;
|
|
367
367
|
/** Lateral jog, for offset sections. */
|
|
368
368
|
geometryOffsetInches?: number | null;
|
|
369
|
+
/** This board's WEST end (the A side) — see {@link SectionEnd}. */
|
|
370
|
+
endA?: SectionEnd | null;
|
|
371
|
+
/** This board's EAST end (the B side). */
|
|
372
|
+
endB?: SectionEnd | null;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* One end of a board (#130).
|
|
376
|
+
*
|
|
377
|
+
* Owner's question was *"how would I update my section joints to be endplates
|
|
378
|
+
* from within MR?"* — and until now nothing could say it: a section had a
|
|
379
|
+
* length, a shape and an outline, but nothing about its ends.
|
|
380
|
+
*
|
|
381
|
+
* ⚠️ **There is deliberately no "this is an endplate" flag.** An owner could
|
|
382
|
+
* tick it wrongly and the registry would then tell Free-Dispatcher that two
|
|
383
|
+
* boards will physically mate when they won't. The geometry decides — describe
|
|
384
|
+
* the end and {@link assessSectionEnd} works out whether it conforms.
|
|
385
|
+
*
|
|
386
|
+
* Absent means **not described**, which is an ordinary internal joint, not a
|
|
387
|
+
* failing endplate: the standard exempts internal boundaries from the
|
|
388
|
+
* end-interface rules (#96).
|
|
389
|
+
*/
|
|
390
|
+
interface SectionEnd {
|
|
391
|
+
/** What this end presents. `"none"` = a closed end (a bumper). */
|
|
392
|
+
config?: TrackConfig | "none" | null;
|
|
393
|
+
/** Face width, inches. Absent = the recommended default. */
|
|
394
|
+
widthInches?: number | null;
|
|
395
|
+
/** Main 1's signed distance from the face centre — the standard's own
|
|
396
|
+
* framing, same as an endplate's (see {@link endplateTrackOffsetInches}). */
|
|
397
|
+
trackOffsetInches?: number | null;
|
|
369
398
|
}
|
|
370
399
|
/** The authored benchwork outline, or null when a module hasn't drawn one
|
|
371
400
|
* (renderers then fall back to a band derived from the endplate widths). A
|
|
@@ -843,6 +872,62 @@ declare function usableCapacity(input: {
|
|
|
843
872
|
library?: TrackPart[];
|
|
844
873
|
carLengthInches?: number;
|
|
845
874
|
}): UsableCapacity;
|
|
875
|
+
/** What a board's end is, once the geometry has been asked (#130). */
|
|
876
|
+
interface SectionEndAssessment {
|
|
877
|
+
/** Has the owner described this end at all? Undescribed is an ordinary
|
|
878
|
+
* internal joint — exempt from the end-interface rules (#96) — not a failure. */
|
|
879
|
+
described: boolean;
|
|
880
|
+
/** Does it meet the standard's end-interface rules? Only a described end can. */
|
|
881
|
+
conforming: boolean;
|
|
882
|
+
/** Why it doesn't, when it doesn't. Empty for a conforming or undescribed end. */
|
|
883
|
+
issues: EndplateWidthIssue[];
|
|
884
|
+
/** The resolved values the assessment was made against. */
|
|
885
|
+
config: TrackConfig | "none";
|
|
886
|
+
widthInches: number;
|
|
887
|
+
trackOffsetInches: number;
|
|
888
|
+
}
|
|
889
|
+
/**
|
|
890
|
+
* Is this end of a board a standard endplate? (#130)
|
|
891
|
+
*
|
|
892
|
+
* ⭐ **Derived, never declared.** The issue is emphatic and the reason is good:
|
|
893
|
+
* a checkbox could be ticked wrongly, and the registry would then promise
|
|
894
|
+
* Free-Dispatcher a mating surface that doesn't exist. So the answer comes from
|
|
895
|
+
* the same rules {@link checkEndplateWidth} already applies to a module's own
|
|
896
|
+
* plates — §1.1's 12″ minimum, and §2.0's 4″ fascia clearance and 1.125″ pair.
|
|
897
|
+
*
|
|
898
|
+
* Two of the standard's conditions aren't checked because they can't be false
|
|
899
|
+
* here: track crosses the face **perpendicular** and a double end's two tracks
|
|
900
|
+
* sit **1.125″ apart** are both true by construction in this model. Inventing
|
|
901
|
+
* fields for them would be inventing ways to be wrong.
|
|
902
|
+
*
|
|
903
|
+
* An end with no config is **undescribed**, which is the ordinary case — most
|
|
904
|
+
* joints inside a module are just joints.
|
|
905
|
+
*/
|
|
906
|
+
declare function assessSectionEnd(end: SectionEnd | null | undefined, opts?: {
|
|
907
|
+
main2Below?: boolean;
|
|
908
|
+
}): SectionEndAssessment;
|
|
909
|
+
/** Two board ends meeting at a joint, and whether that joint is a standard
|
|
910
|
+
* interface (#130). */
|
|
911
|
+
interface SectionJointAssessment {
|
|
912
|
+
west: SectionEndAssessment;
|
|
913
|
+
east: SectionEndAssessment;
|
|
914
|
+
/** Both ends conform AND present the same number of tracks — so these two
|
|
915
|
+
* boards could be separated and each used against any other module. */
|
|
916
|
+
standardInterface: boolean;
|
|
917
|
+
/** Plain-language reason it isn't one, or null when it is. */
|
|
918
|
+
reason: string | null;
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Assess a joint — the two board ends that meet there (#130).
|
|
922
|
+
*
|
|
923
|
+
* ⚠️ Track COUNT is the only compatibility rule. Two conforming ends of
|
|
924
|
+
* differing face WIDTH still mate: the standard lets plates differ in width and
|
|
925
|
+
* be offset, so long as the track lines up. That's a deliberate non-check — see
|
|
926
|
+
* the note on endplate width authoring.
|
|
927
|
+
*/
|
|
928
|
+
declare function assessSectionJoint(west: SectionEnd | null | undefined, east: SectionEnd | null | undefined, opts?: {
|
|
929
|
+
main2Below?: boolean;
|
|
930
|
+
}): SectionJointAssessment;
|
|
846
931
|
/** How much of a car-spot span has no rail under it (#194). */
|
|
847
932
|
interface SpanOverhang {
|
|
848
933
|
/** Inches the span runs past the track's near end (0 = it starts on track). */
|
|
@@ -2047,6 +2132,10 @@ interface ModuleGeometryInput {
|
|
|
2047
2132
|
y: number;
|
|
2048
2133
|
heading: number;
|
|
2049
2134
|
}>;
|
|
2135
|
+
/** Authored endplate FACE widths by id ("A"/"B"), inches — the board's depth.
|
|
2136
|
+
* Needed to place a branch endplate on the benchwork edge rather than on the
|
|
2137
|
+
* centre line; absent ends use the recommended default. */
|
|
2138
|
+
endplateWidths?: Record<string, number>;
|
|
2050
2139
|
/** Half the spacing between the two tracks of a double endplate (Free-mo ≈ 1",
|
|
2051
2140
|
* Free-moN ≈ 9/16"). */
|
|
2052
2141
|
trackHalfSpacingInches?: number;
|
|
@@ -2125,4 +2214,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
2125
2214
|
heading: number;
|
|
2126
2215
|
}>;
|
|
2127
2216
|
|
|
2128
|
-
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, type BenchworkPoint, type BranchConnector, CLEARANCE_SPACING_INCHES, CODE55_RAIL_HEIGHT_INCHES, DEFAULT_FLEX_PART_ID, 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, FLEX_TRACK_PARTS, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, type FlexPiece, type FlexPieceEnd, 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 OccupiedSpan, 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 SpanOverhang, type StoredTrackPart, TIE_HALF_LENGTH_INCHES, TURNOUT_LEAD_INCHES_PER_FROG, type TrackConfig, type TrackPart, type TrackRole, type TurnoutClosure, type TurnoutKind, type UsableCapacity, WHOLE_MODULE_SECTION_ID, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, clearancePointPastFrogInches, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateCentreOffsetInches, endplateFaceSegments, endplateLead, endplateTrackOffsetInches, endplateWidthInches, flexPartFor, flexParts, flexPieces, flexUsage, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, hasNoFarEndplate, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, 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 };
|
|
2217
|
+
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, type BenchworkPoint, type BranchConnector, CLEARANCE_SPACING_INCHES, CODE55_RAIL_HEIGHT_INCHES, DEFAULT_FLEX_PART_ID, 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, FLEX_TRACK_PARTS, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, type FlexPiece, type FlexPieceEnd, 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 OccupiedSpan, 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 SectionEnd, type SectionEndAssessment, type SectionFootprint, type SectionJointAssessment, type SectionRelativePos, type SignalFacing, type SignalSide, type SpanOverhang, type StoredTrackPart, TIE_HALF_LENGTH_INCHES, TURNOUT_LEAD_INCHES_PER_FROG, type TrackConfig, type TrackPart, type TrackRole, type TurnoutClosure, type TurnoutKind, type UsableCapacity, WHOLE_MODULE_SECTION_ID, asModuleSchematic, assessSectionEnd, assessSectionJoint, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, clearancePointPastFrogInches, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateCentreOffsetInches, endplateFaceSegments, endplateLead, endplateTrackOffsetInches, endplateWidthInches, flexPartFor, flexParts, flexPieces, flexUsage, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, hasNoFarEndplate, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, 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 };
|
package/dist/index.js
CHANGED
|
@@ -29,10 +29,28 @@ function moduleSections(doc) {
|
|
|
29
29
|
...typeof len === "number" && Number.isFinite(len) && len > 0 ? { lengthInches: len } : {},
|
|
30
30
|
...sec.geometryType ? { geometryType: sec.geometryType } : {},
|
|
31
31
|
...typeof deg === "number" && Number.isFinite(deg) ? { geometryDegrees: deg } : {},
|
|
32
|
-
...typeof off === "number" && Number.isFinite(off) ? { geometryOffsetInches: off } : {}
|
|
32
|
+
...typeof off === "number" && Number.isFinite(off) ? { geometryOffsetInches: off } : {},
|
|
33
|
+
// The board's two ends (#130). Written only when actually described —
|
|
34
|
+
// an absent end is an ordinary internal joint, and an empty object
|
|
35
|
+
// would claim the owner had said something about it.
|
|
36
|
+
...sectionEnd(sec.endA) ? { endA: sectionEnd(sec.endA) } : {},
|
|
37
|
+
...sectionEnd(sec.endB) ? { endB: sectionEnd(sec.endB) } : {}
|
|
33
38
|
};
|
|
34
39
|
});
|
|
35
40
|
}
|
|
41
|
+
function sectionEnd(end) {
|
|
42
|
+
if (!end) return null;
|
|
43
|
+
const config = end.config === "single" || end.config === "double" || end.config === "none" ? end.config : null;
|
|
44
|
+
const w = end.widthInches;
|
|
45
|
+
const o = end.trackOffsetInches;
|
|
46
|
+
const out = {
|
|
47
|
+
...config ? { config } : {},
|
|
48
|
+
...typeof w === "number" && Number.isFinite(w) && w > 0 ? { widthInches: w } : {},
|
|
49
|
+
// Signed, and 0 is meaningful ("explicitly centred", #93) — keep any finite.
|
|
50
|
+
...typeof o === "number" && Number.isFinite(o) ? { trackOffsetInches: o } : {}
|
|
51
|
+
};
|
|
52
|
+
return Object.keys(out).length ? out : null;
|
|
53
|
+
}
|
|
36
54
|
function sectionFootprints(doc, derive) {
|
|
37
55
|
const spans = derive ? sectionSpans(doc) : [];
|
|
38
56
|
const spanOf = new Map(spans.map((sp) => [sp.id, sp]));
|
|
@@ -625,6 +643,42 @@ function usableCapacity(input) {
|
|
|
625
643
|
scaleFeet: Math.round(inchesToScaleFeet(usable))
|
|
626
644
|
};
|
|
627
645
|
}
|
|
646
|
+
function assessSectionEnd(end, opts = {}) {
|
|
647
|
+
const config = end?.config ?? "none";
|
|
648
|
+
const widthInches = endplateWidthInches({ widthInches: end?.widthInches });
|
|
649
|
+
const trackOffsetInches = endplateTrackOffsetInches(
|
|
650
|
+
end?.trackOffsetInches,
|
|
651
|
+
config,
|
|
652
|
+
opts.main2Below
|
|
653
|
+
);
|
|
654
|
+
const described = config === "single" || config === "double";
|
|
655
|
+
if (!described) {
|
|
656
|
+
return { described: false, conforming: false, issues: [], config, widthInches, trackOffsetInches };
|
|
657
|
+
}
|
|
658
|
+
const issues = checkEndplateWidth({
|
|
659
|
+
widthInches: end?.widthInches,
|
|
660
|
+
config,
|
|
661
|
+
trackOffsetInches: end?.trackOffsetInches,
|
|
662
|
+
main2Below: opts.main2Below
|
|
663
|
+
});
|
|
664
|
+
return { described: true, conforming: issues.length === 0, issues, config, widthInches, trackOffsetInches };
|
|
665
|
+
}
|
|
666
|
+
function assessSectionJoint(west, east, opts = {}) {
|
|
667
|
+
const w = assessSectionEnd(west, opts);
|
|
668
|
+
const e = assessSectionEnd(east, opts);
|
|
669
|
+
let reason = null;
|
|
670
|
+
if (!w.described || !e.described) {
|
|
671
|
+
reason = "an internal joint \u2014 neither end has been described as an interface";
|
|
672
|
+
if (w.described !== e.described)
|
|
673
|
+
reason = `only the ${w.described ? "west" : "east"} side is described as an endplate`;
|
|
674
|
+
} else if (!w.conforming || !e.conforming) {
|
|
675
|
+
const bad = !w.conforming ? w : e;
|
|
676
|
+
reason = bad.issues[0]?.message ?? "an end doesn't meet the standard";
|
|
677
|
+
} else if (w.config !== e.config) {
|
|
678
|
+
reason = `${w.config} meets ${e.config} \u2014 the track counts differ`;
|
|
679
|
+
}
|
|
680
|
+
return { west: w, east: e, standardInterface: reason === null, reason };
|
|
681
|
+
}
|
|
628
682
|
function spanOverhang(input) {
|
|
629
683
|
const lo = Math.min(input.fromPos, input.toPos);
|
|
630
684
|
const hi = Math.max(input.fromPos, input.toPos);
|
|
@@ -2316,15 +2370,21 @@ function deriveEndplatePoses(geo) {
|
|
|
2316
2370
|
})
|
|
2317
2371
|
);
|
|
2318
2372
|
}
|
|
2373
|
+
const widthAt = (frac) => {
|
|
2374
|
+
const wa = endplateWidthFor(geo.endplateWidths, "A");
|
|
2375
|
+
const wb = endplateWidthFor(geo.endplateWidths, "B");
|
|
2376
|
+
return (wa * (1 - frac) + wb * frac) / 2;
|
|
2377
|
+
};
|
|
2319
2378
|
for (const b of geo.branches ?? []) {
|
|
2320
2379
|
const frac = L > 0 ? Math.min(1, Math.max(0, b.atPos / L)) : 0;
|
|
2321
2380
|
const px = frac * L;
|
|
2322
2381
|
const config = b.config === "double" ? "double" : "single";
|
|
2382
|
+
const depth = widthAt(frac);
|
|
2323
2383
|
poses.push(
|
|
2324
2384
|
withOverride({
|
|
2325
2385
|
id: b.id,
|
|
2326
2386
|
x: px,
|
|
2327
|
-
y:
|
|
2387
|
+
y: b.side === "down" ? -depth : depth,
|
|
2328
2388
|
heading: b.side === "down" ? 270 : 90,
|
|
2329
2389
|
trackConfig: config,
|
|
2330
2390
|
trackOffsets: offsetsFor(config, half)
|
|
@@ -2423,6 +2483,6 @@ function poseOverridesFromDoc(doc) {
|
|
|
2423
2483
|
return out;
|
|
2424
2484
|
}
|
|
2425
2485
|
|
|
2426
|
-
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, 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, RAIL_GAUGE_INCHES, TIE_HALF_LENGTH_INCHES, TURNOUT_LEAD_INCHES_PER_FROG, WHOLE_MODULE_SECTION_ID, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, clearancePointPastFrogInches, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateCentreOffsetInches, endplateFaceSegments, endplateLead, endplateTrackOffsetInches, endplateWidthInches, flexPartFor, flexParts, flexPieces, flexUsage, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, hasNoFarEndplate, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, 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 };
|
|
2486
|
+
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, 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, 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, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateCentreOffsetInches, endplateFaceSegments, endplateLead, endplateTrackOffsetInches, endplateWidthInches, flexPartFor, flexParts, flexPieces, flexUsage, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, hasNoFarEndplate, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, 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 };
|
|
2427
2487
|
//# sourceMappingURL=index.js.map
|
|
2428
2488
|
//# sourceMappingURL=index.js.map
|