@willcgage/module-schematic 0.60.0 → 0.62.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 +59 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -3
- package/dist/index.d.ts +57 -3
- package/dist/index.js +59 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -43,6 +43,19 @@ interface SchematicEndplate {
|
|
|
43
43
|
y: number;
|
|
44
44
|
heading: number;
|
|
45
45
|
};
|
|
46
|
+
/** Whether that pose was AUTHORED — placed or typed by the owner — rather
|
|
47
|
+
* than a derived one that found its way into the doc (#182).
|
|
48
|
+
*
|
|
49
|
+
* Authorship used to be inferred from `pose` merely existing, so a derived
|
|
50
|
+
* pose written back silently PINNED the plate: it stopped following the
|
|
51
|
+
* module and went stale the moment the length changed (FMN-0068 ended up with
|
|
52
|
+
* endplate B at x=48 on a 47.9″ board). A pose is only an override when the
|
|
53
|
+
* owner meant it.
|
|
54
|
+
*
|
|
55
|
+
* Absent on A/B = derived residue, ignored. Absent on a placed branch
|
|
56
|
+
* endplate (one with `at`) = still authored — placing it IS the gesture, and
|
|
57
|
+
* docs predate this flag. */
|
|
58
|
+
poseAuthored?: boolean;
|
|
46
59
|
/** Free-moN endplate FACE width across the track, inches — the physical size
|
|
47
60
|
* of the standard interface at this end. Free-moN spec: 12″ minimum, 24″
|
|
48
61
|
* recommended. Absent = the recommended default (modules may differ end to
|
|
@@ -394,6 +407,13 @@ declare function samplePath(pts: BenchworkPoint[], segsPerArc?: number): {
|
|
|
394
407
|
x: number;
|
|
395
408
|
y: number;
|
|
396
409
|
}[];
|
|
410
|
+
/**
|
|
411
|
+
* Arc length of an authored path, inches — the path's OWN length, independent of
|
|
412
|
+
* where it sits or which way it runs. A branch route to a third endplate (#181)
|
|
413
|
+
* has no meaningful extent along the module axis (a square 90° exit projects to
|
|
414
|
+
* zero), so its own length is the only honest measure of it.
|
|
415
|
+
*/
|
|
416
|
+
declare function pathLengthInches(path: BenchworkPoint[] | null | undefined): number;
|
|
397
417
|
/** Normalise an authored track path from a doc, or null if it isn't a real path
|
|
398
418
|
* (needs ≥ 2 valid points). Keeps per-vertex bulge. */
|
|
399
419
|
declare function trackPath(path: BenchworkPoint[] | null | undefined): BenchworkPoint[] | null;
|
|
@@ -951,13 +971,47 @@ interface DrawCrossover {
|
|
|
951
971
|
toPosFrac: number;
|
|
952
972
|
toLane: number;
|
|
953
973
|
}
|
|
954
|
-
/**
|
|
955
|
-
*
|
|
974
|
+
/**
|
|
975
|
+
* A route leaving the module at a third endplate (#170) — Main 3, whatever the
|
|
976
|
+
* owner labels it (#181). Drawn as an ELBOW: it diverges from its host main at
|
|
977
|
+
* `posFrac`, drops to its own `lane`, then runs to `endFrac` and ends at an
|
|
978
|
+
* endplate face.
|
|
979
|
+
*
|
|
980
|
+
* The run is the branch's OWN arc length laid along the strip, not its
|
|
981
|
+
* projection onto the module axis — a square 90° exit projects to zero, which
|
|
982
|
+
* is exactly the case that made branches invisible here. Straightening the
|
|
983
|
+
* route out at its true length is the same idiom this whole view applies to the
|
|
984
|
+
* main; `posFrac → endFrac` is therefore a real axis, and `lengthInches` maps
|
|
985
|
+
* onto it, so anything positioned along the branch has somewhere to draw.
|
|
986
|
+
*/
|
|
956
987
|
interface BranchConnector {
|
|
988
|
+
/** Endplate id — "C", "D", … */
|
|
957
989
|
id: string;
|
|
990
|
+
/** The endplate's label. MR draws no text (the destination depends on what's
|
|
991
|
+
* physically attached, so FD derives the panel label at runtime) — this is
|
|
992
|
+
* the owner's local name, for tooltips and FD's fallback. */
|
|
958
993
|
label: string;
|
|
994
|
+
/** The route's own name, from the track. */
|
|
995
|
+
name: string;
|
|
996
|
+
/** The branch track's id. */
|
|
997
|
+
trackId: string;
|
|
998
|
+
/** Whether the route IS a main (a diverging/split main) or a secondary
|
|
999
|
+
* branch line. Drives drawn weight, not geometry. */
|
|
1000
|
+
kind: "branch" | "main";
|
|
1001
|
+
/** Where it leaves its host main. */
|
|
959
1002
|
posFrac: number;
|
|
1003
|
+
/** The host track's lane — a branch need not leave Main 1. Renderers must
|
|
1004
|
+
* start the diverge HERE, not at a hard-coded lane 0. */
|
|
1005
|
+
fromLane: number;
|
|
1006
|
+
/** Which side of the module it exits. */
|
|
960
1007
|
side: "up" | "down";
|
|
1008
|
+
/** The branch's own lane, signed by `side` and placed clear of every other
|
|
1009
|
+
* lane (so it never collides) — already folded into laneMin/laneMax. */
|
|
1010
|
+
lane: number;
|
|
1011
|
+
/** Where the run ends, and the endplate face is drawn. */
|
|
1012
|
+
endFrac: number;
|
|
1013
|
+
/** The route's own arc length, inches. */
|
|
1014
|
+
lengthInches: number;
|
|
961
1015
|
}
|
|
962
1016
|
/** An industry — draw a car-spot span beside its track's lane, on `side`, with
|
|
963
1017
|
* a name label + an optional car/length readout (#industries). */
|
|
@@ -1583,4 +1637,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
1583
1637
|
heading: number;
|
|
1584
1638
|
}>;
|
|
1585
1639
|
|
|
1586
|
-
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, type BenchworkPoint, type BranchConnector, CODE55_RAIL_HEIGHT_INCHES, type DimensionSource, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, ENDPLATE_FASCIA_CLEAR_INCHES, ENDPLATE_LEAD_INCHES, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, type EndplateTrackIssue, type EndplateWidthIssue, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, type FrogCasting, type GeometryType, type ImportedPart, type IndustryLabelMode, type IndustrySpot, MAIN2_TRACK_ID, MAIN_TRACK_ID, type ModuleFeatures, type ModuleFootprint, type ModuleFootprintInput, type ModuleGeometryInput, type ModuleSchematicDoc, type ModuleTrackRow, N_CAR_LENGTH_INCHES, N_SCALE_RATIO, type OutlineFace, type PartAngle, type PartDimension, type PartEnd, type 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, TURNOUT_LEAD_INCHES_PER_FROG, type TrackConfig, type TrackPart, type TrackRole, type TurnoutClosure, type TurnoutKind, WHOLE_MODULE_SECTION_ID, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateLead, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, leadInchesForSize, mergeImportedParts, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, parseXtpLibrary, partOutlineAtFrog, poseNeedsManual, poseOverridesFromDoc, remapPos, returnLoop, sampleBenchworkOutline, samplePartSegments, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, stateToDoc, toSectionRelative, trackMeetsEndplateIssues, trackPart, trackPath, turnoutClosure, turnoutPartForSize };
|
|
1640
|
+
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, type BenchworkPoint, type BranchConnector, CODE55_RAIL_HEIGHT_INCHES, type DimensionSource, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, ENDPLATE_FASCIA_CLEAR_INCHES, ENDPLATE_LEAD_INCHES, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, type EndplateTrackIssue, type EndplateWidthIssue, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, type FrogCasting, type GeometryType, type ImportedPart, type IndustryLabelMode, type IndustrySpot, MAIN2_TRACK_ID, MAIN_TRACK_ID, type ModuleFeatures, type ModuleFootprint, type ModuleFootprintInput, type ModuleGeometryInput, type ModuleSchematicDoc, type ModuleTrackRow, N_CAR_LENGTH_INCHES, N_SCALE_RATIO, type OutlineFace, type PartAngle, type PartDimension, type PartEnd, type 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, TURNOUT_LEAD_INCHES_PER_FROG, type TrackConfig, type TrackPart, type TrackRole, type TurnoutClosure, type TurnoutKind, WHOLE_MODULE_SECTION_ID, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateLead, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, leadInchesForSize, mergeImportedParts, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, parseXtpLibrary, partOutlineAtFrog, pathLengthInches, poseNeedsManual, poseOverridesFromDoc, remapPos, returnLoop, sampleBenchworkOutline, samplePartSegments, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, stateToDoc, toSectionRelative, trackMeetsEndplateIssues, trackPart, trackPath, turnoutClosure, turnoutPartForSize };
|
package/dist/index.d.ts
CHANGED
|
@@ -43,6 +43,19 @@ interface SchematicEndplate {
|
|
|
43
43
|
y: number;
|
|
44
44
|
heading: number;
|
|
45
45
|
};
|
|
46
|
+
/** Whether that pose was AUTHORED — placed or typed by the owner — rather
|
|
47
|
+
* than a derived one that found its way into the doc (#182).
|
|
48
|
+
*
|
|
49
|
+
* Authorship used to be inferred from `pose` merely existing, so a derived
|
|
50
|
+
* pose written back silently PINNED the plate: it stopped following the
|
|
51
|
+
* module and went stale the moment the length changed (FMN-0068 ended up with
|
|
52
|
+
* endplate B at x=48 on a 47.9″ board). A pose is only an override when the
|
|
53
|
+
* owner meant it.
|
|
54
|
+
*
|
|
55
|
+
* Absent on A/B = derived residue, ignored. Absent on a placed branch
|
|
56
|
+
* endplate (one with `at`) = still authored — placing it IS the gesture, and
|
|
57
|
+
* docs predate this flag. */
|
|
58
|
+
poseAuthored?: boolean;
|
|
46
59
|
/** Free-moN endplate FACE width across the track, inches — the physical size
|
|
47
60
|
* of the standard interface at this end. Free-moN spec: 12″ minimum, 24″
|
|
48
61
|
* recommended. Absent = the recommended default (modules may differ end to
|
|
@@ -394,6 +407,13 @@ declare function samplePath(pts: BenchworkPoint[], segsPerArc?: number): {
|
|
|
394
407
|
x: number;
|
|
395
408
|
y: number;
|
|
396
409
|
}[];
|
|
410
|
+
/**
|
|
411
|
+
* Arc length of an authored path, inches — the path's OWN length, independent of
|
|
412
|
+
* where it sits or which way it runs. A branch route to a third endplate (#181)
|
|
413
|
+
* has no meaningful extent along the module axis (a square 90° exit projects to
|
|
414
|
+
* zero), so its own length is the only honest measure of it.
|
|
415
|
+
*/
|
|
416
|
+
declare function pathLengthInches(path: BenchworkPoint[] | null | undefined): number;
|
|
397
417
|
/** Normalise an authored track path from a doc, or null if it isn't a real path
|
|
398
418
|
* (needs ≥ 2 valid points). Keeps per-vertex bulge. */
|
|
399
419
|
declare function trackPath(path: BenchworkPoint[] | null | undefined): BenchworkPoint[] | null;
|
|
@@ -951,13 +971,47 @@ interface DrawCrossover {
|
|
|
951
971
|
toPosFrac: number;
|
|
952
972
|
toLane: number;
|
|
953
973
|
}
|
|
954
|
-
/**
|
|
955
|
-
*
|
|
974
|
+
/**
|
|
975
|
+
* A route leaving the module at a third endplate (#170) — Main 3, whatever the
|
|
976
|
+
* owner labels it (#181). Drawn as an ELBOW: it diverges from its host main at
|
|
977
|
+
* `posFrac`, drops to its own `lane`, then runs to `endFrac` and ends at an
|
|
978
|
+
* endplate face.
|
|
979
|
+
*
|
|
980
|
+
* The run is the branch's OWN arc length laid along the strip, not its
|
|
981
|
+
* projection onto the module axis — a square 90° exit projects to zero, which
|
|
982
|
+
* is exactly the case that made branches invisible here. Straightening the
|
|
983
|
+
* route out at its true length is the same idiom this whole view applies to the
|
|
984
|
+
* main; `posFrac → endFrac` is therefore a real axis, and `lengthInches` maps
|
|
985
|
+
* onto it, so anything positioned along the branch has somewhere to draw.
|
|
986
|
+
*/
|
|
956
987
|
interface BranchConnector {
|
|
988
|
+
/** Endplate id — "C", "D", … */
|
|
957
989
|
id: string;
|
|
990
|
+
/** The endplate's label. MR draws no text (the destination depends on what's
|
|
991
|
+
* physically attached, so FD derives the panel label at runtime) — this is
|
|
992
|
+
* the owner's local name, for tooltips and FD's fallback. */
|
|
958
993
|
label: string;
|
|
994
|
+
/** The route's own name, from the track. */
|
|
995
|
+
name: string;
|
|
996
|
+
/** The branch track's id. */
|
|
997
|
+
trackId: string;
|
|
998
|
+
/** Whether the route IS a main (a diverging/split main) or a secondary
|
|
999
|
+
* branch line. Drives drawn weight, not geometry. */
|
|
1000
|
+
kind: "branch" | "main";
|
|
1001
|
+
/** Where it leaves its host main. */
|
|
959
1002
|
posFrac: number;
|
|
1003
|
+
/** The host track's lane — a branch need not leave Main 1. Renderers must
|
|
1004
|
+
* start the diverge HERE, not at a hard-coded lane 0. */
|
|
1005
|
+
fromLane: number;
|
|
1006
|
+
/** Which side of the module it exits. */
|
|
960
1007
|
side: "up" | "down";
|
|
1008
|
+
/** The branch's own lane, signed by `side` and placed clear of every other
|
|
1009
|
+
* lane (so it never collides) — already folded into laneMin/laneMax. */
|
|
1010
|
+
lane: number;
|
|
1011
|
+
/** Where the run ends, and the endplate face is drawn. */
|
|
1012
|
+
endFrac: number;
|
|
1013
|
+
/** The route's own arc length, inches. */
|
|
1014
|
+
lengthInches: number;
|
|
961
1015
|
}
|
|
962
1016
|
/** An industry — draw a car-spot span beside its track's lane, on `side`, with
|
|
963
1017
|
* a name label + an optional car/length readout (#industries). */
|
|
@@ -1583,4 +1637,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
1583
1637
|
heading: number;
|
|
1584
1638
|
}>;
|
|
1585
1639
|
|
|
1586
|
-
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, type BenchworkPoint, type BranchConnector, CODE55_RAIL_HEIGHT_INCHES, type DimensionSource, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, ENDPLATE_FASCIA_CLEAR_INCHES, ENDPLATE_LEAD_INCHES, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, type EndplateTrackIssue, type EndplateWidthIssue, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, type FrogCasting, type GeometryType, type ImportedPart, type IndustryLabelMode, type IndustrySpot, MAIN2_TRACK_ID, MAIN_TRACK_ID, type ModuleFeatures, type ModuleFootprint, type ModuleFootprintInput, type ModuleGeometryInput, type ModuleSchematicDoc, type ModuleTrackRow, N_CAR_LENGTH_INCHES, N_SCALE_RATIO, type OutlineFace, type PartAngle, type PartDimension, type PartEnd, type 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, TURNOUT_LEAD_INCHES_PER_FROG, type TrackConfig, type TrackPart, type TrackRole, type TurnoutClosure, type TurnoutKind, WHOLE_MODULE_SECTION_ID, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateLead, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, leadInchesForSize, mergeImportedParts, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, parseXtpLibrary, partOutlineAtFrog, poseNeedsManual, poseOverridesFromDoc, remapPos, returnLoop, sampleBenchworkOutline, samplePartSegments, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, stateToDoc, toSectionRelative, trackMeetsEndplateIssues, trackPart, trackPath, turnoutClosure, turnoutPartForSize };
|
|
1640
|
+
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, type BenchworkPoint, type BranchConnector, CODE55_RAIL_HEIGHT_INCHES, type DimensionSource, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, ENDPLATE_FASCIA_CLEAR_INCHES, ENDPLATE_LEAD_INCHES, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, type EndplateTrackIssue, type EndplateWidthIssue, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, type FrogCasting, type GeometryType, type ImportedPart, type IndustryLabelMode, type IndustrySpot, MAIN2_TRACK_ID, MAIN_TRACK_ID, type ModuleFeatures, type ModuleFootprint, type ModuleFootprintInput, type ModuleGeometryInput, type ModuleSchematicDoc, type ModuleTrackRow, N_CAR_LENGTH_INCHES, N_SCALE_RATIO, type OutlineFace, type PartAngle, type PartDimension, type PartEnd, type 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, TURNOUT_LEAD_INCHES_PER_FROG, type TrackConfig, type TrackPart, type TrackRole, type TurnoutClosure, type TurnoutKind, WHOLE_MODULE_SECTION_ID, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateLead, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, leadInchesForSize, mergeImportedParts, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, parseXtpLibrary, partOutlineAtFrog, pathLengthInches, poseNeedsManual, poseOverridesFromDoc, remapPos, returnLoop, sampleBenchworkOutline, samplePartSegments, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, stateToDoc, toSectionRelative, trackMeetsEndplateIssues, trackPart, trackPath, turnoutClosure, turnoutPartForSize };
|
package/dist/index.js
CHANGED
|
@@ -115,6 +115,15 @@ function samplePath(pts, segsPerArc = 20) {
|
|
|
115
115
|
out.push({ x: pts[n - 1].x, y: pts[n - 1].y });
|
|
116
116
|
return out;
|
|
117
117
|
}
|
|
118
|
+
function pathLengthInches(path) {
|
|
119
|
+
const pts = trackPath(path);
|
|
120
|
+
if (!pts) return 0;
|
|
121
|
+
const poly = samplePath(pts);
|
|
122
|
+
let total = 0;
|
|
123
|
+
for (let i = 1; i < poly.length; i++)
|
|
124
|
+
total += Math.hypot(poly[i].x - poly[i - 1].x, poly[i].y - poly[i - 1].y);
|
|
125
|
+
return total;
|
|
126
|
+
}
|
|
118
127
|
function trackPath(path) {
|
|
119
128
|
const pts = (path ?? []).filter((p) => p && Number.isFinite(p.x) && Number.isFinite(p.y)).map((p) => ({
|
|
120
129
|
x: p.x,
|
|
@@ -658,7 +667,7 @@ function buildTransition(state) {
|
|
|
658
667
|
}
|
|
659
668
|
function withPoses(endplates, overrides) {
|
|
660
669
|
return endplates.map(
|
|
661
|
-
(e) => overrides[e.id] ? { ...e, pose: overrides[e.id] } : e
|
|
670
|
+
(e) => overrides[e.id] ? { ...e, pose: overrides[e.id], poseAuthored: true } : e
|
|
662
671
|
);
|
|
663
672
|
}
|
|
664
673
|
function withWidths(endplates, widths, offsets = {}) {
|
|
@@ -1680,15 +1689,43 @@ function moduleFeatures(doc) {
|
|
|
1680
1689
|
laneA: trackLane.get(x.tracks?.[0] ?? "") ?? 0,
|
|
1681
1690
|
laneB: trackLane.get(x.tracks?.[1] ?? "") ?? 1
|
|
1682
1691
|
}));
|
|
1692
|
+
const main2Lane = trackLane.has(MAIN2_TRACK_ID) ? trackLane.get(MAIN2_TRACK_ID) : null;
|
|
1693
|
+
const baseLanes = [
|
|
1694
|
+
0,
|
|
1695
|
+
main2Lane ?? (doubleMain ? 1 : 0),
|
|
1696
|
+
...extraTracks.map((t) => t.lane),
|
|
1697
|
+
...signals.map((s) => s.lane),
|
|
1698
|
+
...crossings.flatMap((x) => [x.laneA, x.laneB]),
|
|
1699
|
+
...crossovers.flatMap((x) => [x.fromLane, x.toLane])
|
|
1700
|
+
];
|
|
1701
|
+
let upLane = Math.max(...baseLanes, 0);
|
|
1702
|
+
let downLane = Math.min(...baseLanes, 0);
|
|
1683
1703
|
const branchConnectors = doc.endplates.filter(
|
|
1684
1704
|
(e) => e.id !== "A" && e.id !== "B" && e.at && !!e.trackId && (doc.tracks ?? []).some((t) => t.id === e.trackId)
|
|
1685
1705
|
).map((e) => {
|
|
1706
|
+
const trk = (doc.tracks ?? []).find((t) => t.id === e.trackId);
|
|
1686
1707
|
const sw = (doc.turnouts ?? []).find((t) => t.divergeTrack === e.trackId);
|
|
1708
|
+
const startPos = sw ? sw.pos : e.at.pos;
|
|
1709
|
+
const side = e.at.side === "down" ? "down" : "up";
|
|
1710
|
+
const lane = side === "down" ? --downLane : ++upLane;
|
|
1711
|
+
const runInches = pathLengthInches(trk.path) || Math.abs(e.at.pos - startPos) || FREEMO_ENDPLATE_WIDTH_MIN_INCHES;
|
|
1712
|
+
const toB = e.at.pos >= startPos;
|
|
1713
|
+
const fits = (p) => p >= 0 && p <= len;
|
|
1714
|
+
const ahead = startPos + runInches;
|
|
1715
|
+
const behind = startPos - runInches;
|
|
1716
|
+
const endPos = toB && fits(ahead) ? ahead : !toB && fits(behind) ? behind : fits(toB ? behind : ahead) ? toB ? behind : ahead : ahead;
|
|
1687
1717
|
return {
|
|
1688
1718
|
id: e.id,
|
|
1689
1719
|
label: e.label ?? e.id,
|
|
1690
|
-
|
|
1691
|
-
|
|
1720
|
+
name: trk.trackName ?? "",
|
|
1721
|
+
trackId: trk.id,
|
|
1722
|
+
kind: e.kind === "main" ? "main" : "branch",
|
|
1723
|
+
posFrac: clampFrac(startPos),
|
|
1724
|
+
fromLane: sw ? trackLane.get(sw.onTrack) ?? 0 : 0,
|
|
1725
|
+
side,
|
|
1726
|
+
lane,
|
|
1727
|
+
endFrac: clampFrac(endPos),
|
|
1728
|
+
lengthInches: runInches
|
|
1692
1729
|
};
|
|
1693
1730
|
});
|
|
1694
1731
|
const industries = (doc.industries ?? []).flatMap((ind) => {
|
|
@@ -1713,15 +1750,7 @@ function moduleFeatures(doc) {
|
|
|
1713
1750
|
};
|
|
1714
1751
|
});
|
|
1715
1752
|
});
|
|
1716
|
-
const
|
|
1717
|
-
const allLanes = [
|
|
1718
|
-
0,
|
|
1719
|
-
main2Lane ?? (doubleMain ? 1 : 0),
|
|
1720
|
-
...extraTracks.map((t) => t.lane),
|
|
1721
|
-
...signals.map((s) => s.lane),
|
|
1722
|
-
...crossings.flatMap((x) => [x.laneA, x.laneB]),
|
|
1723
|
-
...crossovers.flatMap((x) => [x.fromLane, x.toLane])
|
|
1724
|
-
];
|
|
1753
|
+
const allLanes = [...baseLanes, ...branchConnectors.map((b) => b.lane)];
|
|
1725
1754
|
const loop = isLoopDoc(doc);
|
|
1726
1755
|
const main2 = doc.tracks.find((t) => t.id === MAIN2_TRACK_ID);
|
|
1727
1756
|
const main2Positioned = !!main2 && (main2.fromPos != null || main2.toPos != null) && !loop;
|
|
@@ -2002,16 +2031,32 @@ function trackMeetsEndplateIssues(path, pose, opts) {
|
|
|
2002
2031
|
function poseNeedsManual(geometryType) {
|
|
2003
2032
|
return geometryType === "wye" || geometryType === "other";
|
|
2004
2033
|
}
|
|
2034
|
+
function isAxialPose(p) {
|
|
2035
|
+
const h = norm360(p.heading);
|
|
2036
|
+
return Math.abs(p.y) < 1e-6 && (Math.abs(h) < 1e-6 || Math.abs(h - 180) < 1e-6);
|
|
2037
|
+
}
|
|
2005
2038
|
function poseOverridesFromDoc(doc) {
|
|
2006
2039
|
const out = {};
|
|
2007
2040
|
for (const e of doc.endplates ?? []) {
|
|
2008
|
-
if (e.id && e.pose && typeof e.pose.x === "number" && typeof e.pose.y === "number" && typeof e.pose.heading === "number")
|
|
2041
|
+
if (e.id && e.pose && typeof e.pose.x === "number" && typeof e.pose.y === "number" && typeof e.pose.heading === "number" && // Only an AUTHORED pose overrides derivation (#182) — but docs written
|
|
2042
|
+
// before the flag existed have to keep working, so authorship is inferred
|
|
2043
|
+
// for the two cases that can only BE authored:
|
|
2044
|
+
// · a placed branch endplate (`at`) — dropping it on the board is the
|
|
2045
|
+
// gesture, and it has no derivable position at all;
|
|
2046
|
+
// · an OFF-AXIS pose on A/B — a hand-placed plate is off-axis by
|
|
2047
|
+
// definition (that's why it needed hand placing, e.g. a wye's B).
|
|
2048
|
+
// What's left is an axial A/B pose, which is exactly the shape plain
|
|
2049
|
+
// derivation produces — residue. Honouring it silently pins the plate so
|
|
2050
|
+
// it stops following the module and goes stale (FMN-0068's B sat at 48 on
|
|
2051
|
+
// a 47.9″ board). Anything saved from now on carries the flag, so this
|
|
2052
|
+
// guesswork only ever applies to old docs.
|
|
2053
|
+
(e.poseAuthored === true || !!e.at || !isAxialPose(e.pose))) {
|
|
2009
2054
|
out[e.id] = { x: e.pose.x, y: e.pose.y, heading: e.pose.heading };
|
|
2010
2055
|
}
|
|
2011
2056
|
}
|
|
2012
2057
|
return out;
|
|
2013
2058
|
}
|
|
2014
2059
|
|
|
2015
|
-
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, CODE55_RAIL_HEIGHT_INCHES, ENDPLATE_FASCIA_CLEAR_INCHES, ENDPLATE_LEAD_INCHES, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, MAIN2_TRACK_ID, MAIN_TRACK_ID, N_CAR_LENGTH_INCHES, N_SCALE_RATIO, RAIL_GAUGE_INCHES, TURNOUT_LEAD_INCHES_PER_FROG, WHOLE_MODULE_SECTION_ID, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateLead, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, leadInchesForSize, mergeImportedParts, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, parseXtpLibrary, partOutlineAtFrog, poseNeedsManual, poseOverridesFromDoc, remapPos, returnLoop, sampleBenchworkOutline, samplePartSegments, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, stateToDoc, toSectionRelative, trackMeetsEndplateIssues, trackPart, trackPath, turnoutClosure, turnoutPartForSize };
|
|
2060
|
+
export { ATLAS_CODE55_N, BUILT_IN_TRACK_PARTS, CODE55_RAIL_HEIGHT_INCHES, ENDPLATE_FASCIA_CLEAR_INCHES, ENDPLATE_LEAD_INCHES, FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, FREEMO_TRACK_SPACING_INCHES, MAIN2_TRACK_ID, MAIN_TRACK_ID, N_CAR_LENGTH_INCHES, N_SCALE_RATIO, RAIL_GAUGE_INCHES, TURNOUT_LEAD_INCHES_PER_FROG, WHOLE_MODULE_SECTION_ID, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateLead, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, frogCasting, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, leadInchesForSize, mergeImportedParts, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, parseXtpLibrary, partOutlineAtFrog, pathLengthInches, poseNeedsManual, poseOverridesFromDoc, remapPos, returnLoop, sampleBenchworkOutline, samplePartSegments, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, stateToDoc, toSectionRelative, trackMeetsEndplateIssues, trackPart, trackPath, turnoutClosure, turnoutPartForSize };
|
|
2016
2061
|
//# sourceMappingURL=index.js.map
|
|
2017
2062
|
//# sourceMappingURL=index.js.map
|