@willcgage/module-schematic 0.51.0 → 0.52.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 +162 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +111 -1
- package/dist/index.d.ts +111 -1
- package/dist/index.js +155 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1040,6 +1040,116 @@ declare const RAIL_GAUGE_INCHES = 0.354;
|
|
|
1040
1040
|
* #173) ⇒ 3.375 / 7. (The prototype #7 lead is 62′-1″ ≈ 4.66″ in N; commercial
|
|
1041
1041
|
* turnouts are compressed against that.) */
|
|
1042
1042
|
declare const TURNOUT_LEAD_INCHES_PER_FROG = 0.482;
|
|
1043
|
+
/** Where a dimension came from. `derived` = we computed it from another part or
|
|
1044
|
+
* a rule of thumb; `unverified` = plausible but unconfirmed — treat with care. */
|
|
1045
|
+
type DimensionSource = "manufacturer" | "measured" | "derived" | "unverified";
|
|
1046
|
+
interface PartDimension {
|
|
1047
|
+
inches: number;
|
|
1048
|
+
source: DimensionSource;
|
|
1049
|
+
/** Who measured it / which spec, so it can be re-checked. */
|
|
1050
|
+
note?: string;
|
|
1051
|
+
}
|
|
1052
|
+
interface TrackPart {
|
|
1053
|
+
/** Stable slug, e.g. "atlas-c55-n-7". */
|
|
1054
|
+
id: string;
|
|
1055
|
+
manufacturer: string;
|
|
1056
|
+
/** Product line — "Code 55", "Code 80". */
|
|
1057
|
+
line: string;
|
|
1058
|
+
scale: "N";
|
|
1059
|
+
name: string;
|
|
1060
|
+
kind: "turnout" | "wye" | "curved-turnout" | "crossing";
|
|
1061
|
+
/** Manufacturer part numbers by hand, where the part has a hand. */
|
|
1062
|
+
partNumbers?: {
|
|
1063
|
+
left?: string;
|
|
1064
|
+
right?: string;
|
|
1065
|
+
single?: string;
|
|
1066
|
+
};
|
|
1067
|
+
/** Frog number N (the 1:N ratio). Definitional, so no provenance needed. */
|
|
1068
|
+
frogNumber?: number;
|
|
1069
|
+
/** Points → frog. The number that decides where a turnout's throat lands. */
|
|
1070
|
+
lead?: PartDimension;
|
|
1071
|
+
/** End-to-end length of the part. */
|
|
1072
|
+
overallLength?: PartDimension;
|
|
1073
|
+
/** Diverging route radius (straight turnouts). */
|
|
1074
|
+
divergingRadius?: PartDimension;
|
|
1075
|
+
/** Curved turnouts: the two concentric radii. */
|
|
1076
|
+
outerRadius?: PartDimension;
|
|
1077
|
+
innerRadius?: PartDimension;
|
|
1078
|
+
/** Crossing angle, degrees. */
|
|
1079
|
+
crossingAngleDeg?: number;
|
|
1080
|
+
}
|
|
1081
|
+
/** N-scale code 55 rail height, inches — Atlas publish .055″. */
|
|
1082
|
+
declare const CODE55_RAIL_HEIGHT_INCHES = 0.055;
|
|
1083
|
+
/**
|
|
1084
|
+
* Atlas N-scale Code 55 — the Free-moN mainstay.
|
|
1085
|
+
*
|
|
1086
|
+
* ⚠️ Atlas do not publish leads or overall lengths for the straight turnouts.
|
|
1087
|
+
* The only hard datum is Steve Branton's measurement of a #7 (3⅜″ points→frog,
|
|
1088
|
+
* #173); the #5 and #10 leads are SCALED from it by frog number and are marked
|
|
1089
|
+
* `derived` for exactly that reason — they should be replaced with real
|
|
1090
|
+
* measurements when someone has the parts to hand.
|
|
1091
|
+
*/
|
|
1092
|
+
declare const ATLAS_CODE55_N: TrackPart[];
|
|
1093
|
+
/** Every built-in part, across manufacturers. */
|
|
1094
|
+
declare const BUILT_IN_TRACK_PARTS: TrackPart[];
|
|
1095
|
+
/** Look a part up by its slug. */
|
|
1096
|
+
declare function trackPart(id: string, library?: TrackPart[]): TrackPart | null;
|
|
1097
|
+
/** The closest built-in turnout for a frog number — what a bare `size` maps to
|
|
1098
|
+
* when a turnout names no part. Exact match wins; otherwise the nearest frog. */
|
|
1099
|
+
declare function turnoutPartForSize(size: number, library?: TrackPart[]): TrackPart | null;
|
|
1100
|
+
/** The lead to draw a turnout of this size with — a real part's measurement when
|
|
1101
|
+
* we have one, else the per-frog rule. Keeps `frogLegOf` honest without it
|
|
1102
|
+
* needing to know the library exists. */
|
|
1103
|
+
declare function leadInchesForSize(size: number, library?: TrackPart[]): number;
|
|
1104
|
+
/** One drawn piece of a part's geometry, in the part's own local frame. */
|
|
1105
|
+
type PartSegment = {
|
|
1106
|
+
kind: "straight";
|
|
1107
|
+
x0: number;
|
|
1108
|
+
y0: number;
|
|
1109
|
+
x1: number;
|
|
1110
|
+
y1: number;
|
|
1111
|
+
} | {
|
|
1112
|
+
kind: "curve";
|
|
1113
|
+
radius: number;
|
|
1114
|
+
cx: number;
|
|
1115
|
+
cy: number;
|
|
1116
|
+
startDeg: number;
|
|
1117
|
+
extentDeg: number;
|
|
1118
|
+
};
|
|
1119
|
+
/** A connection point on an imported part: position plus the tangent it faces. */
|
|
1120
|
+
interface PartEnd {
|
|
1121
|
+
x: number;
|
|
1122
|
+
y: number;
|
|
1123
|
+
angleDeg: number;
|
|
1124
|
+
}
|
|
1125
|
+
interface ImportedPart {
|
|
1126
|
+
/** Raw title, tab-separated in the file: manufacturer, name, part number. */
|
|
1127
|
+
title: string;
|
|
1128
|
+
manufacturer?: string;
|
|
1129
|
+
name?: string;
|
|
1130
|
+
partNumber?: string;
|
|
1131
|
+
scale?: string;
|
|
1132
|
+
ends: PartEnd[];
|
|
1133
|
+
segments: PartSegment[];
|
|
1134
|
+
}
|
|
1135
|
+
/**
|
|
1136
|
+
* Parse an XTrkCAD `.xtp` parameter file into parts.
|
|
1137
|
+
*
|
|
1138
|
+
* The format is plain text, record-per-line inside `TURNOUT … END` blocks:
|
|
1139
|
+
* `E x y angle` an endpoint
|
|
1140
|
+
* `S layer width x0 y0 x1 y1` a straight segment
|
|
1141
|
+
* `C layer width radius cx cy a0 ext` a curved segment (radius signed by hand)
|
|
1142
|
+
*
|
|
1143
|
+
* We parse an owner's OWN file — nothing from XTrkCAD is redistributed. Their
|
|
1144
|
+
* geometry is taken as authoritative for part OUTLINES; ⚠️ don't infer frog
|
|
1145
|
+
* positions from it, the shipped Atlas file is internally inconsistent (it puts
|
|
1146
|
+
* the #5's frog further out than the #7's, which is physically impossible).
|
|
1147
|
+
*/
|
|
1148
|
+
declare function parseXtpLibrary(text: string): ImportedPart[];
|
|
1149
|
+
/** Sample an imported part's segments into polylines, in the part's own frame —
|
|
1150
|
+
* XTrkCAD angles run CLOCKWISE FROM NORTH, so a point on a curve is
|
|
1151
|
+
* `(cx + r·sin a, cy + r·cos a)`, not the usual cos/sin. */
|
|
1152
|
+
declare function samplePartSegments(segments: PartSegment[], stepsPerCurve?: number): BenchworkPoint[][];
|
|
1043
1153
|
/** A turnout's CLOSURE — the diverging route's lateral offset from the through
|
|
1044
1154
|
* route, from the points (s = 0) to the frog (s = lead) and beyond.
|
|
1045
1155
|
*
|
|
@@ -1233,4 +1343,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
1233
1343
|
heading: number;
|
|
1234
1344
|
}>;
|
|
1235
1345
|
|
|
1236
|
-
export { type BenchworkPoint, type BranchConnector, 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 GeometryType, 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, 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 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, fromSectionRelative, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, remapPos, returnLoop, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, stateToDoc, toSectionRelative, trackMeetsEndplateIssues, trackPath, turnoutClosure };
|
|
1346
|
+
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 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 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, fromSectionRelative, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, leadInchesForSize, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, parseXtpLibrary, 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
|
@@ -1040,6 +1040,116 @@ declare const RAIL_GAUGE_INCHES = 0.354;
|
|
|
1040
1040
|
* #173) ⇒ 3.375 / 7. (The prototype #7 lead is 62′-1″ ≈ 4.66″ in N; commercial
|
|
1041
1041
|
* turnouts are compressed against that.) */
|
|
1042
1042
|
declare const TURNOUT_LEAD_INCHES_PER_FROG = 0.482;
|
|
1043
|
+
/** Where a dimension came from. `derived` = we computed it from another part or
|
|
1044
|
+
* a rule of thumb; `unverified` = plausible but unconfirmed — treat with care. */
|
|
1045
|
+
type DimensionSource = "manufacturer" | "measured" | "derived" | "unverified";
|
|
1046
|
+
interface PartDimension {
|
|
1047
|
+
inches: number;
|
|
1048
|
+
source: DimensionSource;
|
|
1049
|
+
/** Who measured it / which spec, so it can be re-checked. */
|
|
1050
|
+
note?: string;
|
|
1051
|
+
}
|
|
1052
|
+
interface TrackPart {
|
|
1053
|
+
/** Stable slug, e.g. "atlas-c55-n-7". */
|
|
1054
|
+
id: string;
|
|
1055
|
+
manufacturer: string;
|
|
1056
|
+
/** Product line — "Code 55", "Code 80". */
|
|
1057
|
+
line: string;
|
|
1058
|
+
scale: "N";
|
|
1059
|
+
name: string;
|
|
1060
|
+
kind: "turnout" | "wye" | "curved-turnout" | "crossing";
|
|
1061
|
+
/** Manufacturer part numbers by hand, where the part has a hand. */
|
|
1062
|
+
partNumbers?: {
|
|
1063
|
+
left?: string;
|
|
1064
|
+
right?: string;
|
|
1065
|
+
single?: string;
|
|
1066
|
+
};
|
|
1067
|
+
/** Frog number N (the 1:N ratio). Definitional, so no provenance needed. */
|
|
1068
|
+
frogNumber?: number;
|
|
1069
|
+
/** Points → frog. The number that decides where a turnout's throat lands. */
|
|
1070
|
+
lead?: PartDimension;
|
|
1071
|
+
/** End-to-end length of the part. */
|
|
1072
|
+
overallLength?: PartDimension;
|
|
1073
|
+
/** Diverging route radius (straight turnouts). */
|
|
1074
|
+
divergingRadius?: PartDimension;
|
|
1075
|
+
/** Curved turnouts: the two concentric radii. */
|
|
1076
|
+
outerRadius?: PartDimension;
|
|
1077
|
+
innerRadius?: PartDimension;
|
|
1078
|
+
/** Crossing angle, degrees. */
|
|
1079
|
+
crossingAngleDeg?: number;
|
|
1080
|
+
}
|
|
1081
|
+
/** N-scale code 55 rail height, inches — Atlas publish .055″. */
|
|
1082
|
+
declare const CODE55_RAIL_HEIGHT_INCHES = 0.055;
|
|
1083
|
+
/**
|
|
1084
|
+
* Atlas N-scale Code 55 — the Free-moN mainstay.
|
|
1085
|
+
*
|
|
1086
|
+
* ⚠️ Atlas do not publish leads or overall lengths for the straight turnouts.
|
|
1087
|
+
* The only hard datum is Steve Branton's measurement of a #7 (3⅜″ points→frog,
|
|
1088
|
+
* #173); the #5 and #10 leads are SCALED from it by frog number and are marked
|
|
1089
|
+
* `derived` for exactly that reason — they should be replaced with real
|
|
1090
|
+
* measurements when someone has the parts to hand.
|
|
1091
|
+
*/
|
|
1092
|
+
declare const ATLAS_CODE55_N: TrackPart[];
|
|
1093
|
+
/** Every built-in part, across manufacturers. */
|
|
1094
|
+
declare const BUILT_IN_TRACK_PARTS: TrackPart[];
|
|
1095
|
+
/** Look a part up by its slug. */
|
|
1096
|
+
declare function trackPart(id: string, library?: TrackPart[]): TrackPart | null;
|
|
1097
|
+
/** The closest built-in turnout for a frog number — what a bare `size` maps to
|
|
1098
|
+
* when a turnout names no part. Exact match wins; otherwise the nearest frog. */
|
|
1099
|
+
declare function turnoutPartForSize(size: number, library?: TrackPart[]): TrackPart | null;
|
|
1100
|
+
/** The lead to draw a turnout of this size with — a real part's measurement when
|
|
1101
|
+
* we have one, else the per-frog rule. Keeps `frogLegOf` honest without it
|
|
1102
|
+
* needing to know the library exists. */
|
|
1103
|
+
declare function leadInchesForSize(size: number, library?: TrackPart[]): number;
|
|
1104
|
+
/** One drawn piece of a part's geometry, in the part's own local frame. */
|
|
1105
|
+
type PartSegment = {
|
|
1106
|
+
kind: "straight";
|
|
1107
|
+
x0: number;
|
|
1108
|
+
y0: number;
|
|
1109
|
+
x1: number;
|
|
1110
|
+
y1: number;
|
|
1111
|
+
} | {
|
|
1112
|
+
kind: "curve";
|
|
1113
|
+
radius: number;
|
|
1114
|
+
cx: number;
|
|
1115
|
+
cy: number;
|
|
1116
|
+
startDeg: number;
|
|
1117
|
+
extentDeg: number;
|
|
1118
|
+
};
|
|
1119
|
+
/** A connection point on an imported part: position plus the tangent it faces. */
|
|
1120
|
+
interface PartEnd {
|
|
1121
|
+
x: number;
|
|
1122
|
+
y: number;
|
|
1123
|
+
angleDeg: number;
|
|
1124
|
+
}
|
|
1125
|
+
interface ImportedPart {
|
|
1126
|
+
/** Raw title, tab-separated in the file: manufacturer, name, part number. */
|
|
1127
|
+
title: string;
|
|
1128
|
+
manufacturer?: string;
|
|
1129
|
+
name?: string;
|
|
1130
|
+
partNumber?: string;
|
|
1131
|
+
scale?: string;
|
|
1132
|
+
ends: PartEnd[];
|
|
1133
|
+
segments: PartSegment[];
|
|
1134
|
+
}
|
|
1135
|
+
/**
|
|
1136
|
+
* Parse an XTrkCAD `.xtp` parameter file into parts.
|
|
1137
|
+
*
|
|
1138
|
+
* The format is plain text, record-per-line inside `TURNOUT … END` blocks:
|
|
1139
|
+
* `E x y angle` an endpoint
|
|
1140
|
+
* `S layer width x0 y0 x1 y1` a straight segment
|
|
1141
|
+
* `C layer width radius cx cy a0 ext` a curved segment (radius signed by hand)
|
|
1142
|
+
*
|
|
1143
|
+
* We parse an owner's OWN file — nothing from XTrkCAD is redistributed. Their
|
|
1144
|
+
* geometry is taken as authoritative for part OUTLINES; ⚠️ don't infer frog
|
|
1145
|
+
* positions from it, the shipped Atlas file is internally inconsistent (it puts
|
|
1146
|
+
* the #5's frog further out than the #7's, which is physically impossible).
|
|
1147
|
+
*/
|
|
1148
|
+
declare function parseXtpLibrary(text: string): ImportedPart[];
|
|
1149
|
+
/** Sample an imported part's segments into polylines, in the part's own frame —
|
|
1150
|
+
* XTrkCAD angles run CLOCKWISE FROM NORTH, so a point on a curve is
|
|
1151
|
+
* `(cx + r·sin a, cy + r·cos a)`, not the usual cos/sin. */
|
|
1152
|
+
declare function samplePartSegments(segments: PartSegment[], stepsPerCurve?: number): BenchworkPoint[][];
|
|
1043
1153
|
/** A turnout's CLOSURE — the diverging route's lateral offset from the through
|
|
1044
1154
|
* route, from the points (s = 0) to the frog (s = lead) and beyond.
|
|
1045
1155
|
*
|
|
@@ -1233,4 +1343,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
1233
1343
|
heading: number;
|
|
1234
1344
|
}>;
|
|
1235
1345
|
|
|
1236
|
-
export { type BenchworkPoint, type BranchConnector, 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 GeometryType, 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, 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 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, fromSectionRelative, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, remapPos, returnLoop, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, stateToDoc, toSectionRelative, trackMeetsEndplateIssues, trackPath, turnoutClosure };
|
|
1346
|
+
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 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 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, fromSectionRelative, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, leadInchesForSize, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, parseXtpLibrary, 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
|
@@ -1090,6 +1090,160 @@ function buildCrossover(state) {
|
|
|
1090
1090
|
}
|
|
1091
1091
|
var RAIL_GAUGE_INCHES = 0.354;
|
|
1092
1092
|
var TURNOUT_LEAD_INCHES_PER_FROG = 0.482;
|
|
1093
|
+
var CODE55_RAIL_HEIGHT_INCHES = 0.055;
|
|
1094
|
+
var ATLAS_CODE55_N = [
|
|
1095
|
+
{
|
|
1096
|
+
id: "atlas-c55-n-5",
|
|
1097
|
+
manufacturer: "Atlas",
|
|
1098
|
+
line: "Code 55",
|
|
1099
|
+
scale: "N",
|
|
1100
|
+
name: "#5 Turnout",
|
|
1101
|
+
kind: "turnout",
|
|
1102
|
+
partNumbers: { left: "2050", right: "2051" },
|
|
1103
|
+
frogNumber: 5,
|
|
1104
|
+
lead: {
|
|
1105
|
+
inches: 5 * TURNOUT_LEAD_INCHES_PER_FROG,
|
|
1106
|
+
source: "derived",
|
|
1107
|
+
note: "scaled from the measured #7 by frog number \u2014 not measured"
|
|
1108
|
+
}
|
|
1109
|
+
},
|
|
1110
|
+
{
|
|
1111
|
+
id: "atlas-c55-n-7",
|
|
1112
|
+
manufacturer: "Atlas",
|
|
1113
|
+
line: "Code 55",
|
|
1114
|
+
scale: "N",
|
|
1115
|
+
name: "#7 Turnout",
|
|
1116
|
+
kind: "turnout",
|
|
1117
|
+
partNumbers: { left: "2052", right: "2053" },
|
|
1118
|
+
frogNumber: 7,
|
|
1119
|
+
lead: {
|
|
1120
|
+
inches: 3.375,
|
|
1121
|
+
source: "measured",
|
|
1122
|
+
note: "Steve Branton, physical Atlas code 55 #7, 3\u215C\u2033 points\u2192frog (#173)"
|
|
1123
|
+
}
|
|
1124
|
+
},
|
|
1125
|
+
{
|
|
1126
|
+
id: "atlas-c55-n-10",
|
|
1127
|
+
manufacturer: "Atlas",
|
|
1128
|
+
line: "Code 55",
|
|
1129
|
+
scale: "N",
|
|
1130
|
+
name: "#10 Turnout",
|
|
1131
|
+
kind: "turnout",
|
|
1132
|
+
partNumbers: { left: "2054", right: "2055" },
|
|
1133
|
+
frogNumber: 10,
|
|
1134
|
+
lead: {
|
|
1135
|
+
inches: 10 * TURNOUT_LEAD_INCHES_PER_FROG,
|
|
1136
|
+
source: "derived",
|
|
1137
|
+
note: "scaled from the measured #7 by frog number \u2014 not measured"
|
|
1138
|
+
}
|
|
1139
|
+
},
|
|
1140
|
+
{
|
|
1141
|
+
id: "atlas-c55-n-wye",
|
|
1142
|
+
manufacturer: "Atlas",
|
|
1143
|
+
line: "Code 55",
|
|
1144
|
+
scale: "N",
|
|
1145
|
+
name: "#2.5 Wye",
|
|
1146
|
+
kind: "wye",
|
|
1147
|
+
partNumbers: { single: "2056" },
|
|
1148
|
+
frogNumber: 2.5,
|
|
1149
|
+
lead: {
|
|
1150
|
+
inches: 2.5 * TURNOUT_LEAD_INCHES_PER_FROG,
|
|
1151
|
+
source: "derived",
|
|
1152
|
+
note: "scaled from the measured #7 by frog number \u2014 not measured"
|
|
1153
|
+
}
|
|
1154
|
+
},
|
|
1155
|
+
{
|
|
1156
|
+
id: "atlas-c55-n-curved-21-15",
|
|
1157
|
+
manufacturer: "Atlas",
|
|
1158
|
+
line: "Code 55",
|
|
1159
|
+
scale: "N",
|
|
1160
|
+
name: 'Curved Turnout 21\xBC" / 15"',
|
|
1161
|
+
kind: "curved-turnout",
|
|
1162
|
+
partNumbers: { left: "2058", right: "2059" },
|
|
1163
|
+
outerRadius: { inches: 21.25, source: "manufacturer", note: "Atlas product listing" },
|
|
1164
|
+
innerRadius: { inches: 15, source: "manufacturer", note: "Atlas product listing" }
|
|
1165
|
+
}
|
|
1166
|
+
];
|
|
1167
|
+
var BUILT_IN_TRACK_PARTS = [...ATLAS_CODE55_N];
|
|
1168
|
+
function trackPart(id, library = BUILT_IN_TRACK_PARTS) {
|
|
1169
|
+
return library.find((p) => p.id === id) ?? null;
|
|
1170
|
+
}
|
|
1171
|
+
function turnoutPartForSize(size, library = BUILT_IN_TRACK_PARTS) {
|
|
1172
|
+
const turnouts = library.filter((p) => p.kind === "turnout" && p.frogNumber != null);
|
|
1173
|
+
if (!turnouts.length) return null;
|
|
1174
|
+
return turnouts.reduce(
|
|
1175
|
+
(best, p) => Math.abs(p.frogNumber - size) < Math.abs(best.frogNumber - size) ? p : best
|
|
1176
|
+
);
|
|
1177
|
+
}
|
|
1178
|
+
function leadInchesForSize(size, library = BUILT_IN_TRACK_PARTS) {
|
|
1179
|
+
const part = turnoutPartForSize(size, library);
|
|
1180
|
+
if (part?.lead && part.frogNumber === size) return part.lead.inches;
|
|
1181
|
+
return size * TURNOUT_LEAD_INCHES_PER_FROG;
|
|
1182
|
+
}
|
|
1183
|
+
function parseXtpLibrary(text) {
|
|
1184
|
+
const parts = [];
|
|
1185
|
+
let cur = null;
|
|
1186
|
+
for (const raw of text.split(/\r?\n/)) {
|
|
1187
|
+
const line = raw.trim();
|
|
1188
|
+
if (!line || line.startsWith("#")) continue;
|
|
1189
|
+
if (line.startsWith("TURNOUT")) {
|
|
1190
|
+
const quoted = line.match(/"([^"]*)"/);
|
|
1191
|
+
const scale = line.split(/\s+/)[1];
|
|
1192
|
+
const title = quoted?.[1] ?? "";
|
|
1193
|
+
const bits = title.split(" ").map((s) => s.trim()).filter(Boolean);
|
|
1194
|
+
cur = {
|
|
1195
|
+
title,
|
|
1196
|
+
scale,
|
|
1197
|
+
manufacturer: bits[0],
|
|
1198
|
+
name: bits[1],
|
|
1199
|
+
partNumber: bits[2],
|
|
1200
|
+
ends: [],
|
|
1201
|
+
segments: []
|
|
1202
|
+
};
|
|
1203
|
+
continue;
|
|
1204
|
+
}
|
|
1205
|
+
if (!cur) continue;
|
|
1206
|
+
if (line === "END") {
|
|
1207
|
+
if (cur.ends.length || cur.segments.length) parts.push(cur);
|
|
1208
|
+
cur = null;
|
|
1209
|
+
continue;
|
|
1210
|
+
}
|
|
1211
|
+
const n = line.split(/\s+/);
|
|
1212
|
+
const num = (i) => Number(n[i]);
|
|
1213
|
+
if (n[0] === "E" && n.length >= 4) {
|
|
1214
|
+
cur.ends.push({ x: num(1), y: num(2), angleDeg: num(3) });
|
|
1215
|
+
} else if (n[0] === "S" && n.length >= 7) {
|
|
1216
|
+
cur.segments.push({ kind: "straight", x0: num(3), y0: num(4), x1: num(5), y1: num(6) });
|
|
1217
|
+
} else if (n[0] === "C" && n.length >= 8) {
|
|
1218
|
+
cur.segments.push({
|
|
1219
|
+
kind: "curve",
|
|
1220
|
+
radius: num(3),
|
|
1221
|
+
cx: num(4),
|
|
1222
|
+
cy: num(5),
|
|
1223
|
+
startDeg: num(6),
|
|
1224
|
+
extentDeg: num(7)
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
return parts;
|
|
1229
|
+
}
|
|
1230
|
+
function samplePartSegments(segments, stepsPerCurve = 16) {
|
|
1231
|
+
return segments.map((s) => {
|
|
1232
|
+
if (s.kind === "straight") {
|
|
1233
|
+
return [
|
|
1234
|
+
{ x: s.x0, y: s.y0 },
|
|
1235
|
+
{ x: s.x1, y: s.y1 }
|
|
1236
|
+
];
|
|
1237
|
+
}
|
|
1238
|
+
const r = Math.abs(s.radius);
|
|
1239
|
+
const out = [];
|
|
1240
|
+
for (let i = 0; i <= stepsPerCurve; i++) {
|
|
1241
|
+
const a = (s.startDeg + s.extentDeg * i / stepsPerCurve) * Math.PI / 180;
|
|
1242
|
+
out.push({ x: s.cx + r * Math.sin(a), y: s.cy + r * Math.cos(a) });
|
|
1243
|
+
}
|
|
1244
|
+
return out;
|
|
1245
|
+
});
|
|
1246
|
+
}
|
|
1093
1247
|
function turnoutClosure(size, opts = {}) {
|
|
1094
1248
|
const N = size > 0 ? size : 6;
|
|
1095
1249
|
const g = opts.gaugeInches ?? RAIL_GAUGE_INCHES;
|
|
@@ -1619,6 +1773,6 @@ function poseOverridesFromDoc(doc) {
|
|
|
1619
1773
|
return out;
|
|
1620
1774
|
}
|
|
1621
1775
|
|
|
1622
|
-
export { 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, fromSectionRelative, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, remapPos, returnLoop, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionAdjacency, sectionBand, sectionBreaksFromSections, sectionComponents, sectionFootprints, sectionNeighbours, sectionSpans, sectionSpansOrWhole, sectionedCenterline, sectionedEndPose, sliceCenterline, stateToDoc, toSectionRelative, trackMeetsEndplateIssues, trackPath, turnoutClosure };
|
|
1776
|
+
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, fromSectionRelative, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, leadInchesForSize, moduleCenterline, moduleFeatures, moduleFootprint, moduleLengthFromSections, moduleSections, nextId, parseXtpLibrary, 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 };
|
|
1623
1777
|
//# sourceMappingURL=index.js.map
|
|
1624
1778
|
//# sourceMappingURL=index.js.map
|