@willcgage/module-schematic 0.28.0 → 0.29.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 +30 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +66 -3
- package/dist/index.d.ts +66 -3
- package/dist/index.js +29 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -240,8 +240,22 @@ interface ModuleSchematicDoc {
|
|
|
240
240
|
outline?: BenchworkPoint[];
|
|
241
241
|
/** Internal section joints — inches from endplate A where the module's boards
|
|
242
242
|
* split into sections. Operationally one unit; these mark construction/transport
|
|
243
|
-
* seams (exempt from the end-interface standards). Empty/absent = one section.
|
|
243
|
+
* seams (exempt from the end-interface standards). Empty/absent = one section.
|
|
244
|
+
* Describes only sections that are full-depth SLICES; a section with a shape
|
|
245
|
+
* of its own lives in `sections` below. */
|
|
244
246
|
sectionBreaks?: number[];
|
|
247
|
+
/** The module's sections as real objects — named, each with a bench-work
|
|
248
|
+
* outline of its own (#96 phase 2). A module is a kit: the same sections can
|
|
249
|
+
* be set up in different combinations, so its footprint is the UNION of the
|
|
250
|
+
* sections present rather than an independently authored shape.
|
|
251
|
+
*
|
|
252
|
+
* Needed because sections are not slices. Real modules hang a deep section
|
|
253
|
+
* off the BACK of a shallow main band — a peninsula carrying an industry —
|
|
254
|
+
* which no single position along the main can describe.
|
|
255
|
+
*
|
|
256
|
+
* Absent = the module keeps using its own `outline` exactly as before; this
|
|
257
|
+
* is purely additive and nothing migrates on read. */
|
|
258
|
+
sections?: SchematicSection[];
|
|
245
259
|
/** @deprecated pre-grouping flat signals; read for back-compat. */
|
|
246
260
|
signals?: SchematicSignal[];
|
|
247
261
|
/** Authored mainline centre-line (module-local inches, open path with arcs).
|
|
@@ -258,12 +272,43 @@ interface BenchworkPoint {
|
|
|
258
272
|
y: number;
|
|
259
273
|
bulge?: number;
|
|
260
274
|
}
|
|
275
|
+
/** One bench-work section of a module (#96 phase 2). */
|
|
276
|
+
interface SchematicSection {
|
|
277
|
+
id: string;
|
|
278
|
+
/** What the owner calls this board — "west transition", "double #3". */
|
|
279
|
+
name?: string | null;
|
|
280
|
+
/** This section's own footprint polygon, module-local inches, same frame as
|
|
281
|
+
* the module outline. Absent = the section has no shape of its own yet (it's
|
|
282
|
+
* described only by the joints in `sectionBreaks`). */
|
|
283
|
+
outline?: BenchworkPoint[] | null;
|
|
284
|
+
}
|
|
261
285
|
/** The authored benchwork outline, or null when a module hasn't drawn one
|
|
262
286
|
* (renderers then fall back to a band derived from the endplate widths). A
|
|
263
287
|
* valid outline needs at least 3 points. Normalises each vertex to {x, y, bulge?}. */
|
|
264
288
|
declare function benchworkOutline(doc: {
|
|
265
289
|
outline?: BenchworkPoint[] | null;
|
|
266
290
|
} | null | undefined): BenchworkPoint[] | null;
|
|
291
|
+
/** The module's sections, normalised — id required, name trimmed away when
|
|
292
|
+
* blank, outline kept only when it's a usable polygon (#96 phase 2). */
|
|
293
|
+
declare function moduleSections(doc: {
|
|
294
|
+
sections?: SchematicSection[] | null;
|
|
295
|
+
} | null | undefined): SchematicSection[];
|
|
296
|
+
/** Every section outline that's actually a shape, arc-sampled for drawing.
|
|
297
|
+
* Drawing all of them IS the module's footprint — the union of its sections.
|
|
298
|
+
* No polygon boolean is computed: a renderer painting each ring gives the same
|
|
299
|
+
* picture, and an approximate union would be worse than none. If something
|
|
300
|
+
* ever needs a single ring (an export, a collision test), that's the point to
|
|
301
|
+
* bring in real clipping. */
|
|
302
|
+
declare function sectionFootprints(doc: {
|
|
303
|
+
sections?: SchematicSection[] | null;
|
|
304
|
+
} | null | undefined): {
|
|
305
|
+
id: string;
|
|
306
|
+
name?: string;
|
|
307
|
+
outline: {
|
|
308
|
+
x: number;
|
|
309
|
+
y: number;
|
|
310
|
+
}[];
|
|
311
|
+
}[];
|
|
267
312
|
/**
|
|
268
313
|
* Expand a benchwork outline (whose edges may be arcs) into a dense closed
|
|
269
314
|
* polyline for rendering — the SAME sampling both the Repository preview and
|
|
@@ -305,6 +350,9 @@ interface ModuleFootprintInput {
|
|
|
305
350
|
endplateTrackOffsets?: Record<string, number>;
|
|
306
351
|
/** Authored benchwork outline (module-local inches), or absent for the band. */
|
|
307
352
|
outline?: BenchworkPoint[] | null;
|
|
353
|
+
/** The module's sections (#96 phase 2). When any carries an outline, the
|
|
354
|
+
* module's footprint is the union of those — `outline` is then ignored. */
|
|
355
|
+
sections?: SchematicSection[] | null;
|
|
308
356
|
/** Authored mainline centre-line (module-local inches, open path with arcs).
|
|
309
357
|
* When present it wins over the geometry-derived centre-line — the owner drew
|
|
310
358
|
* the real shape (#2d-track, physical view only). */
|
|
@@ -323,8 +371,20 @@ interface ModuleFootprint {
|
|
|
323
371
|
band: BenchworkPoint[];
|
|
324
372
|
/** Endplate faces: [A end, B end]. */
|
|
325
373
|
endplateFaces: OutlineFace[];
|
|
326
|
-
/** Authored outline (arc-sampled closed ring) or null → render the band.
|
|
374
|
+
/** Authored outline (arc-sampled closed ring) or null → render the band.
|
|
375
|
+
* Null too when `sectionOutlines` is non-empty — the sections ARE the shape. */
|
|
327
376
|
outline: BenchworkPoint[] | null;
|
|
377
|
+
/** Per-section footprints, arc-sampled (#96 phase 2). Draw every one: together
|
|
378
|
+
* they are the module's footprint. Empty = this module doesn't use sections,
|
|
379
|
+
* so fall back to `outline ?? band` exactly as before. */
|
|
380
|
+
sectionOutlines: {
|
|
381
|
+
id: string;
|
|
382
|
+
name?: string;
|
|
383
|
+
outline: {
|
|
384
|
+
x: number;
|
|
385
|
+
y: number;
|
|
386
|
+
}[];
|
|
387
|
+
}[];
|
|
328
388
|
}
|
|
329
389
|
/** Module-local main track centre-line (A→B), sampling arcs for curves/corners.
|
|
330
390
|
* An authored `mainPath` wins — the owner drew the real shape; otherwise the
|
|
@@ -531,6 +591,9 @@ interface EditorState {
|
|
|
531
591
|
/** Internal section joints — inches from endplate A where the boards split
|
|
532
592
|
* into sections. Empty = a single section (#48). */
|
|
533
593
|
sectionBreaks: number[];
|
|
594
|
+
/** The module's sections as named objects, each optionally carrying its own
|
|
595
|
+
* outline (#96 phase 2). Empty = fall back to `outline` + `sectionBreaks`. */
|
|
596
|
+
sections: SchematicSection[];
|
|
534
597
|
controlPoints: EditorControlPoint[];
|
|
535
598
|
/** Rail-served industries — car-spot spans on a track (#industries). */
|
|
536
599
|
industries: EditorIndustry[];
|
|
@@ -815,4 +878,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
815
878
|
heading: number;
|
|
816
879
|
}>;
|
|
817
880
|
|
|
818
|
-
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, 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, 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, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, stateToDoc, trackPath };
|
|
881
|
+
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, 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, type SchematicBlock, type SchematicControlPoint, type SchematicCrossing, type SchematicEndplate, type SchematicEndplateTrack, type SchematicIndustry, type SchematicSection, type SchematicSignal, type SchematicTrack, type SchematicTurnout, type SignalFacing, type SignalSide, type TrackConfig, type TrackRole, type TurnoutKind, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionFootprints, stateToDoc, trackPath };
|
package/dist/index.d.ts
CHANGED
|
@@ -240,8 +240,22 @@ interface ModuleSchematicDoc {
|
|
|
240
240
|
outline?: BenchworkPoint[];
|
|
241
241
|
/** Internal section joints — inches from endplate A where the module's boards
|
|
242
242
|
* split into sections. Operationally one unit; these mark construction/transport
|
|
243
|
-
* seams (exempt from the end-interface standards). Empty/absent = one section.
|
|
243
|
+
* seams (exempt from the end-interface standards). Empty/absent = one section.
|
|
244
|
+
* Describes only sections that are full-depth SLICES; a section with a shape
|
|
245
|
+
* of its own lives in `sections` below. */
|
|
244
246
|
sectionBreaks?: number[];
|
|
247
|
+
/** The module's sections as real objects — named, each with a bench-work
|
|
248
|
+
* outline of its own (#96 phase 2). A module is a kit: the same sections can
|
|
249
|
+
* be set up in different combinations, so its footprint is the UNION of the
|
|
250
|
+
* sections present rather than an independently authored shape.
|
|
251
|
+
*
|
|
252
|
+
* Needed because sections are not slices. Real modules hang a deep section
|
|
253
|
+
* off the BACK of a shallow main band — a peninsula carrying an industry —
|
|
254
|
+
* which no single position along the main can describe.
|
|
255
|
+
*
|
|
256
|
+
* Absent = the module keeps using its own `outline` exactly as before; this
|
|
257
|
+
* is purely additive and nothing migrates on read. */
|
|
258
|
+
sections?: SchematicSection[];
|
|
245
259
|
/** @deprecated pre-grouping flat signals; read for back-compat. */
|
|
246
260
|
signals?: SchematicSignal[];
|
|
247
261
|
/** Authored mainline centre-line (module-local inches, open path with arcs).
|
|
@@ -258,12 +272,43 @@ interface BenchworkPoint {
|
|
|
258
272
|
y: number;
|
|
259
273
|
bulge?: number;
|
|
260
274
|
}
|
|
275
|
+
/** One bench-work section of a module (#96 phase 2). */
|
|
276
|
+
interface SchematicSection {
|
|
277
|
+
id: string;
|
|
278
|
+
/** What the owner calls this board — "west transition", "double #3". */
|
|
279
|
+
name?: string | null;
|
|
280
|
+
/** This section's own footprint polygon, module-local inches, same frame as
|
|
281
|
+
* the module outline. Absent = the section has no shape of its own yet (it's
|
|
282
|
+
* described only by the joints in `sectionBreaks`). */
|
|
283
|
+
outline?: BenchworkPoint[] | null;
|
|
284
|
+
}
|
|
261
285
|
/** The authored benchwork outline, or null when a module hasn't drawn one
|
|
262
286
|
* (renderers then fall back to a band derived from the endplate widths). A
|
|
263
287
|
* valid outline needs at least 3 points. Normalises each vertex to {x, y, bulge?}. */
|
|
264
288
|
declare function benchworkOutline(doc: {
|
|
265
289
|
outline?: BenchworkPoint[] | null;
|
|
266
290
|
} | null | undefined): BenchworkPoint[] | null;
|
|
291
|
+
/** The module's sections, normalised — id required, name trimmed away when
|
|
292
|
+
* blank, outline kept only when it's a usable polygon (#96 phase 2). */
|
|
293
|
+
declare function moduleSections(doc: {
|
|
294
|
+
sections?: SchematicSection[] | null;
|
|
295
|
+
} | null | undefined): SchematicSection[];
|
|
296
|
+
/** Every section outline that's actually a shape, arc-sampled for drawing.
|
|
297
|
+
* Drawing all of them IS the module's footprint — the union of its sections.
|
|
298
|
+
* No polygon boolean is computed: a renderer painting each ring gives the same
|
|
299
|
+
* picture, and an approximate union would be worse than none. If something
|
|
300
|
+
* ever needs a single ring (an export, a collision test), that's the point to
|
|
301
|
+
* bring in real clipping. */
|
|
302
|
+
declare function sectionFootprints(doc: {
|
|
303
|
+
sections?: SchematicSection[] | null;
|
|
304
|
+
} | null | undefined): {
|
|
305
|
+
id: string;
|
|
306
|
+
name?: string;
|
|
307
|
+
outline: {
|
|
308
|
+
x: number;
|
|
309
|
+
y: number;
|
|
310
|
+
}[];
|
|
311
|
+
}[];
|
|
267
312
|
/**
|
|
268
313
|
* Expand a benchwork outline (whose edges may be arcs) into a dense closed
|
|
269
314
|
* polyline for rendering — the SAME sampling both the Repository preview and
|
|
@@ -305,6 +350,9 @@ interface ModuleFootprintInput {
|
|
|
305
350
|
endplateTrackOffsets?: Record<string, number>;
|
|
306
351
|
/** Authored benchwork outline (module-local inches), or absent for the band. */
|
|
307
352
|
outline?: BenchworkPoint[] | null;
|
|
353
|
+
/** The module's sections (#96 phase 2). When any carries an outline, the
|
|
354
|
+
* module's footprint is the union of those — `outline` is then ignored. */
|
|
355
|
+
sections?: SchematicSection[] | null;
|
|
308
356
|
/** Authored mainline centre-line (module-local inches, open path with arcs).
|
|
309
357
|
* When present it wins over the geometry-derived centre-line — the owner drew
|
|
310
358
|
* the real shape (#2d-track, physical view only). */
|
|
@@ -323,8 +371,20 @@ interface ModuleFootprint {
|
|
|
323
371
|
band: BenchworkPoint[];
|
|
324
372
|
/** Endplate faces: [A end, B end]. */
|
|
325
373
|
endplateFaces: OutlineFace[];
|
|
326
|
-
/** Authored outline (arc-sampled closed ring) or null → render the band.
|
|
374
|
+
/** Authored outline (arc-sampled closed ring) or null → render the band.
|
|
375
|
+
* Null too when `sectionOutlines` is non-empty — the sections ARE the shape. */
|
|
327
376
|
outline: BenchworkPoint[] | null;
|
|
377
|
+
/** Per-section footprints, arc-sampled (#96 phase 2). Draw every one: together
|
|
378
|
+
* they are the module's footprint. Empty = this module doesn't use sections,
|
|
379
|
+
* so fall back to `outline ?? band` exactly as before. */
|
|
380
|
+
sectionOutlines: {
|
|
381
|
+
id: string;
|
|
382
|
+
name?: string;
|
|
383
|
+
outline: {
|
|
384
|
+
x: number;
|
|
385
|
+
y: number;
|
|
386
|
+
}[];
|
|
387
|
+
}[];
|
|
328
388
|
}
|
|
329
389
|
/** Module-local main track centre-line (A→B), sampling arcs for curves/corners.
|
|
330
390
|
* An authored `mainPath` wins — the owner drew the real shape; otherwise the
|
|
@@ -531,6 +591,9 @@ interface EditorState {
|
|
|
531
591
|
/** Internal section joints — inches from endplate A where the boards split
|
|
532
592
|
* into sections. Empty = a single section (#48). */
|
|
533
593
|
sectionBreaks: number[];
|
|
594
|
+
/** The module's sections as named objects, each optionally carrying its own
|
|
595
|
+
* outline (#96 phase 2). Empty = fall back to `outline` + `sectionBreaks`. */
|
|
596
|
+
sections: SchematicSection[];
|
|
534
597
|
controlPoints: EditorControlPoint[];
|
|
535
598
|
/** Rail-served industries — car-spot spans on a track (#industries). */
|
|
536
599
|
industries: EditorIndustry[];
|
|
@@ -815,4 +878,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
815
878
|
heading: number;
|
|
816
879
|
}>;
|
|
817
880
|
|
|
818
|
-
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, 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, 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, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, stateToDoc, trackPath };
|
|
881
|
+
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, 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, type SchematicBlock, type SchematicControlPoint, type SchematicCrossing, type SchematicEndplate, type SchematicEndplateTrack, type SchematicIndustry, type SchematicSection, type SchematicSignal, type SchematicTrack, type SchematicTurnout, type SignalFacing, type SignalSide, type TrackConfig, type TrackRole, type TurnoutKind, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionFootprints, stateToDoc, trackPath };
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,24 @@ function benchworkOutline(doc) {
|
|
|
15
15
|
}));
|
|
16
16
|
return pts.length >= 3 ? pts : null;
|
|
17
17
|
}
|
|
18
|
+
function moduleSections(doc) {
|
|
19
|
+
return (doc?.sections ?? []).filter((sec) => sec && typeof sec.id === "string" && sec.id !== "").map((sec) => {
|
|
20
|
+
const outline = benchworkOutline({ outline: sec.outline });
|
|
21
|
+
const name = typeof sec.name === "string" ? sec.name.trim() : "";
|
|
22
|
+
return {
|
|
23
|
+
id: sec.id,
|
|
24
|
+
...name ? { name } : {},
|
|
25
|
+
...outline ? { outline } : {}
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function sectionFootprints(doc) {
|
|
30
|
+
return moduleSections(doc).filter((sec) => sec.outline).map((sec) => ({
|
|
31
|
+
id: sec.id,
|
|
32
|
+
...sec.name ? { name: sec.name } : {},
|
|
33
|
+
outline: sampleBenchworkOutline(sec.outline)
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
18
36
|
function sampleBenchworkOutline(pts, segsPerArc = 20) {
|
|
19
37
|
const n = pts.length;
|
|
20
38
|
if (n < 2) return pts.map((p) => ({ x: p.x, y: p.y }));
|
|
@@ -177,11 +195,13 @@ function moduleFootprint(input) {
|
|
|
177
195
|
const authored = benchworkOutline(input);
|
|
178
196
|
const offA = input.endplateTrackOffsets?.["A"] ?? 0;
|
|
179
197
|
const offB = input.endplateTrackOffsets?.["B"] ?? 0;
|
|
198
|
+
const sectionOutlines = sectionFootprints(input);
|
|
180
199
|
return {
|
|
181
200
|
centerline,
|
|
182
201
|
band: benchworkBand(centerline, widthA, widthB, offA, offB),
|
|
183
202
|
endplateFaces: endplateFaceSegments(centerline, widthA, widthB, offA, offB),
|
|
184
|
-
outline: authored ? sampleBenchworkOutline(authored)
|
|
203
|
+
outline: sectionOutlines.length || !authored ? null : sampleBenchworkOutline(authored),
|
|
204
|
+
sectionOutlines
|
|
185
205
|
};
|
|
186
206
|
}
|
|
187
207
|
function endplateTrackOffsetFor(config, authoredTrackOffset) {
|
|
@@ -202,8 +222,8 @@ function checkEndplateWidth(input) {
|
|
|
202
222
|
requiredInches: FREEMO_ENDPLATE_WIDTH_MIN_INCHES
|
|
203
223
|
});
|
|
204
224
|
}
|
|
205
|
-
const off = input.trackOffsetInches ?? 0;
|
|
206
|
-
const centres = input.config === "double" ? [off
|
|
225
|
+
const off = endplateTrackOffsetInches(input.trackOffsetInches, input.config ?? void 0);
|
|
226
|
+
const centres = input.config === "double" ? [off, off + FREEMO_TRACK_SPACING_INCHES] : [off];
|
|
207
227
|
const worst = Math.max(...centres.map((c) => Math.abs(c)));
|
|
208
228
|
const clearance = width / 2 - worst;
|
|
209
229
|
if (clearance < FREEMO_ENDPLATE_TRACK_FASCIA_CLEARANCE_INCHES) {
|
|
@@ -262,6 +282,7 @@ function emptyEditorState(lengthInches) {
|
|
|
262
282
|
endplateTrackOffsets: {},
|
|
263
283
|
outline: [],
|
|
264
284
|
sectionBreaks: [],
|
|
285
|
+
sections: [],
|
|
265
286
|
controlPoints: [],
|
|
266
287
|
industries: [],
|
|
267
288
|
mainPath: []
|
|
@@ -485,6 +506,9 @@ function stateToDoc(state, recordNumber) {
|
|
|
485
506
|
...state.outline.length >= 3 ? { outline: state.outline } : {},
|
|
486
507
|
// Internal section joints (inches from A), when the module has more than one.
|
|
487
508
|
...state.sectionBreaks.length ? { sectionBreaks: state.sectionBreaks } : {},
|
|
509
|
+
// Sections as objects — emitted only once the owner has some, so a module
|
|
510
|
+
// that never used them keeps exactly the doc it had before (#96 phase 2).
|
|
511
|
+
...state.sections.length ? { sections: moduleSections({ sections: state.sections }) } : {},
|
|
488
512
|
// Authored mainline path (module-local inches); only when it's a real path.
|
|
489
513
|
...state.mainPath.length >= 2 ? { mainPath: state.mainPath } : {}
|
|
490
514
|
};
|
|
@@ -590,6 +614,7 @@ function docToState(doc, fallbackLength, moduleTracks = []) {
|
|
|
590
614
|
endplateTrackOffsets,
|
|
591
615
|
outline,
|
|
592
616
|
sectionBreaks: (d.sectionBreaks ?? []).filter((n) => Number.isFinite(n)).map((n) => sc(n)),
|
|
617
|
+
sections: moduleSections(d),
|
|
593
618
|
mainPath,
|
|
594
619
|
crossings: (d.crossings ?? []).map((x) => ({
|
|
595
620
|
id: x.id,
|
|
@@ -1091,6 +1116,6 @@ function poseOverridesFromDoc(doc) {
|
|
|
1091
1116
|
return out;
|
|
1092
1117
|
}
|
|
1093
1118
|
|
|
1094
|
-
export { 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, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, stateToDoc, trackPath };
|
|
1119
|
+
export { 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, asModuleSchematic, benchworkBand, benchworkOutline, buildCrossover, buildPassingSiding, buildTransition, carCapacity, checkEndplateWidth, deriveEndplatePoses, divergeSideForHand, docToState, emptyEditorState, endplateFaceSegments, endplateTrackOffsetFor, endplateTrackOffsetInches, endplateWidthInches, geometryTurnDegrees, inchesToScaleFeet, isLoopDoc, isTransitionTurnout, moduleCenterline, moduleFeatures, moduleFootprint, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionFootprints, stateToDoc, trackPath };
|
|
1095
1120
|
//# sourceMappingURL=index.js.map
|
|
1096
1121
|
//# sourceMappingURL=index.js.map
|