@willcgage/module-schematic 0.56.0 → 0.57.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 +82 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -1
- package/dist/index.d.ts +43 -1
- package/dist/index.js +80 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1128,6 +1128,16 @@ interface TrackPart {
|
|
|
1128
1128
|
innerRadius?: PartDimension;
|
|
1129
1129
|
/** Crossing angle, degrees. */
|
|
1130
1130
|
crossingAngleDeg?: number;
|
|
1131
|
+
/** The part's drawn geometry in its own frame, when it came from a library
|
|
1132
|
+
* file. This is the payload worth importing — real outlines we can draw
|
|
1133
|
+
* instead of deriving a turnout's shape from a frog number. */
|
|
1134
|
+
segments?: PartSegment[];
|
|
1135
|
+
/** Connection points, each carrying position AND tangent. The seam a piece
|
|
1136
|
+
* graph would snap on (#179 stage 1-2). */
|
|
1137
|
+
ends?: PartEnd[];
|
|
1138
|
+
/** Set when the part came from an imported library file rather than our own
|
|
1139
|
+
* data — names the source so a user can tell where a dimension came from. */
|
|
1140
|
+
importedFrom?: string;
|
|
1131
1141
|
}
|
|
1132
1142
|
/** N-scale code 55 rail height, inches — Atlas publish .055″. */
|
|
1133
1143
|
declare const CODE55_RAIL_HEIGHT_INCHES = 0.055;
|
|
@@ -1257,6 +1267,38 @@ declare function parseXtpLibrary(text: string): ImportedPart[];
|
|
|
1257
1267
|
* XTrkCAD angles run CLOCKWISE FROM NORTH, so a point on a curve is
|
|
1258
1268
|
* `(cx + r·sin a, cy + r·cos a)`, not the usual cos/sin. */
|
|
1259
1269
|
declare function samplePartSegments(segments: PartSegment[], stepsPerCurve?: number): BenchworkPoint[][];
|
|
1270
|
+
/** Pull a frog number out of a part name — "#5", "No. 5", "Number 7 Left".
|
|
1271
|
+
* Identification, not measurement: it reads the label the maker printed. */
|
|
1272
|
+
declare function frogNumberFromName(name: string | undefined): number | undefined;
|
|
1273
|
+
/**
|
|
1274
|
+
* Convert a parsed `.xtp` part into a library {@link TrackPart}.
|
|
1275
|
+
*
|
|
1276
|
+
* ⚠️⚠️ **DELIBERATELY DERIVES NO `lead` AND NO `frogOffset`.** The shipped Atlas
|
|
1277
|
+
* file's frog positions are internally inconsistent — it puts the #5's frog
|
|
1278
|
+
* FURTHER OUT than the #7's, which cannot be true of physical parts. Every lead
|
|
1279
|
+
* in this library is a physical measurement and must stay that way; an imported
|
|
1280
|
+
* lead would silently outrank {@link leadInchesForSize}'s interpolation across
|
|
1281
|
+
* those measurements, which is exactly the wrong trade.
|
|
1282
|
+
*
|
|
1283
|
+
* What IS taken: identity (manufacturer, name, part number, frog number), the
|
|
1284
|
+
* drawn `segments` and `ends`, and two dimensions the geometry states directly —
|
|
1285
|
+
* overall length along the through axis, and the actual divergence angle. Both
|
|
1286
|
+
* land as `unverified`, because a community CAD file is not a measurement.
|
|
1287
|
+
*/
|
|
1288
|
+
declare function importedPartToTrackPart(part: ImportedPart, sourceName?: string): TrackPart;
|
|
1289
|
+
/**
|
|
1290
|
+
* Fold imported parts into a library.
|
|
1291
|
+
*
|
|
1292
|
+
* **Imports never overwrite. Ever.** They may only fill a gap — attach geometry
|
|
1293
|
+
* a built-in lacks, or add a part we have no entry for. A dimension already
|
|
1294
|
+
* present wins regardless of its source, because our worst built-in value is at
|
|
1295
|
+
* least one we can trace, and this library has already been burned once by a
|
|
1296
|
+
* plausible number from a CAD file (the constant-switch-angle model was fitted
|
|
1297
|
+
* to an `.xtp` figure that turned out to be measured to the wrong landmark).
|
|
1298
|
+
*
|
|
1299
|
+
* Matching is by manufacturer part number first, then manufacturer + frog number.
|
|
1300
|
+
*/
|
|
1301
|
+
declare function mergeImportedParts(imported: ImportedPart[], library?: TrackPart[], sourceName?: string): TrackPart[];
|
|
1260
1302
|
/** A turnout's CLOSURE — the diverging route's lateral offset from the through
|
|
1261
1303
|
* route, from the points (s = 0) to the frog (s = lead) and beyond.
|
|
1262
1304
|
*
|
|
@@ -1450,4 +1492,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
1450
1492
|
heading: number;
|
|
1451
1493
|
}>;
|
|
1452
1494
|
|
|
1453
|
-
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 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, 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 };
|
|
1495
|
+
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 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, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, leadInchesForSize, mergeImportedParts, 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
|
@@ -1128,6 +1128,16 @@ interface TrackPart {
|
|
|
1128
1128
|
innerRadius?: PartDimension;
|
|
1129
1129
|
/** Crossing angle, degrees. */
|
|
1130
1130
|
crossingAngleDeg?: number;
|
|
1131
|
+
/** The part's drawn geometry in its own frame, when it came from a library
|
|
1132
|
+
* file. This is the payload worth importing — real outlines we can draw
|
|
1133
|
+
* instead of deriving a turnout's shape from a frog number. */
|
|
1134
|
+
segments?: PartSegment[];
|
|
1135
|
+
/** Connection points, each carrying position AND tangent. The seam a piece
|
|
1136
|
+
* graph would snap on (#179 stage 1-2). */
|
|
1137
|
+
ends?: PartEnd[];
|
|
1138
|
+
/** Set when the part came from an imported library file rather than our own
|
|
1139
|
+
* data — names the source so a user can tell where a dimension came from. */
|
|
1140
|
+
importedFrom?: string;
|
|
1131
1141
|
}
|
|
1132
1142
|
/** N-scale code 55 rail height, inches — Atlas publish .055″. */
|
|
1133
1143
|
declare const CODE55_RAIL_HEIGHT_INCHES = 0.055;
|
|
@@ -1257,6 +1267,38 @@ declare function parseXtpLibrary(text: string): ImportedPart[];
|
|
|
1257
1267
|
* XTrkCAD angles run CLOCKWISE FROM NORTH, so a point on a curve is
|
|
1258
1268
|
* `(cx + r·sin a, cy + r·cos a)`, not the usual cos/sin. */
|
|
1259
1269
|
declare function samplePartSegments(segments: PartSegment[], stepsPerCurve?: number): BenchworkPoint[][];
|
|
1270
|
+
/** Pull a frog number out of a part name — "#5", "No. 5", "Number 7 Left".
|
|
1271
|
+
* Identification, not measurement: it reads the label the maker printed. */
|
|
1272
|
+
declare function frogNumberFromName(name: string | undefined): number | undefined;
|
|
1273
|
+
/**
|
|
1274
|
+
* Convert a parsed `.xtp` part into a library {@link TrackPart}.
|
|
1275
|
+
*
|
|
1276
|
+
* ⚠️⚠️ **DELIBERATELY DERIVES NO `lead` AND NO `frogOffset`.** The shipped Atlas
|
|
1277
|
+
* file's frog positions are internally inconsistent — it puts the #5's frog
|
|
1278
|
+
* FURTHER OUT than the #7's, which cannot be true of physical parts. Every lead
|
|
1279
|
+
* in this library is a physical measurement and must stay that way; an imported
|
|
1280
|
+
* lead would silently outrank {@link leadInchesForSize}'s interpolation across
|
|
1281
|
+
* those measurements, which is exactly the wrong trade.
|
|
1282
|
+
*
|
|
1283
|
+
* What IS taken: identity (manufacturer, name, part number, frog number), the
|
|
1284
|
+
* drawn `segments` and `ends`, and two dimensions the geometry states directly —
|
|
1285
|
+
* overall length along the through axis, and the actual divergence angle. Both
|
|
1286
|
+
* land as `unverified`, because a community CAD file is not a measurement.
|
|
1287
|
+
*/
|
|
1288
|
+
declare function importedPartToTrackPart(part: ImportedPart, sourceName?: string): TrackPart;
|
|
1289
|
+
/**
|
|
1290
|
+
* Fold imported parts into a library.
|
|
1291
|
+
*
|
|
1292
|
+
* **Imports never overwrite. Ever.** They may only fill a gap — attach geometry
|
|
1293
|
+
* a built-in lacks, or add a part we have no entry for. A dimension already
|
|
1294
|
+
* present wins regardless of its source, because our worst built-in value is at
|
|
1295
|
+
* least one we can trace, and this library has already been burned once by a
|
|
1296
|
+
* plausible number from a CAD file (the constant-switch-angle model was fitted
|
|
1297
|
+
* to an `.xtp` figure that turned out to be measured to the wrong landmark).
|
|
1298
|
+
*
|
|
1299
|
+
* Matching is by manufacturer part number first, then manufacturer + frog number.
|
|
1300
|
+
*/
|
|
1301
|
+
declare function mergeImportedParts(imported: ImportedPart[], library?: TrackPart[], sourceName?: string): TrackPart[];
|
|
1260
1302
|
/** A turnout's CLOSURE — the diverging route's lateral offset from the through
|
|
1261
1303
|
* route, from the points (s = 0) to the frog (s = lead) and beyond.
|
|
1262
1304
|
*
|
|
@@ -1450,4 +1492,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
1450
1492
|
heading: number;
|
|
1451
1493
|
}>;
|
|
1452
1494
|
|
|
1453
|
-
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 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, 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 };
|
|
1495
|
+
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 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, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, leadInchesForSize, mergeImportedParts, 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
|
@@ -1318,6 +1318,85 @@ function samplePartSegments(segments, stepsPerCurve = 16) {
|
|
|
1318
1318
|
return out;
|
|
1319
1319
|
});
|
|
1320
1320
|
}
|
|
1321
|
+
function angleDeltaDeg(a, b) {
|
|
1322
|
+
let d = ((a - b) % 360 + 540) % 360 - 180;
|
|
1323
|
+
if (d === -180) d = 180;
|
|
1324
|
+
return d;
|
|
1325
|
+
}
|
|
1326
|
+
function frogNumberFromName(name) {
|
|
1327
|
+
if (!name) return void 0;
|
|
1328
|
+
const m = name.match(/(?:#|no\.?\s*|number\s+)(\d+(?:\.\d+)?)/i);
|
|
1329
|
+
if (!m) return void 0;
|
|
1330
|
+
const n = Number(m[1]);
|
|
1331
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
1332
|
+
}
|
|
1333
|
+
function importedKind(name) {
|
|
1334
|
+
const s = (name ?? "").toLowerCase();
|
|
1335
|
+
if (s.includes("wye")) return "wye";
|
|
1336
|
+
if (s.includes("crossing")) return "crossing";
|
|
1337
|
+
if (s.includes("curved")) return "curved-turnout";
|
|
1338
|
+
return "turnout";
|
|
1339
|
+
}
|
|
1340
|
+
var slug = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
1341
|
+
function importedPartToTrackPart(part, sourceName = "imported .xtp") {
|
|
1342
|
+
const name = part.name ?? part.title ?? "Imported part";
|
|
1343
|
+
const manufacturer = part.manufacturer ?? "Unknown";
|
|
1344
|
+
const note = `from ${sourceName} \u2014 community CAD data, not a measurement`;
|
|
1345
|
+
const out = {
|
|
1346
|
+
id: `xtp-${slug(manufacturer)}-${slug(part.partNumber || name)}`,
|
|
1347
|
+
manufacturer,
|
|
1348
|
+
name,
|
|
1349
|
+
line: "",
|
|
1350
|
+
scale: "N",
|
|
1351
|
+
kind: importedKind(name),
|
|
1352
|
+
frogNumber: frogNumberFromName(name),
|
|
1353
|
+
segments: part.segments,
|
|
1354
|
+
ends: part.ends,
|
|
1355
|
+
importedFrom: sourceName
|
|
1356
|
+
};
|
|
1357
|
+
if (part.partNumber) out.partNumbers = { single: part.partNumber };
|
|
1358
|
+
const ends = part.ends;
|
|
1359
|
+
if (ends.length >= 2) {
|
|
1360
|
+
const a = ends[0].angleDeg * Math.PI / 180;
|
|
1361
|
+
const ux = Math.sin(a);
|
|
1362
|
+
const uy = Math.cos(a);
|
|
1363
|
+
const proj = ends.map((e) => (e.x - ends[0].x) * ux + (e.y - ends[0].y) * uy);
|
|
1364
|
+
const span = Math.max(...proj) - Math.min(...proj);
|
|
1365
|
+
if (span > 0) out.overallLength = { inches: span, source: "unverified", note };
|
|
1366
|
+
}
|
|
1367
|
+
if (ends.length >= 3) {
|
|
1368
|
+
const rest = ends.slice(1);
|
|
1369
|
+
const opposite = rest.map((e) => ({ e, off: Math.abs(angleDeltaDeg(e.angleDeg, ends[0].angleDeg + 180)) })).sort((p, q) => p.off - q.off);
|
|
1370
|
+
const through = opposite[0].e;
|
|
1371
|
+
const diverging = opposite[opposite.length - 1].e;
|
|
1372
|
+
const deg = Math.abs(angleDeltaDeg(diverging.angleDeg, through.angleDeg));
|
|
1373
|
+
if (deg > 0.01) out.actualAngle = { deg, source: "unverified", note };
|
|
1374
|
+
}
|
|
1375
|
+
return out;
|
|
1376
|
+
}
|
|
1377
|
+
function mergeImportedParts(imported, library = BUILT_IN_TRACK_PARTS, sourceName = "imported .xtp") {
|
|
1378
|
+
const out = library.map((p) => ({ ...p }));
|
|
1379
|
+
const numbersOf = (p) => [p.partNumbers?.left, p.partNumbers?.right, p.partNumbers?.single].filter(Boolean).map((s) => s.trim().toLowerCase());
|
|
1380
|
+
for (const raw of imported) {
|
|
1381
|
+
const conv = importedPartToTrackPart(raw, sourceName);
|
|
1382
|
+
const pn = raw.partNumber?.trim().toLowerCase();
|
|
1383
|
+
const match = (pn ? out.find((p) => numbersOf(p).includes(pn)) : void 0) ?? (conv.frogNumber != null ? out.find(
|
|
1384
|
+
(p) => p.frogNumber === conv.frogNumber && p.kind === conv.kind && p.manufacturer.toLowerCase() === conv.manufacturer.toLowerCase()
|
|
1385
|
+
) : void 0);
|
|
1386
|
+
if (!match) {
|
|
1387
|
+
out.push(conv);
|
|
1388
|
+
continue;
|
|
1389
|
+
}
|
|
1390
|
+
if (!match.segments?.length && conv.segments?.length) match.segments = conv.segments;
|
|
1391
|
+
if (!match.ends?.length && conv.ends?.length) match.ends = conv.ends;
|
|
1392
|
+
if (!match.importedFrom && (conv.segments?.length || conv.ends?.length)) {
|
|
1393
|
+
match.importedFrom = sourceName;
|
|
1394
|
+
}
|
|
1395
|
+
if (!match.overallLength && conv.overallLength) match.overallLength = conv.overallLength;
|
|
1396
|
+
if (!match.actualAngle && conv.actualAngle) match.actualAngle = conv.actualAngle;
|
|
1397
|
+
}
|
|
1398
|
+
return out;
|
|
1399
|
+
}
|
|
1321
1400
|
function turnoutClosure(size, opts = {}) {
|
|
1322
1401
|
const N = size > 0 ? size : 6;
|
|
1323
1402
|
const g = opts.gaugeInches ?? RAIL_GAUGE_INCHES;
|
|
@@ -1847,6 +1926,6 @@ function poseOverridesFromDoc(doc) {
|
|
|
1847
1926
|
return out;
|
|
1848
1927
|
}
|
|
1849
1928
|
|
|
1850
|
-
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 };
|
|
1929
|
+
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, frogNumberFromName, fromSectionRelative, geometryTurnDegrees, importedPartToTrackPart, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, leadInchesForSize, mergeImportedParts, 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 };
|
|
1851
1930
|
//# sourceMappingURL=index.js.map
|
|
1852
1931
|
//# sourceMappingURL=index.js.map
|