@willcgage/module-schematic 0.20.0 → 0.22.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 +32 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -3
- package/dist/index.d.ts +23 -3
- package/dist/index.js +32 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -149,16 +149,27 @@ type IndustryLabelMode = "none" | "cars" | "inches";
|
|
|
149
149
|
* offset to `side`. The span length gives its car capacity; the dispatcher and
|
|
150
150
|
* crews read where cars set out. Mirrors a `freemon_industries` row.
|
|
151
151
|
*/
|
|
152
|
+
/** One car-spot span of an industry on a track — an industry may have several
|
|
153
|
+
* (a house track serving one customer across multiple spot tracks, #54). */
|
|
154
|
+
interface IndustrySpot {
|
|
155
|
+
track: string;
|
|
156
|
+
fromPos: number;
|
|
157
|
+
toPos: number;
|
|
158
|
+
side?: SignalSide;
|
|
159
|
+
}
|
|
152
160
|
interface SchematicIndustry {
|
|
153
161
|
id: string;
|
|
154
162
|
name: string;
|
|
155
163
|
/** Industry type value from the lookup (e.g. "team_track", "grain"). */
|
|
156
164
|
type?: string | null;
|
|
157
|
-
/** The track this industry spots cars on (a spur/siding id
|
|
165
|
+
/** The primary track this industry spots cars on (a spur/siding id or main).
|
|
166
|
+
* Additional spots (other tracks) live in `spots`. */
|
|
158
167
|
track: string;
|
|
159
|
-
/** The car-spot span along
|
|
168
|
+
/** The primary car-spot span along `track`, inches from endplate A. */
|
|
160
169
|
fromPos: number;
|
|
161
170
|
toPos: number;
|
|
171
|
+
/** Extra car-spot spans on other tracks — the industry's house-track spots. */
|
|
172
|
+
spots?: IndustrySpot[];
|
|
162
173
|
/** Which side of the track the building + label sit on. */
|
|
163
174
|
side?: SignalSide;
|
|
164
175
|
/** Secondary readout at the label — a car count, a length, or none. */
|
|
@@ -200,6 +211,10 @@ interface ModuleSchematicDoc {
|
|
|
200
211
|
* +y up). Stored as an open ring; renderers close it. Absent = derive an
|
|
201
212
|
* approximate band from the endplate widths. */
|
|
202
213
|
outline?: BenchworkPoint[];
|
|
214
|
+
/** Internal section joints — inches from endplate A where the module's boards
|
|
215
|
+
* split into sections. Operationally one unit; these mark construction/transport
|
|
216
|
+
* seams (exempt from the end-interface standards). Empty/absent = one section. */
|
|
217
|
+
sectionBreaks?: number[];
|
|
203
218
|
/** @deprecated pre-grouping flat signals; read for back-compat. */
|
|
204
219
|
signals?: SchematicSignal[];
|
|
205
220
|
/** Authored mainline centre-line (module-local inches, open path with arcs).
|
|
@@ -375,6 +390,8 @@ interface EditorIndustry {
|
|
|
375
390
|
track: string;
|
|
376
391
|
fromPos: number;
|
|
377
392
|
toPos: number;
|
|
393
|
+
/** Extra car-spot spans on other tracks (house-track spots, #54). */
|
|
394
|
+
spots: IndustrySpot[];
|
|
378
395
|
side: SignalSide;
|
|
379
396
|
labelMode: IndustryLabelMode;
|
|
380
397
|
carTypes: string[];
|
|
@@ -425,6 +442,9 @@ interface EditorState {
|
|
|
425
442
|
* (endplate A's track point at the origin, mainline +x, perpendicular +y up).
|
|
426
443
|
* Empty = no authored outline (fall back to the endplate-width band). */
|
|
427
444
|
outline: BenchworkPoint[];
|
|
445
|
+
/** Internal section joints — inches from endplate A where the boards split
|
|
446
|
+
* into sections. Empty = a single section (#48). */
|
|
447
|
+
sectionBreaks: number[];
|
|
428
448
|
controlPoints: EditorControlPoint[];
|
|
429
449
|
/** Rail-served industries — car-spot spans on a track (#industries). */
|
|
430
450
|
industries: EditorIndustry[];
|
|
@@ -709,4 +729,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
709
729
|
heading: number;
|
|
710
730
|
}>;
|
|
711
731
|
|
|
712
|
-
export { type BenchworkPoint, type BranchConnector, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, type GeometryType, type IndustryLabelMode, 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 SchematicBlock, type SchematicControlPoint, type SchematicCrossing, type SchematicEndplate, type SchematicEndplateTrack, type SchematicIndustry, type SchematicSignal, type SchematicTrack, type SchematicTurnout, type SignalFacing, type SignalSide, type TrackConfig, type TrackRole, type TurnoutKind, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, stateToDoc, trackPath };
|
|
732
|
+
export { type BenchworkPoint, type BranchConnector, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_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, type SchematicBlock, type SchematicControlPoint, type SchematicCrossing, type SchematicEndplate, type SchematicEndplateTrack, type SchematicIndustry, type SchematicSignal, type SchematicTrack, type SchematicTurnout, type SignalFacing, type SignalSide, type TrackConfig, type TrackRole, type TurnoutKind, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, stateToDoc, trackPath };
|
package/dist/index.d.ts
CHANGED
|
@@ -149,16 +149,27 @@ type IndustryLabelMode = "none" | "cars" | "inches";
|
|
|
149
149
|
* offset to `side`. The span length gives its car capacity; the dispatcher and
|
|
150
150
|
* crews read where cars set out. Mirrors a `freemon_industries` row.
|
|
151
151
|
*/
|
|
152
|
+
/** One car-spot span of an industry on a track — an industry may have several
|
|
153
|
+
* (a house track serving one customer across multiple spot tracks, #54). */
|
|
154
|
+
interface IndustrySpot {
|
|
155
|
+
track: string;
|
|
156
|
+
fromPos: number;
|
|
157
|
+
toPos: number;
|
|
158
|
+
side?: SignalSide;
|
|
159
|
+
}
|
|
152
160
|
interface SchematicIndustry {
|
|
153
161
|
id: string;
|
|
154
162
|
name: string;
|
|
155
163
|
/** Industry type value from the lookup (e.g. "team_track", "grain"). */
|
|
156
164
|
type?: string | null;
|
|
157
|
-
/** The track this industry spots cars on (a spur/siding id
|
|
165
|
+
/** The primary track this industry spots cars on (a spur/siding id or main).
|
|
166
|
+
* Additional spots (other tracks) live in `spots`. */
|
|
158
167
|
track: string;
|
|
159
|
-
/** The car-spot span along
|
|
168
|
+
/** The primary car-spot span along `track`, inches from endplate A. */
|
|
160
169
|
fromPos: number;
|
|
161
170
|
toPos: number;
|
|
171
|
+
/** Extra car-spot spans on other tracks — the industry's house-track spots. */
|
|
172
|
+
spots?: IndustrySpot[];
|
|
162
173
|
/** Which side of the track the building + label sit on. */
|
|
163
174
|
side?: SignalSide;
|
|
164
175
|
/** Secondary readout at the label — a car count, a length, or none. */
|
|
@@ -200,6 +211,10 @@ interface ModuleSchematicDoc {
|
|
|
200
211
|
* +y up). Stored as an open ring; renderers close it. Absent = derive an
|
|
201
212
|
* approximate band from the endplate widths. */
|
|
202
213
|
outline?: BenchworkPoint[];
|
|
214
|
+
/** Internal section joints — inches from endplate A where the module's boards
|
|
215
|
+
* split into sections. Operationally one unit; these mark construction/transport
|
|
216
|
+
* seams (exempt from the end-interface standards). Empty/absent = one section. */
|
|
217
|
+
sectionBreaks?: number[];
|
|
203
218
|
/** @deprecated pre-grouping flat signals; read for back-compat. */
|
|
204
219
|
signals?: SchematicSignal[];
|
|
205
220
|
/** Authored mainline centre-line (module-local inches, open path with arcs).
|
|
@@ -375,6 +390,8 @@ interface EditorIndustry {
|
|
|
375
390
|
track: string;
|
|
376
391
|
fromPos: number;
|
|
377
392
|
toPos: number;
|
|
393
|
+
/** Extra car-spot spans on other tracks (house-track spots, #54). */
|
|
394
|
+
spots: IndustrySpot[];
|
|
378
395
|
side: SignalSide;
|
|
379
396
|
labelMode: IndustryLabelMode;
|
|
380
397
|
carTypes: string[];
|
|
@@ -425,6 +442,9 @@ interface EditorState {
|
|
|
425
442
|
* (endplate A's track point at the origin, mainline +x, perpendicular +y up).
|
|
426
443
|
* Empty = no authored outline (fall back to the endplate-width band). */
|
|
427
444
|
outline: BenchworkPoint[];
|
|
445
|
+
/** Internal section joints — inches from endplate A where the boards split
|
|
446
|
+
* into sections. Empty = a single section (#48). */
|
|
447
|
+
sectionBreaks: number[];
|
|
428
448
|
controlPoints: EditorControlPoint[];
|
|
429
449
|
/** Rail-served industries — car-spot spans on a track (#industries). */
|
|
430
450
|
industries: EditorIndustry[];
|
|
@@ -709,4 +729,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
709
729
|
heading: number;
|
|
710
730
|
}>;
|
|
711
731
|
|
|
712
|
-
export { type BenchworkPoint, type BranchConnector, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, type GeometryType, type IndustryLabelMode, 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 SchematicBlock, type SchematicControlPoint, type SchematicCrossing, type SchematicEndplate, type SchematicEndplateTrack, type SchematicIndustry, type SchematicSignal, type SchematicTrack, type SchematicTurnout, type SignalFacing, type SignalSide, type TrackConfig, type TrackRole, type TurnoutKind, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, stateToDoc, trackPath };
|
|
732
|
+
export { type BenchworkPoint, type BranchConnector, type DrawCrossing, type DrawCrossover, type DrawIndustry, type DrawSignal, type DrawTrack, type DrawTurnout, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorIndustry, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_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, type SchematicBlock, type SchematicControlPoint, type SchematicCrossing, type SchematicEndplate, type SchematicEndplateTrack, type SchematicIndustry, type SchematicSignal, type SchematicTrack, type SchematicTurnout, type SignalFacing, type SignalSide, type TrackConfig, type TrackRole, type TurnoutKind, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, stateToDoc, trackPath };
|
package/dist/index.js
CHANGED
|
@@ -214,6 +214,7 @@ function emptyEditorState(lengthInches) {
|
|
|
214
214
|
poseOverrides: {},
|
|
215
215
|
endplateWidths: {},
|
|
216
216
|
outline: [],
|
|
217
|
+
sectionBreaks: [],
|
|
217
218
|
controlPoints: [],
|
|
218
219
|
industries: [],
|
|
219
220
|
mainPath: []
|
|
@@ -397,6 +398,7 @@ function stateToDoc(state, recordNumber) {
|
|
|
397
398
|
track: ind.track,
|
|
398
399
|
fromPos: ind.fromPos,
|
|
399
400
|
toPos: ind.toPos,
|
|
401
|
+
...ind.spots?.length ? { spots: ind.spots } : {},
|
|
400
402
|
side: ind.side,
|
|
401
403
|
...ind.labelMode && ind.labelMode !== "none" ? { labelMode: ind.labelMode } : {},
|
|
402
404
|
...ind.carTypes.length ? { carTypes: ind.carTypes } : {},
|
|
@@ -406,6 +408,8 @@ function stateToDoc(state, recordNumber) {
|
|
|
406
408
|
// Benchwork footprint outline (module-local inches); only when it's a real
|
|
407
409
|
// ring (≥ 3 vertices).
|
|
408
410
|
...state.outline.length >= 3 ? { outline: state.outline } : {},
|
|
411
|
+
// Internal section joints (inches from A), when the module has more than one.
|
|
412
|
+
...state.sectionBreaks.length ? { sectionBreaks: state.sectionBreaks } : {},
|
|
409
413
|
// Authored mainline path (module-local inches); only when it's a real path.
|
|
410
414
|
...state.mainPath.length >= 2 ? { mainPath: state.mainPath } : {}
|
|
411
415
|
};
|
|
@@ -505,6 +509,7 @@ function docToState(doc, fallbackLength, moduleTracks = []) {
|
|
|
505
509
|
poseOverrides,
|
|
506
510
|
endplateWidths,
|
|
507
511
|
outline,
|
|
512
|
+
sectionBreaks: (d.sectionBreaks ?? []).filter((n) => Number.isFinite(n)).map((n) => sc(n)),
|
|
508
513
|
mainPath,
|
|
509
514
|
crossings: (d.crossings ?? []).map((x) => ({
|
|
510
515
|
id: x.id,
|
|
@@ -531,6 +536,12 @@ function docToState(doc, fallbackLength, moduleTracks = []) {
|
|
|
531
536
|
track: ind.track,
|
|
532
537
|
fromPos: sc(ind.fromPos ?? 0),
|
|
533
538
|
toPos: ind.toPos != null ? sc(ind.toPos) : len,
|
|
539
|
+
spots: (ind.spots ?? []).map((s) => ({
|
|
540
|
+
track: s.track,
|
|
541
|
+
fromPos: sc(s.fromPos ?? 0),
|
|
542
|
+
toPos: s.toPos != null ? sc(s.toPos) : len,
|
|
543
|
+
...s.side ? { side: s.side } : {}
|
|
544
|
+
})),
|
|
534
545
|
side: ind.side ?? "above",
|
|
535
546
|
labelMode: ind.labelMode ?? "none",
|
|
536
547
|
carTypes: Array.isArray(ind.carTypes) ? ind.carTypes : [],
|
|
@@ -834,21 +845,27 @@ function moduleFeatures(doc) {
|
|
|
834
845
|
posFrac: clampFrac(e.at.pos),
|
|
835
846
|
side: e.at.side === "down" ? "down" : "up"
|
|
836
847
|
}));
|
|
837
|
-
const industries = (doc.industries ?? []).
|
|
838
|
-
const
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
848
|
+
const industries = (doc.industries ?? []).flatMap((ind) => {
|
|
849
|
+
const spots = [
|
|
850
|
+
{ track: ind.track, fromPos: ind.fromPos, toPos: ind.toPos, side: ind.side },
|
|
851
|
+
...ind.spots ?? []
|
|
852
|
+
];
|
|
853
|
+
return spots.map((sp, i) => {
|
|
854
|
+
const from = sp.fromPos ?? 0;
|
|
855
|
+
const to = sp.toPos ?? len;
|
|
856
|
+
return {
|
|
857
|
+
id: i === 0 ? ind.id : `${ind.id}-s${i}`,
|
|
858
|
+
name: ind.name ?? "",
|
|
859
|
+
type: ind.type ?? null,
|
|
860
|
+
fromFrac: clampFrac(Math.min(from, to)),
|
|
861
|
+
toFrac: clampFrac(Math.max(from, to)),
|
|
862
|
+
lane: trackLane.get(sp.track) ?? 0,
|
|
863
|
+
side: sp.side ?? "above",
|
|
864
|
+
labelMode: ind.labelMode ?? "none",
|
|
865
|
+
cars: carCapacity(from, to),
|
|
866
|
+
carTypes: Array.isArray(ind.carTypes) ? ind.carTypes : []
|
|
867
|
+
};
|
|
868
|
+
});
|
|
852
869
|
});
|
|
853
870
|
const allLanes = [
|
|
854
871
|
0,
|