@willcgage/module-schematic 0.95.1 → 0.96.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.d.cts CHANGED
@@ -218,6 +218,15 @@ interface SchematicTrack {
218
218
  * the crossover at the spacing it was actually built to — the Fast Tracks N
219
219
  * fixtures are 1.09″ against Free-moN's 1.125″, and the difference is real. */
220
220
  crossoverPartId?: string | null;
221
+ /**
222
+ * Which end of this track is CLOSED BY A BUMPER — deliberately the end of the
223
+ * line, rather than track that merely stops.
224
+ *
225
+ * ⭐ The difference is operational, not decorative: a bumpered end is where a
226
+ * cut of cars can be shoved to, and it is where usable length runs out. An
227
+ * end that just stops might only be unfinished.
228
+ */
229
+ bumperAt?: "from" | "to" | null;
221
230
  /** The owner's MEASURED usable length, real inches (#20) — for what the
222
231
  * drawing can't know: a bumper post short of the drawn end, a structure
223
232
  * fouling the track. Absent = derive it from the clearance points (#19). */
@@ -1649,7 +1658,7 @@ interface TrackPart {
1649
1658
  * {@link secondaryFrogAngle}, which no single turnout has, and
1650
1659
  * {@link piecesPerAssembly} — because its lengths describe the HALF, not the
1651
1660
  * finished crossover. */
1652
- kind: "turnout" | "wye" | "curved-turnout" | "crossover" | "crossing" | "flex";
1661
+ kind: "turnout" | "wye" | "curved-turnout" | "crossover" | "crossing" | "flex" | "bumper";
1653
1662
  /** Manufacturer part numbers by hand, where the part has a hand. */
1654
1663
  partNumbers?: {
1655
1664
  left?: string;
@@ -1955,6 +1964,17 @@ declare const FAST_TRACKS_N_ME55_CROSSOVERS: TrackPart[];
1955
1964
  /** What a track is laid with when nobody has said — the commonest N-scale flex. */
1956
1965
  declare const DEFAULT_FLEX_PART_ID = "atlas-c55-n-flex";
1957
1966
  /** Every built-in part, across manufacturers. */
1967
+ /**
1968
+ * A bumper that is not a product.
1969
+ *
1970
+ * ⭐ DELIBERATELY GENERIC, AND CARRYING NO DIMENSIONS AT ALL. Owners build these
1971
+ * out of a tie and a scrap of rail as often as they buy them, and what a bumper
1972
+ * MEANS — this end of the track is closed on purpose — does not depend on which
1973
+ * one it is. Recording an invented length here would be exactly the mistake the
1974
+ * rest of this library exists to avoid; a named product can be added with its
1975
+ * own measurement, and will draw at it.
1976
+ */
1977
+ declare const GENERIC_END_OF_TRACK: TrackPart[];
1958
1978
  declare const BUILT_IN_TRACK_PARTS: TrackPart[];
1959
1979
  /** Every flex product a track can be laid with. */
1960
1980
  declare function flexParts(library?: TrackPart[]): TrackPart[];
@@ -2598,6 +2618,16 @@ interface TrackGraph {
2598
2618
  * tight enough that nothing joins by accident, loose enough to absorb the
2599
2619
  * rounding of a drag. */
2600
2620
  declare const JOINT_SNAP_INCHES = 0.01;
2621
+ /**
2622
+ * How long a bumper draws when it is not a named product.
2623
+ *
2624
+ * ⚠️ A DRAWING DEFAULT, NOT A MEASUREMENT, and deliberately not recorded as one
2625
+ * on any part. What a bumper is FOR — saying this end of the track is closed on
2626
+ * purpose — does not depend on its length, and plenty are a tie and a bit of
2627
+ * scrap. A named product supplies its own `overallLength` and this stops
2628
+ * applying.
2629
+ */
2630
+ declare const BUMPER_DRAWN_INCHES = 0.75;
2601
2631
  /**
2602
2632
  * Where a bent run's far end lands, and which way it points — in the piece's own
2603
2633
  * frame, starting at its origin heading +x.
@@ -2687,6 +2717,9 @@ interface GraphRoute {
2687
2717
  bornAt: string | null;
2688
2718
  /** The turnout it runs back into. Set = a SIDING; null = it dead-ends. */
2689
2719
  endsAt: string | null;
2720
+ /** The piece that CLOSES this route — a bumper. Set = the track ends here on
2721
+ * purpose; null = it simply stops, which may just mean unfinished. */
2722
+ closedBy: string | null;
2690
2723
  pieces: string[];
2691
2724
  /** The same pieces, each with where it starts and ends along the route. */
2692
2725
  spans: RouteSpan[];
@@ -3104,4 +3137,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
3104
3137
  heading: number;
3105
3138
  }>;
3106
3139
 
3107
- 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 EndplateEdge, type EndplateEdgePose, type EndplatePose, type EndplateTrackIssue, type EndplateWidthIssue, 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_MAIN_MIN_RADIUS_INCHES, FREEMO_REVERSE_CURVE_STRAIGHT_INCHES, FREEMO_TRACK_SPACING_INCHES, type FlexPiece, type FlexPieceEnd, type FrogCasting, type GeometryType, type GraphAnchor, type GraphConflict, type GraphConnection, type GraphDocInput, type GraphDocResult, type GraphRoute, type GraphTurnout, type GraphWalk, type ImportedPart, type IndustryLabelMode, type IndustrySpot, JOINT_SNAP_INCHES, type LanePinch, 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, PINCH_EASE_INCHES, type PartAngle, type PartDimension, type PartEnd, type PartExtent, type PartGeometry, type PartJoint, type PartJointRole, type PartSegment, type PieceSnap, type PlacedJoint, RAIL_GAUGE_INCHES, type ResolvedAnchor, type ReturnLoopGeometry, type ReturnLoopShape, type RouteSpan, 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 TrackGraph, type TrackPart, type TrackPiece, type TrackRole, type TurnoutClosure, type TurnoutKind, type UsableCapacity, WHOLE_MODULE_SECTION_ID, asModuleSchematic, assessSectionEnd, assessSectionJoint, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTrackGraph, buildTransition, carCapacity, checkEndplateWidth, clearancePointPastFrogInches, crossoverPinches, deriveEndplatePoses, deriveGraphDoc, divergeSideForHand, docToState, emptyEditorState, endplateCentreOffsetInches, endplateEdgePose, endplateFaceSegments, endplateLead, endplateTrackOffsetInches, endplateWidthInches, fitFlexBetween, flexPartFor, flexParts, flexPieces, flexRunEnd, flexUsage, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, graphToDoc, 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, pieceHand, piecePartNumber, pieceRoutePaths, placedJoints, poseNeedsManual, poseOverridesFromDoc, remapPos, resizeFlexPiece, resolveGraphAnchor, returnLoop, sampleBenchworkOutline, samplePartSegments, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, snapPiece, spanOverhang, stateToDoc, storedPartToTrackPart, toSectionRelative, trackMeetsEndplateIssues, trackPart, trackPath, turnoutClosure, turnoutFacing, turnoutOccupiedSpan, turnoutPartForSize, usableCapacity, walkTrackGraph };
3140
+ export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, BUMPER_DRAWN_INCHES, 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 EndplateEdge, type EndplateEdgePose, type EndplatePose, type EndplateTrackIssue, type EndplateWidthIssue, 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_MAIN_MIN_RADIUS_INCHES, FREEMO_REVERSE_CURVE_STRAIGHT_INCHES, FREEMO_TRACK_SPACING_INCHES, type FlexPiece, type FlexPieceEnd, type FrogCasting, GENERIC_END_OF_TRACK, type GeometryType, type GraphAnchor, type GraphConflict, type GraphConnection, type GraphDocInput, type GraphDocResult, type GraphRoute, type GraphTurnout, type GraphWalk, type ImportedPart, type IndustryLabelMode, type IndustrySpot, JOINT_SNAP_INCHES, type LanePinch, 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, PINCH_EASE_INCHES, type PartAngle, type PartDimension, type PartEnd, type PartExtent, type PartGeometry, type PartJoint, type PartJointRole, type PartSegment, type PieceSnap, type PlacedJoint, RAIL_GAUGE_INCHES, type ResolvedAnchor, type ReturnLoopGeometry, type ReturnLoopShape, type RouteSpan, 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 TrackGraph, type TrackPart, type TrackPiece, type TrackRole, type TurnoutClosure, type TurnoutKind, type UsableCapacity, WHOLE_MODULE_SECTION_ID, asModuleSchematic, assessSectionEnd, assessSectionJoint, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTrackGraph, buildTransition, carCapacity, checkEndplateWidth, clearancePointPastFrogInches, crossoverPinches, deriveEndplatePoses, deriveGraphDoc, divergeSideForHand, docToState, emptyEditorState, endplateCentreOffsetInches, endplateEdgePose, endplateFaceSegments, endplateLead, endplateTrackOffsetInches, endplateWidthInches, fitFlexBetween, flexPartFor, flexParts, flexPieces, flexRunEnd, flexUsage, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, graphToDoc, 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, pieceHand, piecePartNumber, pieceRoutePaths, placedJoints, poseNeedsManual, poseOverridesFromDoc, remapPos, resizeFlexPiece, resolveGraphAnchor, returnLoop, sampleBenchworkOutline, samplePartSegments, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, snapPiece, spanOverhang, stateToDoc, storedPartToTrackPart, toSectionRelative, trackMeetsEndplateIssues, trackPart, trackPath, turnoutClosure, turnoutFacing, turnoutOccupiedSpan, turnoutPartForSize, usableCapacity, walkTrackGraph };
package/dist/index.d.ts CHANGED
@@ -218,6 +218,15 @@ interface SchematicTrack {
218
218
  * the crossover at the spacing it was actually built to — the Fast Tracks N
219
219
  * fixtures are 1.09″ against Free-moN's 1.125″, and the difference is real. */
220
220
  crossoverPartId?: string | null;
221
+ /**
222
+ * Which end of this track is CLOSED BY A BUMPER — deliberately the end of the
223
+ * line, rather than track that merely stops.
224
+ *
225
+ * ⭐ The difference is operational, not decorative: a bumpered end is where a
226
+ * cut of cars can be shoved to, and it is where usable length runs out. An
227
+ * end that just stops might only be unfinished.
228
+ */
229
+ bumperAt?: "from" | "to" | null;
221
230
  /** The owner's MEASURED usable length, real inches (#20) — for what the
222
231
  * drawing can't know: a bumper post short of the drawn end, a structure
223
232
  * fouling the track. Absent = derive it from the clearance points (#19). */
@@ -1649,7 +1658,7 @@ interface TrackPart {
1649
1658
  * {@link secondaryFrogAngle}, which no single turnout has, and
1650
1659
  * {@link piecesPerAssembly} — because its lengths describe the HALF, not the
1651
1660
  * finished crossover. */
1652
- kind: "turnout" | "wye" | "curved-turnout" | "crossover" | "crossing" | "flex";
1661
+ kind: "turnout" | "wye" | "curved-turnout" | "crossover" | "crossing" | "flex" | "bumper";
1653
1662
  /** Manufacturer part numbers by hand, where the part has a hand. */
1654
1663
  partNumbers?: {
1655
1664
  left?: string;
@@ -1955,6 +1964,17 @@ declare const FAST_TRACKS_N_ME55_CROSSOVERS: TrackPart[];
1955
1964
  /** What a track is laid with when nobody has said — the commonest N-scale flex. */
1956
1965
  declare const DEFAULT_FLEX_PART_ID = "atlas-c55-n-flex";
1957
1966
  /** Every built-in part, across manufacturers. */
1967
+ /**
1968
+ * A bumper that is not a product.
1969
+ *
1970
+ * ⭐ DELIBERATELY GENERIC, AND CARRYING NO DIMENSIONS AT ALL. Owners build these
1971
+ * out of a tie and a scrap of rail as often as they buy them, and what a bumper
1972
+ * MEANS — this end of the track is closed on purpose — does not depend on which
1973
+ * one it is. Recording an invented length here would be exactly the mistake the
1974
+ * rest of this library exists to avoid; a named product can be added with its
1975
+ * own measurement, and will draw at it.
1976
+ */
1977
+ declare const GENERIC_END_OF_TRACK: TrackPart[];
1958
1978
  declare const BUILT_IN_TRACK_PARTS: TrackPart[];
1959
1979
  /** Every flex product a track can be laid with. */
1960
1980
  declare function flexParts(library?: TrackPart[]): TrackPart[];
@@ -2598,6 +2618,16 @@ interface TrackGraph {
2598
2618
  * tight enough that nothing joins by accident, loose enough to absorb the
2599
2619
  * rounding of a drag. */
2600
2620
  declare const JOINT_SNAP_INCHES = 0.01;
2621
+ /**
2622
+ * How long a bumper draws when it is not a named product.
2623
+ *
2624
+ * ⚠️ A DRAWING DEFAULT, NOT A MEASUREMENT, and deliberately not recorded as one
2625
+ * on any part. What a bumper is FOR — saying this end of the track is closed on
2626
+ * purpose — does not depend on its length, and plenty are a tie and a bit of
2627
+ * scrap. A named product supplies its own `overallLength` and this stops
2628
+ * applying.
2629
+ */
2630
+ declare const BUMPER_DRAWN_INCHES = 0.75;
2601
2631
  /**
2602
2632
  * Where a bent run's far end lands, and which way it points — in the piece's own
2603
2633
  * frame, starting at its origin heading +x.
@@ -2687,6 +2717,9 @@ interface GraphRoute {
2687
2717
  bornAt: string | null;
2688
2718
  /** The turnout it runs back into. Set = a SIDING; null = it dead-ends. */
2689
2719
  endsAt: string | null;
2720
+ /** The piece that CLOSES this route — a bumper. Set = the track ends here on
2721
+ * purpose; null = it simply stops, which may just mean unfinished. */
2722
+ closedBy: string | null;
2690
2723
  pieces: string[];
2691
2724
  /** The same pieces, each with where it starts and ends along the route. */
2692
2725
  spans: RouteSpan[];
@@ -3104,4 +3137,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
3104
3137
  heading: number;
3105
3138
  }>;
3106
3139
 
3107
- 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 EndplateEdge, type EndplateEdgePose, type EndplatePose, type EndplateTrackIssue, type EndplateWidthIssue, 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_MAIN_MIN_RADIUS_INCHES, FREEMO_REVERSE_CURVE_STRAIGHT_INCHES, FREEMO_TRACK_SPACING_INCHES, type FlexPiece, type FlexPieceEnd, type FrogCasting, type GeometryType, type GraphAnchor, type GraphConflict, type GraphConnection, type GraphDocInput, type GraphDocResult, type GraphRoute, type GraphTurnout, type GraphWalk, type ImportedPart, type IndustryLabelMode, type IndustrySpot, JOINT_SNAP_INCHES, type LanePinch, 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, PINCH_EASE_INCHES, type PartAngle, type PartDimension, type PartEnd, type PartExtent, type PartGeometry, type PartJoint, type PartJointRole, type PartSegment, type PieceSnap, type PlacedJoint, RAIL_GAUGE_INCHES, type ResolvedAnchor, type ReturnLoopGeometry, type ReturnLoopShape, type RouteSpan, 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 TrackGraph, type TrackPart, type TrackPiece, type TrackRole, type TurnoutClosure, type TurnoutKind, type UsableCapacity, WHOLE_MODULE_SECTION_ID, asModuleSchematic, assessSectionEnd, assessSectionJoint, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTrackGraph, buildTransition, carCapacity, checkEndplateWidth, clearancePointPastFrogInches, crossoverPinches, deriveEndplatePoses, deriveGraphDoc, divergeSideForHand, docToState, emptyEditorState, endplateCentreOffsetInches, endplateEdgePose, endplateFaceSegments, endplateLead, endplateTrackOffsetInches, endplateWidthInches, fitFlexBetween, flexPartFor, flexParts, flexPieces, flexRunEnd, flexUsage, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, graphToDoc, 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, pieceHand, piecePartNumber, pieceRoutePaths, placedJoints, poseNeedsManual, poseOverridesFromDoc, remapPos, resizeFlexPiece, resolveGraphAnchor, returnLoop, sampleBenchworkOutline, samplePartSegments, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, snapPiece, spanOverhang, stateToDoc, storedPartToTrackPart, toSectionRelative, trackMeetsEndplateIssues, trackPart, trackPath, turnoutClosure, turnoutFacing, turnoutOccupiedSpan, turnoutPartForSize, usableCapacity, walkTrackGraph };
3140
+ export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, BUMPER_DRAWN_INCHES, 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 EndplateEdge, type EndplateEdgePose, type EndplatePose, type EndplateTrackIssue, type EndplateWidthIssue, 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_MAIN_MIN_RADIUS_INCHES, FREEMO_REVERSE_CURVE_STRAIGHT_INCHES, FREEMO_TRACK_SPACING_INCHES, type FlexPiece, type FlexPieceEnd, type FrogCasting, GENERIC_END_OF_TRACK, type GeometryType, type GraphAnchor, type GraphConflict, type GraphConnection, type GraphDocInput, type GraphDocResult, type GraphRoute, type GraphTurnout, type GraphWalk, type ImportedPart, type IndustryLabelMode, type IndustrySpot, JOINT_SNAP_INCHES, type LanePinch, 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, PINCH_EASE_INCHES, type PartAngle, type PartDimension, type PartEnd, type PartExtent, type PartGeometry, type PartJoint, type PartJointRole, type PartSegment, type PieceSnap, type PlacedJoint, RAIL_GAUGE_INCHES, type ResolvedAnchor, type ReturnLoopGeometry, type ReturnLoopShape, type RouteSpan, 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 TrackGraph, type TrackPart, type TrackPiece, type TrackRole, type TurnoutClosure, type TurnoutKind, type UsableCapacity, WHOLE_MODULE_SECTION_ID, asModuleSchematic, assessSectionEnd, assessSectionJoint, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTrackGraph, buildTransition, carCapacity, checkEndplateWidth, clearancePointPastFrogInches, crossoverPinches, deriveEndplatePoses, deriveGraphDoc, divergeSideForHand, docToState, emptyEditorState, endplateCentreOffsetInches, endplateEdgePose, endplateFaceSegments, endplateLead, endplateTrackOffsetInches, endplateWidthInches, fitFlexBetween, flexPartFor, flexParts, flexPieces, flexRunEnd, flexUsage, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, graphToDoc, 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, pieceHand, piecePartNumber, pieceRoutePaths, placedJoints, poseNeedsManual, poseOverridesFromDoc, remapPos, resizeFlexPiece, resolveGraphAnchor, returnLoop, sampleBenchworkOutline, samplePartSegments, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, snapPiece, spanOverhang, stateToDoc, storedPartToTrackPart, toSectionRelative, trackMeetsEndplateIssues, trackPart, trackPath, turnoutClosure, turnoutFacing, turnoutOccupiedSpan, turnoutPartForSize, usableCapacity, walkTrackGraph };
package/dist/index.js CHANGED
@@ -1701,11 +1701,22 @@ var FAST_TRACKS_N_ME55_CROSSOVERS = [
1701
1701
  };
1702
1702
  });
1703
1703
  var DEFAULT_FLEX_PART_ID = "atlas-c55-n-flex";
1704
+ var GENERIC_END_OF_TRACK = [
1705
+ {
1706
+ id: "generic-bumper",
1707
+ manufacturer: "Generic",
1708
+ line: "N scale",
1709
+ scale: "N",
1710
+ name: "Bumper",
1711
+ kind: "bumper"
1712
+ }
1713
+ ];
1704
1714
  var BUILT_IN_TRACK_PARTS = [
1705
1715
  ...ATLAS_CODE55_N,
1706
1716
  ...FAST_TRACKS_N_ME55,
1707
1717
  ...FAST_TRACKS_N_ME55_CROSSOVERS,
1708
- ...FLEX_TRACK_PARTS
1718
+ ...FLEX_TRACK_PARTS,
1719
+ ...GENERIC_END_OF_TRACK
1709
1720
  ];
1710
1721
  function flexParts(library = BUILT_IN_TRACK_PARTS) {
1711
1722
  return library.filter((p) => p.kind === "flex");
@@ -2160,6 +2171,7 @@ function turnoutClosure(size, opts = {}) {
2160
2171
  }
2161
2172
  function partGeometryGap(part) {
2162
2173
  if (part.kind === "flex") return null;
2174
+ if (part.kind === "bumper") return null;
2163
2175
  if (part.kind === "crossover")
2164
2176
  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";
2165
2177
  if (part.kind === "crossing") return "crossing geometry is not modelled yet";
@@ -2173,6 +2185,14 @@ function partGeometryGap(part) {
2173
2185
  }
2174
2186
  function partGeometry(part, library = BUILT_IN_TRACK_PARTS) {
2175
2187
  if (partGeometryGap(part)) return null;
2188
+ if (part.kind === "bumper") {
2189
+ return {
2190
+ joints: [{ id: "a", role: "throat", x: 0, y: 0, angleDeg: 180 }],
2191
+ routes: [],
2192
+ source: part.overallLength?.source ?? "unverified",
2193
+ divergingEndMeasured: false
2194
+ };
2195
+ }
2176
2196
  if (part.kind === "flex") {
2177
2197
  return {
2178
2198
  joints: [
@@ -2263,6 +2283,12 @@ function pieceRoutePaths(piece, library = BUILT_IN_TRACK_PARTS) {
2263
2283
  return { x: piece.x + x * c - ly * s, y: piece.y + x * s + ly * c };
2264
2284
  };
2265
2285
  const out = [];
2286
+ if (part.kind === "bumper") {
2287
+ const at2 = joints[0];
2288
+ if (!at2) return out;
2289
+ const len = part.overallLength?.inches ?? BUMPER_DRAWN_INCHES;
2290
+ return [{ route: ["a", "a"], points: [{ x: at2.x, y: at2.y }, place(len, 0)] }];
2291
+ }
2266
2292
  for (const route of geo.routes) {
2267
2293
  const a = at(route[0]);
2268
2294
  const b = at(route[1]);
@@ -2326,6 +2352,7 @@ function partsPlaceable(library = BUILT_IN_TRACK_PARTS) {
2326
2352
  return { placeable, blocked };
2327
2353
  }
2328
2354
  var JOINT_SNAP_INCHES = 0.01;
2355
+ var BUMPER_DRAWN_INCHES = 0.75;
2329
2356
  function flexRunEnd(lengthInches, radiusInches) {
2330
2357
  const L = lengthInches;
2331
2358
  const R = radiusInches;
@@ -2517,6 +2544,7 @@ function walkTrackGraph(graph, pieces, startAt, library = BUILT_IN_TRACK_PARTS)
2517
2544
  toPos: startPos,
2518
2545
  bornAt,
2519
2546
  endsAt: null,
2547
+ closedBy: null,
2520
2548
  pieces: [],
2521
2549
  spans: [],
2522
2550
  lateral: 0
@@ -2531,7 +2559,11 @@ function walkTrackGraph(graph, pieces, startAt, library = BUILT_IN_TRACK_PARTS)
2531
2559
  const geo = geoOf(here.piece);
2532
2560
  if (!geo) break;
2533
2561
  const opts = geo.routes.filter((r) => r.includes(here.joint));
2534
- if (!opts.length) break;
2562
+ if (!opts.length) {
2563
+ route.pieces.push(here.piece);
2564
+ route.closedBy = here.piece;
2565
+ break;
2566
+ }
2535
2567
  const pick = opts.find((r) => r.includes("through")) ?? opts[0];
2536
2568
  const exitJoint = pick[0] === here.joint ? pick[1] : pick[0];
2537
2569
  const exit = byKey.get(`${here.piece}.${exitJoint}`);
@@ -2689,7 +2721,10 @@ function graphToDoc(pieces, input) {
2689
2721
  role: "main",
2690
2722
  lane: 0,
2691
2723
  from: epA?.id ?? "A",
2692
- ...epB ? { to: epB.id } : {}
2724
+ ...epB ? { to: epB.id } : {},
2725
+ // A main can be closed too — that is a pocket module, where the track
2726
+ // runs in and stops rather than crossing to a second endplate.
2727
+ ...main.closedBy ? { bumperAt: "to" } : {}
2693
2728
  },
2694
2729
  ...twoMains ? [
2695
2730
  {
@@ -2716,6 +2751,11 @@ function graphToDoc(pieces, input) {
2716
2751
  lane: laneOf(r, uniqueBranches),
2717
2752
  fromPos: round(Math.min(r.fromPos, r.toPos)),
2718
2753
  toPos: round(Math.max(r.fromPos, r.toPos)),
2754
+ // ⚠️ ALWAYS THE `to` END, and not because of an assumption: a branch's
2755
+ // positions are ARC LENGTH FROM ITS THROAT, so they only ever grow — a
2756
+ // spur running physically back toward endplate A still ends at the larger
2757
+ // number. The closed end is the far one from the turnout, by definition.
2758
+ ...r.closedBy ? { bumperAt: "to" } : {},
2719
2759
  ...meta.trackName ? { trackName: meta.trackName } : {},
2720
2760
  ...meta.capacityFeet != null ? { capacityFeet: meta.capacityFeet } : {},
2721
2761
  ...meta.moduleTrackId != null ? { moduleTrackId: meta.moduleTrackId } : {}
@@ -3473,6 +3513,6 @@ function poseOverridesFromDoc(doc) {
3473
3513
  return out;
3474
3514
  }
3475
3515
 
3476
- 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_MAIN_MIN_RADIUS_INCHES, FREEMO_REVERSE_CURVE_STRAIGHT_INCHES, FREEMO_TRACK_SPACING_INCHES, JOINT_SNAP_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, buildTrackGraph, buildTransition, carCapacity, checkEndplateWidth, clearancePointPastFrogInches, crossoverPinches, deriveEndplatePoses, deriveGraphDoc, divergeSideForHand, docToState, emptyEditorState, endplateCentreOffsetInches, endplateEdgePose, endplateFaceSegments, endplateLead, endplateTrackOffsetInches, endplateWidthInches, fitFlexBetween, flexPartFor, flexParts, flexPieces, flexRunEnd, flexUsage, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, graphToDoc, 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, pieceHand, piecePartNumber, pieceRoutePaths, placedJoints, poseNeedsManual, poseOverridesFromDoc, remapPos, resizeFlexPiece, resolveGraphAnchor, returnLoop, sampleBenchworkOutline, samplePartSegments, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, snapPiece, spanOverhang, stateToDoc, storedPartToTrackPart, toSectionRelative, trackMeetsEndplateIssues, trackPart, trackPath, turnoutClosure, turnoutFacing, turnoutOccupiedSpan, turnoutPartForSize, usableCapacity, walkTrackGraph };
3516
+ export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, BUMPER_DRAWN_INCHES, 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_MAIN_MIN_RADIUS_INCHES, FREEMO_REVERSE_CURVE_STRAIGHT_INCHES, FREEMO_TRACK_SPACING_INCHES, GENERIC_END_OF_TRACK, JOINT_SNAP_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, buildTrackGraph, buildTransition, carCapacity, checkEndplateWidth, clearancePointPastFrogInches, crossoverPinches, deriveEndplatePoses, deriveGraphDoc, divergeSideForHand, docToState, emptyEditorState, endplateCentreOffsetInches, endplateEdgePose, endplateFaceSegments, endplateLead, endplateTrackOffsetInches, endplateWidthInches, fitFlexBetween, flexPartFor, flexParts, flexPieces, flexRunEnd, flexUsage, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, graphToDoc, 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, pieceHand, piecePartNumber, pieceRoutePaths, placedJoints, poseNeedsManual, poseOverridesFromDoc, remapPos, resizeFlexPiece, resolveGraphAnchor, returnLoop, sampleBenchworkOutline, samplePartSegments, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, snapPiece, spanOverhang, stateToDoc, storedPartToTrackPart, toSectionRelative, trackMeetsEndplateIssues, trackPart, trackPath, turnoutClosure, turnoutFacing, turnoutOccupiedSpan, turnoutPartForSize, usableCapacity, walkTrackGraph };
3477
3517
  //# sourceMappingURL=index.js.map
3478
3518
  //# sourceMappingURL=index.js.map