@willcgage/module-schematic 0.17.0 → 0.18.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 +54 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +74 -1
- package/dist/index.d.ts +74 -1
- package/dist/index.js +53 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -132,6 +132,35 @@ interface SchematicControlPoint {
|
|
|
132
132
|
crossings?: string[];
|
|
133
133
|
signals?: SchematicSignal[];
|
|
134
134
|
}
|
|
135
|
+
/** What a rendered industry shows beside its name: a car count, a length in
|
|
136
|
+
* inches, or nothing (name only). Authored per industry. */
|
|
137
|
+
type IndustryLabelMode = "none" | "cars" | "inches";
|
|
138
|
+
/**
|
|
139
|
+
* An industry — a rail-served customer that spots cars, authored as a SPAN on a
|
|
140
|
+
* track (a spur/siding, or the main). Positional like everything else: it lives
|
|
141
|
+
* in the same module-local inch frame and is rendered into the shared 2-D view,
|
|
142
|
+
* offset to `side`. The span length gives its car capacity; the dispatcher and
|
|
143
|
+
* crews read where cars set out. Mirrors a `freemon_industries` row.
|
|
144
|
+
*/
|
|
145
|
+
interface SchematicIndustry {
|
|
146
|
+
id: string;
|
|
147
|
+
name: string;
|
|
148
|
+
/** Industry type value from the lookup (e.g. "team_track", "grain"). */
|
|
149
|
+
type?: string | null;
|
|
150
|
+
/** The track this industry spots cars on (a spur/siding id, or the main). */
|
|
151
|
+
track: string;
|
|
152
|
+
/** The car-spot span along that track, inches from endplate A. */
|
|
153
|
+
fromPos: number;
|
|
154
|
+
toPos: number;
|
|
155
|
+
/** Which side of the track the building + label sit on. */
|
|
156
|
+
side?: SignalSide;
|
|
157
|
+
/** Secondary readout at the label — a car count, a length, or none. */
|
|
158
|
+
labelMode?: IndustryLabelMode;
|
|
159
|
+
/** Car types this industry receives (car-type value strings). */
|
|
160
|
+
carTypes?: string[];
|
|
161
|
+
/** The `freemon_industries` row this is (single source of truth); null = new. */
|
|
162
|
+
moduleIndustryId?: number | null;
|
|
163
|
+
}
|
|
135
164
|
interface ModuleSchematicDoc {
|
|
136
165
|
version: number;
|
|
137
166
|
module?: string;
|
|
@@ -156,6 +185,8 @@ interface ModuleSchematicDoc {
|
|
|
156
185
|
/** Grade crossings / diamonds (#170). */
|
|
157
186
|
crossings?: SchematicCrossing[];
|
|
158
187
|
controlPoints?: SchematicControlPoint[];
|
|
188
|
+
/** Rail-served industries — car-spot spans on a track (#industries). */
|
|
189
|
+
industries?: SchematicIndustry[];
|
|
159
190
|
/** Benchwork FOOTPRINT outline — the module's physical board shape as a
|
|
160
191
|
* polygon in module-local inches, in the same frame as the endplate poses
|
|
161
192
|
* (endplate A's track point at the origin, the mainline along +x, perpendicular
|
|
@@ -243,6 +274,13 @@ declare const N_SCALE_RATIO = 160;
|
|
|
243
274
|
declare function inchesToScaleFeet(inches: number, ratio?: number): number;
|
|
244
275
|
/** Scale feet of prototype track → real inches on the module. */
|
|
245
276
|
declare function scaleFeetToInches(feet: number, ratio?: number): number;
|
|
277
|
+
/** Length a spotted car occupies on N-scale track, inches. A 40-ft car body is
|
|
278
|
+
* ~3.0″; ~3.3″ over the couplers — the real spacing a cut of cars takes. The
|
|
279
|
+
* single constant every repo reads so a track's car count matches everywhere. */
|
|
280
|
+
declare const N_CAR_LENGTH_INCHES = 3.3;
|
|
281
|
+
/** How many cars fit in a span, from its drawn length — the derived capacity a
|
|
282
|
+
* siding or an industry spot holds (never typed). */
|
|
283
|
+
declare function carCapacity(fromPos: number, toPos: number, carLengthInches?: number): number;
|
|
246
284
|
/** Parse a jsonb value into a schematic doc, or null if it isn't one. */
|
|
247
285
|
declare function asModuleSchematic(x: unknown): ModuleSchematicDoc | null;
|
|
248
286
|
interface EditorTrack {
|
|
@@ -294,6 +332,20 @@ interface EditorCrossing {
|
|
|
294
332
|
trackA: string;
|
|
295
333
|
trackB: string;
|
|
296
334
|
}
|
|
335
|
+
/** An industry as the authoring form binds it — a car-spot span on a track. */
|
|
336
|
+
interface EditorIndustry {
|
|
337
|
+
id: string;
|
|
338
|
+
name: string;
|
|
339
|
+
type: string;
|
|
340
|
+
track: string;
|
|
341
|
+
fromPos: number;
|
|
342
|
+
toPos: number;
|
|
343
|
+
side: SignalSide;
|
|
344
|
+
labelMode: IndustryLabelMode;
|
|
345
|
+
carTypes: string[];
|
|
346
|
+
/** freemon_industries row (single source of truth), or null for a new one. */
|
|
347
|
+
moduleIndustryId: number | null;
|
|
348
|
+
}
|
|
297
349
|
/** A 3rd+ endplate — a branch/junction connection off the module (#170).
|
|
298
350
|
* A module may have several (e.g. a set carrying a second railroad through:
|
|
299
351
|
* MoPac enters at one branch endplate and leaves at another). */
|
|
@@ -339,6 +391,8 @@ interface EditorState {
|
|
|
339
391
|
* Empty = no authored outline (fall back to the endplate-width band). */
|
|
340
392
|
outline: BenchworkPoint[];
|
|
341
393
|
controlPoints: EditorControlPoint[];
|
|
394
|
+
/** Rail-served industries — car-spot spans on a track (#industries). */
|
|
395
|
+
industries: EditorIndustry[];
|
|
342
396
|
}
|
|
343
397
|
/** Build the empty editor state for a module of the given length. */
|
|
344
398
|
declare function emptyEditorState(lengthInches: number): EditorState;
|
|
@@ -469,6 +523,23 @@ interface BranchConnector {
|
|
|
469
523
|
posFrac: number;
|
|
470
524
|
side: "up" | "down";
|
|
471
525
|
}
|
|
526
|
+
/** An industry — draw a car-spot span beside its track's lane, on `side`, with
|
|
527
|
+
* a name label + an optional car/length readout (#industries). */
|
|
528
|
+
interface DrawIndustry {
|
|
529
|
+
id: string;
|
|
530
|
+
name: string;
|
|
531
|
+
type: string | null;
|
|
532
|
+
/** Span as fractions of module length (sorted West→East). */
|
|
533
|
+
fromFrac: number;
|
|
534
|
+
toFrac: number;
|
|
535
|
+
/** Lane of the track it spots on, so it draws beside the right track. */
|
|
536
|
+
lane: number;
|
|
537
|
+
side: SignalSide;
|
|
538
|
+
labelMode: IndustryLabelMode;
|
|
539
|
+
/** Cars that spot here, derived from the drawn span length. */
|
|
540
|
+
cars: number;
|
|
541
|
+
carTypes: string[];
|
|
542
|
+
}
|
|
472
543
|
interface ModuleFeatures {
|
|
473
544
|
/** Whether either endplate declares a double-track main. */
|
|
474
545
|
doubleMain: boolean;
|
|
@@ -493,6 +564,8 @@ interface ModuleFeatures {
|
|
|
493
564
|
crossovers: DrawCrossover[];
|
|
494
565
|
/** Branch endplates — junction connectors off the module (#170). */
|
|
495
566
|
branchConnectors: BranchConnector[];
|
|
567
|
+
/** Rail-served industries — car-spot spans beside their track (#industries). */
|
|
568
|
+
industries: DrawIndustry[];
|
|
496
569
|
/** Main 2's extent when it doesn't run the full module — a single↔double
|
|
497
570
|
* transition (Main 2 starts/ends at the mainline turnout). Null = full
|
|
498
571
|
* length (or no Main 2). Renderers draw the partial line + its diverge. */
|
|
@@ -598,4 +671,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
598
671
|
heading: number;
|
|
599
672
|
}>;
|
|
600
673
|
|
|
601
|
-
export { type BenchworkPoint, type BranchConnector, type DrawCrossing, type DrawCrossover, type DrawSignal, type DrawTrack, type DrawTurnout, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, type GeometryType, MAIN2_TRACK_ID, MAIN_TRACK_ID, type ModuleFeatures, type ModuleFootprint, type ModuleFootprintInput, type ModuleGeometryInput, type ModuleSchematicDoc, type ModuleTrackRow, N_SCALE_RATIO, type OutlineFace, type SchematicBlock, type SchematicControlPoint, type SchematicCrossing, type SchematicEndplate, type SchematicEndplateTrack, type SchematicSignal, type SchematicTrack, type SchematicTurnout, type SignalFacing, type SignalSide, type TrackConfig, type TrackRole, type TurnoutKind, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, scaleFeetToInches, stateToDoc };
|
|
674
|
+
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, scaleFeetToInches, stateToDoc };
|
package/dist/index.d.ts
CHANGED
|
@@ -132,6 +132,35 @@ interface SchematicControlPoint {
|
|
|
132
132
|
crossings?: string[];
|
|
133
133
|
signals?: SchematicSignal[];
|
|
134
134
|
}
|
|
135
|
+
/** What a rendered industry shows beside its name: a car count, a length in
|
|
136
|
+
* inches, or nothing (name only). Authored per industry. */
|
|
137
|
+
type IndustryLabelMode = "none" | "cars" | "inches";
|
|
138
|
+
/**
|
|
139
|
+
* An industry — a rail-served customer that spots cars, authored as a SPAN on a
|
|
140
|
+
* track (a spur/siding, or the main). Positional like everything else: it lives
|
|
141
|
+
* in the same module-local inch frame and is rendered into the shared 2-D view,
|
|
142
|
+
* offset to `side`. The span length gives its car capacity; the dispatcher and
|
|
143
|
+
* crews read where cars set out. Mirrors a `freemon_industries` row.
|
|
144
|
+
*/
|
|
145
|
+
interface SchematicIndustry {
|
|
146
|
+
id: string;
|
|
147
|
+
name: string;
|
|
148
|
+
/** Industry type value from the lookup (e.g. "team_track", "grain"). */
|
|
149
|
+
type?: string | null;
|
|
150
|
+
/** The track this industry spots cars on (a spur/siding id, or the main). */
|
|
151
|
+
track: string;
|
|
152
|
+
/** The car-spot span along that track, inches from endplate A. */
|
|
153
|
+
fromPos: number;
|
|
154
|
+
toPos: number;
|
|
155
|
+
/** Which side of the track the building + label sit on. */
|
|
156
|
+
side?: SignalSide;
|
|
157
|
+
/** Secondary readout at the label — a car count, a length, or none. */
|
|
158
|
+
labelMode?: IndustryLabelMode;
|
|
159
|
+
/** Car types this industry receives (car-type value strings). */
|
|
160
|
+
carTypes?: string[];
|
|
161
|
+
/** The `freemon_industries` row this is (single source of truth); null = new. */
|
|
162
|
+
moduleIndustryId?: number | null;
|
|
163
|
+
}
|
|
135
164
|
interface ModuleSchematicDoc {
|
|
136
165
|
version: number;
|
|
137
166
|
module?: string;
|
|
@@ -156,6 +185,8 @@ interface ModuleSchematicDoc {
|
|
|
156
185
|
/** Grade crossings / diamonds (#170). */
|
|
157
186
|
crossings?: SchematicCrossing[];
|
|
158
187
|
controlPoints?: SchematicControlPoint[];
|
|
188
|
+
/** Rail-served industries — car-spot spans on a track (#industries). */
|
|
189
|
+
industries?: SchematicIndustry[];
|
|
159
190
|
/** Benchwork FOOTPRINT outline — the module's physical board shape as a
|
|
160
191
|
* polygon in module-local inches, in the same frame as the endplate poses
|
|
161
192
|
* (endplate A's track point at the origin, the mainline along +x, perpendicular
|
|
@@ -243,6 +274,13 @@ declare const N_SCALE_RATIO = 160;
|
|
|
243
274
|
declare function inchesToScaleFeet(inches: number, ratio?: number): number;
|
|
244
275
|
/** Scale feet of prototype track → real inches on the module. */
|
|
245
276
|
declare function scaleFeetToInches(feet: number, ratio?: number): number;
|
|
277
|
+
/** Length a spotted car occupies on N-scale track, inches. A 40-ft car body is
|
|
278
|
+
* ~3.0″; ~3.3″ over the couplers — the real spacing a cut of cars takes. The
|
|
279
|
+
* single constant every repo reads so a track's car count matches everywhere. */
|
|
280
|
+
declare const N_CAR_LENGTH_INCHES = 3.3;
|
|
281
|
+
/** How many cars fit in a span, from its drawn length — the derived capacity a
|
|
282
|
+
* siding or an industry spot holds (never typed). */
|
|
283
|
+
declare function carCapacity(fromPos: number, toPos: number, carLengthInches?: number): number;
|
|
246
284
|
/** Parse a jsonb value into a schematic doc, or null if it isn't one. */
|
|
247
285
|
declare function asModuleSchematic(x: unknown): ModuleSchematicDoc | null;
|
|
248
286
|
interface EditorTrack {
|
|
@@ -294,6 +332,20 @@ interface EditorCrossing {
|
|
|
294
332
|
trackA: string;
|
|
295
333
|
trackB: string;
|
|
296
334
|
}
|
|
335
|
+
/** An industry as the authoring form binds it — a car-spot span on a track. */
|
|
336
|
+
interface EditorIndustry {
|
|
337
|
+
id: string;
|
|
338
|
+
name: string;
|
|
339
|
+
type: string;
|
|
340
|
+
track: string;
|
|
341
|
+
fromPos: number;
|
|
342
|
+
toPos: number;
|
|
343
|
+
side: SignalSide;
|
|
344
|
+
labelMode: IndustryLabelMode;
|
|
345
|
+
carTypes: string[];
|
|
346
|
+
/** freemon_industries row (single source of truth), or null for a new one. */
|
|
347
|
+
moduleIndustryId: number | null;
|
|
348
|
+
}
|
|
297
349
|
/** A 3rd+ endplate — a branch/junction connection off the module (#170).
|
|
298
350
|
* A module may have several (e.g. a set carrying a second railroad through:
|
|
299
351
|
* MoPac enters at one branch endplate and leaves at another). */
|
|
@@ -339,6 +391,8 @@ interface EditorState {
|
|
|
339
391
|
* Empty = no authored outline (fall back to the endplate-width band). */
|
|
340
392
|
outline: BenchworkPoint[];
|
|
341
393
|
controlPoints: EditorControlPoint[];
|
|
394
|
+
/** Rail-served industries — car-spot spans on a track (#industries). */
|
|
395
|
+
industries: EditorIndustry[];
|
|
342
396
|
}
|
|
343
397
|
/** Build the empty editor state for a module of the given length. */
|
|
344
398
|
declare function emptyEditorState(lengthInches: number): EditorState;
|
|
@@ -469,6 +523,23 @@ interface BranchConnector {
|
|
|
469
523
|
posFrac: number;
|
|
470
524
|
side: "up" | "down";
|
|
471
525
|
}
|
|
526
|
+
/** An industry — draw a car-spot span beside its track's lane, on `side`, with
|
|
527
|
+
* a name label + an optional car/length readout (#industries). */
|
|
528
|
+
interface DrawIndustry {
|
|
529
|
+
id: string;
|
|
530
|
+
name: string;
|
|
531
|
+
type: string | null;
|
|
532
|
+
/** Span as fractions of module length (sorted West→East). */
|
|
533
|
+
fromFrac: number;
|
|
534
|
+
toFrac: number;
|
|
535
|
+
/** Lane of the track it spots on, so it draws beside the right track. */
|
|
536
|
+
lane: number;
|
|
537
|
+
side: SignalSide;
|
|
538
|
+
labelMode: IndustryLabelMode;
|
|
539
|
+
/** Cars that spot here, derived from the drawn span length. */
|
|
540
|
+
cars: number;
|
|
541
|
+
carTypes: string[];
|
|
542
|
+
}
|
|
472
543
|
interface ModuleFeatures {
|
|
473
544
|
/** Whether either endplate declares a double-track main. */
|
|
474
545
|
doubleMain: boolean;
|
|
@@ -493,6 +564,8 @@ interface ModuleFeatures {
|
|
|
493
564
|
crossovers: DrawCrossover[];
|
|
494
565
|
/** Branch endplates — junction connectors off the module (#170). */
|
|
495
566
|
branchConnectors: BranchConnector[];
|
|
567
|
+
/** Rail-served industries — car-spot spans beside their track (#industries). */
|
|
568
|
+
industries: DrawIndustry[];
|
|
496
569
|
/** Main 2's extent when it doesn't run the full module — a single↔double
|
|
497
570
|
* transition (Main 2 starts/ends at the mainline turnout). Null = full
|
|
498
571
|
* length (or no Main 2). Renderers draw the partial line + its diverge. */
|
|
@@ -598,4 +671,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
598
671
|
heading: number;
|
|
599
672
|
}>;
|
|
600
673
|
|
|
601
|
-
export { type BenchworkPoint, type BranchConnector, type DrawCrossing, type DrawCrossover, type DrawSignal, type DrawTrack, type DrawTurnout, type EditorBranch, type EditorControlPoint, type EditorCpSignal, type EditorCrossing, type EditorState, type EditorTrack, type EditorTurnout, type EndplateBConfig, type EndplatePose, FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, type GeometryType, MAIN2_TRACK_ID, MAIN_TRACK_ID, type ModuleFeatures, type ModuleFootprint, type ModuleFootprintInput, type ModuleGeometryInput, type ModuleSchematicDoc, type ModuleTrackRow, N_SCALE_RATIO, type OutlineFace, type SchematicBlock, type SchematicControlPoint, type SchematicCrossing, type SchematicEndplate, type SchematicEndplateTrack, type SchematicSignal, type SchematicTrack, type SchematicTurnout, type SignalFacing, type SignalSide, type TrackConfig, type TrackRole, type TurnoutKind, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, scaleFeetToInches, stateToDoc };
|
|
674
|
+
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, scaleFeetToInches, stateToDoc };
|
package/dist/index.js
CHANGED
|
@@ -147,6 +147,11 @@ function inchesToScaleFeet(inches, ratio = N_SCALE_RATIO) {
|
|
|
147
147
|
function scaleFeetToInches(feet, ratio = N_SCALE_RATIO) {
|
|
148
148
|
return feet * 12 / ratio;
|
|
149
149
|
}
|
|
150
|
+
var N_CAR_LENGTH_INCHES = 3.3;
|
|
151
|
+
function carCapacity(fromPos, toPos, carLengthInches = N_CAR_LENGTH_INCHES) {
|
|
152
|
+
if (!(carLengthInches > 0)) return 0;
|
|
153
|
+
return Math.max(0, Math.floor(Math.abs(toPos - fromPos) / carLengthInches));
|
|
154
|
+
}
|
|
150
155
|
function asModuleSchematic(x) {
|
|
151
156
|
if (!x || typeof x !== "object") return null;
|
|
152
157
|
const d = x;
|
|
@@ -168,7 +173,8 @@ function emptyEditorState(lengthInches) {
|
|
|
168
173
|
poseOverrides: {},
|
|
169
174
|
endplateWidths: {},
|
|
170
175
|
outline: [],
|
|
171
|
-
controlPoints: []
|
|
176
|
+
controlPoints: [],
|
|
177
|
+
industries: []
|
|
172
178
|
};
|
|
173
179
|
}
|
|
174
180
|
function isTransitionTurnout(t) {
|
|
@@ -338,6 +344,21 @@ function stateToDoc(state, recordNumber) {
|
|
|
338
344
|
side: s.side
|
|
339
345
|
}))
|
|
340
346
|
})),
|
|
347
|
+
// Industries — car-spot spans on a track; only when any are authored.
|
|
348
|
+
...state.industries.length > 0 ? {
|
|
349
|
+
industries: state.industries.map((ind) => ({
|
|
350
|
+
id: ind.id,
|
|
351
|
+
name: ind.name,
|
|
352
|
+
...ind.type ? { type: ind.type } : {},
|
|
353
|
+
track: ind.track,
|
|
354
|
+
fromPos: ind.fromPos,
|
|
355
|
+
toPos: ind.toPos,
|
|
356
|
+
side: ind.side,
|
|
357
|
+
...ind.labelMode && ind.labelMode !== "none" ? { labelMode: ind.labelMode } : {},
|
|
358
|
+
...ind.carTypes.length ? { carTypes: ind.carTypes } : {},
|
|
359
|
+
moduleIndustryId: ind.moduleIndustryId
|
|
360
|
+
}))
|
|
361
|
+
} : {},
|
|
341
362
|
// Benchwork footprint outline (module-local inches); only when it's a real
|
|
342
363
|
// ring (≥ 3 vertices).
|
|
343
364
|
...state.outline.length >= 3 ? { outline: state.outline } : {}
|
|
@@ -451,7 +472,19 @@ function docToState(doc, fallbackLength, moduleTracks = []) {
|
|
|
451
472
|
divergeTrack: t.divergeTrack,
|
|
452
473
|
kind: t.kind ?? "right"
|
|
453
474
|
})),
|
|
454
|
-
controlPoints: readControlPoints(d, sc)
|
|
475
|
+
controlPoints: readControlPoints(d, sc),
|
|
476
|
+
industries: (d.industries ?? []).map((ind) => ({
|
|
477
|
+
id: ind.id,
|
|
478
|
+
name: ind.name ?? "",
|
|
479
|
+
type: ind.type ?? "",
|
|
480
|
+
track: ind.track,
|
|
481
|
+
fromPos: sc(ind.fromPos ?? 0),
|
|
482
|
+
toPos: ind.toPos != null ? sc(ind.toPos) : len,
|
|
483
|
+
side: ind.side ?? "above",
|
|
484
|
+
labelMode: ind.labelMode ?? "none",
|
|
485
|
+
carTypes: Array.isArray(ind.carTypes) ? ind.carTypes : [],
|
|
486
|
+
moduleIndustryId: ind.moduleIndustryId ?? null
|
|
487
|
+
}))
|
|
455
488
|
};
|
|
456
489
|
}
|
|
457
490
|
function readControlPoints(d, sc = (p) => p) {
|
|
@@ -750,6 +783,22 @@ function moduleFeatures(doc) {
|
|
|
750
783
|
posFrac: clampFrac(e.at.pos),
|
|
751
784
|
side: e.at.side === "down" ? "down" : "up"
|
|
752
785
|
}));
|
|
786
|
+
const industries = (doc.industries ?? []).map((ind) => {
|
|
787
|
+
const from = ind.fromPos ?? 0;
|
|
788
|
+
const to = ind.toPos ?? len;
|
|
789
|
+
return {
|
|
790
|
+
id: ind.id,
|
|
791
|
+
name: ind.name ?? "",
|
|
792
|
+
type: ind.type ?? null,
|
|
793
|
+
fromFrac: clampFrac(Math.min(from, to)),
|
|
794
|
+
toFrac: clampFrac(Math.max(from, to)),
|
|
795
|
+
lane: trackLane.get(ind.track) ?? 0,
|
|
796
|
+
side: ind.side ?? "above",
|
|
797
|
+
labelMode: ind.labelMode ?? "none",
|
|
798
|
+
cars: carCapacity(from, to),
|
|
799
|
+
carTypes: Array.isArray(ind.carTypes) ? ind.carTypes : []
|
|
800
|
+
};
|
|
801
|
+
});
|
|
753
802
|
const allLanes = [
|
|
754
803
|
0,
|
|
755
804
|
doubleMain ? 1 : 0,
|
|
@@ -790,6 +839,7 @@ function moduleFeatures(doc) {
|
|
|
790
839
|
crossings,
|
|
791
840
|
crossovers,
|
|
792
841
|
branchConnectors,
|
|
842
|
+
industries,
|
|
793
843
|
laneMin: Math.min(...allLanes),
|
|
794
844
|
laneMax: Math.max(...allLanes)
|
|
795
845
|
};
|
|
@@ -892,6 +942,6 @@ function poseOverridesFromDoc(doc) {
|
|
|
892
942
|
return out;
|
|
893
943
|
}
|
|
894
944
|
|
|
895
|
-
export { FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, MAIN2_TRACK_ID, MAIN_TRACK_ID, N_SCALE_RATIO, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, scaleFeetToInches, stateToDoc };
|
|
945
|
+
export { FREEMO_ENDPLATE_WIDTH_MIN_INCHES, FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, MAIN2_TRACK_ID, MAIN_TRACK_ID, N_CAR_LENGTH_INCHES, N_SCALE_RATIO, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, scaleFeetToInches, stateToDoc };
|
|
896
946
|
//# sourceMappingURL=index.js.map
|
|
897
947
|
//# sourceMappingURL=index.js.map
|