@willcgage/module-schematic 0.91.0 → 0.92.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
@@ -2465,8 +2465,27 @@ interface TrackPiece {
2465
2465
  rotationDeg: number;
2466
2466
  /** Mirrored across its own through route — a left-hand turnout from a right. */
2467
2467
  flipped?: boolean;
2468
- /** FLEX ONLY: how long this run is. The one piece a builder cuts (ADR 0001). */
2468
+ /** FLEX ONLY: how long this run is. The one piece a builder cuts (ADR 0001).
2469
+ * ⚠️ ARC length when the run is bent — the rail, not the chord across it. */
2469
2470
  lengthInches?: number;
2471
+ /**
2472
+ * FLEX ONLY: the radius this run is bent to, inches. Absent = straight.
2473
+ *
2474
+ * ⭐ It lives on the PIECE, not the part, because bending flex is what a
2475
+ * builder does to it — the product is the same product either way. That is
2476
+ * the same reason `lengthInches` is here.
2477
+ *
2478
+ * ⭐ SIGNED, and the sign IS the side: positive curves toward +y in the
2479
+ * piece's own frame, negative the other way. One number, no separate
2480
+ * "direction" field to disagree with it — the same reasoning that keeps a
2481
+ * hand off turnouts, where the side is simply where the piece is.
2482
+ *
2483
+ * ⚠️ {@link lengthInches} stays the ARC length. `pos` is arc length
2484
+ * everywhere in this model, a curve's rail is genuinely longer than the chord
2485
+ * it spans (a 90° corner at R30 runs 47.1″ across a 42.4″ chord), and it is
2486
+ * the rail a train travels.
2487
+ */
2488
+ radiusInches?: number;
2470
2489
  /** Owner's label, carried onto whatever route this piece ends up in. */
2471
2490
  name?: string;
2472
2491
  }
@@ -2519,6 +2538,19 @@ interface TrackGraph {
2519
2538
  * tight enough that nothing joins by accident, loose enough to absorb the
2520
2539
  * rounding of a drag. */
2521
2540
  declare const JOINT_SNAP_INCHES = 0.01;
2541
+ /**
2542
+ * Where a bent run's far end lands, and which way it points — in the piece's own
2543
+ * frame, starting at its origin heading +x.
2544
+ *
2545
+ * ONE definition, called by both {@link placedJoints} and
2546
+ * {@link pieceRoutePaths}, so the drawn rail cannot arrive anywhere other than
2547
+ * the joint at the end of it.
2548
+ */
2549
+ declare function flexRunEnd(lengthInches: number, radiusInches?: number): {
2550
+ x: number;
2551
+ y: number;
2552
+ headingDeg: number;
2553
+ };
2522
2554
  /** Every piece's joints, transformed onto the board. */
2523
2555
  declare function placedJoints(pieces: TrackPiece[], library?: TrackPart[]): PlacedJoint[];
2524
2556
  /**
@@ -2986,4 +3018,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
2986
3018
  heading: number;
2987
3019
  }>;
2988
3020
 
2989
- 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_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, flexPartFor, flexParts, flexPieces, 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, 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 };
3021
+ 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_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, 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, 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
@@ -2465,8 +2465,27 @@ interface TrackPiece {
2465
2465
  rotationDeg: number;
2466
2466
  /** Mirrored across its own through route — a left-hand turnout from a right. */
2467
2467
  flipped?: boolean;
2468
- /** FLEX ONLY: how long this run is. The one piece a builder cuts (ADR 0001). */
2468
+ /** FLEX ONLY: how long this run is. The one piece a builder cuts (ADR 0001).
2469
+ * ⚠️ ARC length when the run is bent — the rail, not the chord across it. */
2469
2470
  lengthInches?: number;
2471
+ /**
2472
+ * FLEX ONLY: the radius this run is bent to, inches. Absent = straight.
2473
+ *
2474
+ * ⭐ It lives on the PIECE, not the part, because bending flex is what a
2475
+ * builder does to it — the product is the same product either way. That is
2476
+ * the same reason `lengthInches` is here.
2477
+ *
2478
+ * ⭐ SIGNED, and the sign IS the side: positive curves toward +y in the
2479
+ * piece's own frame, negative the other way. One number, no separate
2480
+ * "direction" field to disagree with it — the same reasoning that keeps a
2481
+ * hand off turnouts, where the side is simply where the piece is.
2482
+ *
2483
+ * ⚠️ {@link lengthInches} stays the ARC length. `pos` is arc length
2484
+ * everywhere in this model, a curve's rail is genuinely longer than the chord
2485
+ * it spans (a 90° corner at R30 runs 47.1″ across a 42.4″ chord), and it is
2486
+ * the rail a train travels.
2487
+ */
2488
+ radiusInches?: number;
2470
2489
  /** Owner's label, carried onto whatever route this piece ends up in. */
2471
2490
  name?: string;
2472
2491
  }
@@ -2519,6 +2538,19 @@ interface TrackGraph {
2519
2538
  * tight enough that nothing joins by accident, loose enough to absorb the
2520
2539
  * rounding of a drag. */
2521
2540
  declare const JOINT_SNAP_INCHES = 0.01;
2541
+ /**
2542
+ * Where a bent run's far end lands, and which way it points — in the piece's own
2543
+ * frame, starting at its origin heading +x.
2544
+ *
2545
+ * ONE definition, called by both {@link placedJoints} and
2546
+ * {@link pieceRoutePaths}, so the drawn rail cannot arrive anywhere other than
2547
+ * the joint at the end of it.
2548
+ */
2549
+ declare function flexRunEnd(lengthInches: number, radiusInches?: number): {
2550
+ x: number;
2551
+ y: number;
2552
+ headingDeg: number;
2553
+ };
2522
2554
  /** Every piece's joints, transformed onto the board. */
2523
2555
  declare function placedJoints(pieces: TrackPiece[], library?: TrackPart[]): PlacedJoint[];
2524
2556
  /**
@@ -2986,4 +3018,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
2986
3018
  heading: number;
2987
3019
  }>;
2988
3020
 
2989
- 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_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, flexPartFor, flexParts, flexPieces, 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, 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 };
3021
+ 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_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, 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, 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
@@ -2266,8 +2266,16 @@ function pieceRoutePaths(piece, library = BUILT_IN_TRACK_PARTS) {
2266
2266
  const b = at(route[1]);
2267
2267
  if (!a || !b) continue;
2268
2268
  const ends = [{ x: a.x, y: a.y }, { x: b.x, y: b.y }];
2269
+ if (part.kind === "flex") {
2270
+ const pts2 = flexRunPoints(piece.lengthInches ?? 0, piece.radiusInches).map(
2271
+ (q) => place(q.x, q.y)
2272
+ );
2273
+ pts2[pts2.length - 1] = { x: b.x, y: b.y };
2274
+ out.push({ route, points: pts2 });
2275
+ continue;
2276
+ }
2269
2277
  const diverging = route.some((r) => r === "diverge" || r === "legA" || r === "legB");
2270
- if (!diverging || part.kind === "flex") {
2278
+ if (!diverging) {
2271
2279
  out.push({ route, points: ends });
2272
2280
  continue;
2273
2281
  }
@@ -2306,6 +2314,25 @@ function partsPlaceable(library = BUILT_IN_TRACK_PARTS) {
2306
2314
  return { placeable, blocked };
2307
2315
  }
2308
2316
  var JOINT_SNAP_INCHES = 0.01;
2317
+ function flexRunEnd(lengthInches, radiusInches) {
2318
+ const L = lengthInches;
2319
+ const R = radiusInches;
2320
+ if (!R || !Number.isFinite(R) || Math.abs(R) < 1e-6)
2321
+ return { x: L, y: 0, headingDeg: 0 };
2322
+ const theta = L / R;
2323
+ return {
2324
+ x: Math.abs(R) * Math.sin(Math.abs(theta)) * Math.sign(L || 1),
2325
+ y: R * (1 - Math.cos(theta)),
2326
+ headingDeg: theta * 180 / Math.PI
2327
+ };
2328
+ }
2329
+ function flexRunPoints(lengthInches, radiusInches, steps = 16) {
2330
+ if (!radiusInches || !Number.isFinite(radiusInches) || Math.abs(radiusInches) < 1e-6)
2331
+ return [{ x: 0, y: 0 }, { x: lengthInches, y: 0 }];
2332
+ const out = [];
2333
+ for (let i = 0; i <= steps; i++) out.push(flexRunEnd(lengthInches * i / steps, radiusInches));
2334
+ return out.map((p) => ({ x: p.x, y: p.y }));
2335
+ }
2309
2336
  function placedJoints(pieces, library = BUILT_IN_TRACK_PARTS) {
2310
2337
  const out = [];
2311
2338
  const RAD = Math.PI / 180;
@@ -2316,10 +2343,13 @@ function placedJoints(pieces, library = BUILT_IN_TRACK_PARTS) {
2316
2343
  if (!geo) continue;
2317
2344
  const c = Math.cos(p.rotationDeg * RAD);
2318
2345
  const s = Math.sin(p.rotationDeg * RAD);
2346
+ const run = part.kind === "flex" ? flexRunEnd(p.lengthInches ?? 0, p.radiusInches) : null;
2319
2347
  for (const j of geo.joints) {
2320
- const lx = part.kind === "flex" && j.id === "b" ? p.lengthInches ?? 0 : j.x;
2321
- const ly = p.flipped ? -j.y : j.y;
2322
- const h = (p.flipped ? -j.angleDeg : j.angleDeg) + p.rotationDeg;
2348
+ const far = run && j.id === "b";
2349
+ const lx = far ? run.x : j.x;
2350
+ const ly = p.flipped ? -(far ? run.y : j.y) : far ? run.y : j.y;
2351
+ const local = far ? run.headingDeg : j.angleDeg;
2352
+ const h = (p.flipped ? -local : local) + p.rotationDeg;
2323
2353
  out.push({
2324
2354
  key: `${p.id}.${j.id}`,
2325
2355
  piece: p.id,
@@ -2425,7 +2455,15 @@ function walkTrackGraph(graph, pieces, startAt, library = BUILT_IN_TRACK_PARTS)
2425
2455
  const part = partOf(pid);
2426
2456
  return part ? partGeometry(part, library) : null;
2427
2457
  };
2428
- const gap = (a, b) => a && b ? Math.hypot(a.x - b.x, a.y - b.y) : 0;
2458
+ const gap = (a, b) => {
2459
+ if (!a || !b) return 0;
2460
+ if (a.piece === b.piece) {
2461
+ const piece = pieceById.get(a.piece);
2462
+ const part = piece ? partOf(a.piece) : void 0;
2463
+ if (piece && part?.kind === "flex") return piece.lengthInches ?? 0;
2464
+ }
2465
+ return Math.hypot(a.x - b.x, a.y - b.y);
2466
+ };
2429
2467
  const routes = [];
2430
2468
  const turnouts = [];
2431
2469
  const warnings = [];
@@ -3325,6 +3363,6 @@ function poseOverridesFromDoc(doc) {
3325
3363
  return out;
3326
3364
  }
3327
3365
 
3328
- export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, CLEARANCE_SPACING_INCHES, CODE55_RAIL_HEIGHT_INCHES, DEFAULT_FLEX_PART_ID, ENDPLATE_FASCIA_CLEAR_INCHES, ENDPLATE_LEAD_INCHES, FAST_TRACKS_N_ME55, FAST_TRACKS_N_ME55_CROSSOVERS, FLEX_TRACK_PARTS, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, 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, flexPartFor, flexParts, flexPieces, 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, 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 };
3366
+ export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, CLEARANCE_SPACING_INCHES, CODE55_RAIL_HEIGHT_INCHES, DEFAULT_FLEX_PART_ID, ENDPLATE_FASCIA_CLEAR_INCHES, ENDPLATE_LEAD_INCHES, FAST_TRACKS_N_ME55, FAST_TRACKS_N_ME55_CROSSOVERS, FLEX_TRACK_PARTS, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, 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, 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, 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 };
3329
3367
  //# sourceMappingURL=index.js.map
3330
3368
  //# sourceMappingURL=index.js.map