@willcgage/module-schematic 0.30.0 → 0.31.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 +86 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -18
- package/dist/index.d.ts +39 -18
- package/dist/index.js +85 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -273,6 +273,18 @@ interface BenchworkPoint {
|
|
|
273
273
|
bulge?: number;
|
|
274
274
|
}
|
|
275
275
|
/** One bench-work section of a module (#96 phase 2). */
|
|
276
|
+
interface SectionFootprint {
|
|
277
|
+
id: string;
|
|
278
|
+
name?: string;
|
|
279
|
+
outline: {
|
|
280
|
+
x: number;
|
|
281
|
+
y: number;
|
|
282
|
+
}[];
|
|
283
|
+
/** True when this shape is DERIVED from the section's span rather than
|
|
284
|
+
* authored — a derived outline follows the board when it's resized, an
|
|
285
|
+
* authored one stays exactly as drawn (#96 phase 2b). */
|
|
286
|
+
derived: boolean;
|
|
287
|
+
}
|
|
276
288
|
interface SchematicSection {
|
|
277
289
|
id: string;
|
|
278
290
|
/** What the owner calls this board — "west transition", "double #3". */
|
|
@@ -314,14 +326,18 @@ declare function moduleSections(doc: {
|
|
|
314
326
|
* bring in real clipping. */
|
|
315
327
|
declare function sectionFootprints(doc: {
|
|
316
328
|
sections?: SchematicSection[] | null;
|
|
317
|
-
} | null | undefined
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
329
|
+
} | null | undefined,
|
|
330
|
+
/** The module's spine and dimensions. Given these, a section with no
|
|
331
|
+
* authored polygon gets a band derived from its own span, so every section
|
|
332
|
+
* has a shape and a resized board reshapes with it (#96 phase 2b). Omit to
|
|
333
|
+
* get authored outlines only. */
|
|
334
|
+
derive?: {
|
|
335
|
+
centerline: BenchworkPoint[];
|
|
336
|
+
widthA: number;
|
|
337
|
+
widthB: number;
|
|
338
|
+
offsetA: number;
|
|
339
|
+
offsetB: number;
|
|
340
|
+
}): SectionFootprint[];
|
|
325
341
|
/**
|
|
326
342
|
* Expand a benchwork outline (whose edges may be arcs) into a dense closed
|
|
327
343
|
* polyline for rendering — the SAME sampling both the Repository preview and
|
|
@@ -387,17 +403,10 @@ interface ModuleFootprint {
|
|
|
387
403
|
/** Authored outline (arc-sampled closed ring) or null → render the band.
|
|
388
404
|
* Null too when `sectionOutlines` is non-empty — the sections ARE the shape. */
|
|
389
405
|
outline: BenchworkPoint[] | null;
|
|
390
|
-
/** Per-section footprints, arc-sampled (#96 phase
|
|
406
|
+
/** Per-section footprints, arc-sampled (#96 phase 2b). Draw every one: together
|
|
391
407
|
* they are the module's footprint. Empty = this module doesn't use sections,
|
|
392
408
|
* so fall back to `outline ?? band` exactly as before. */
|
|
393
|
-
sectionOutlines:
|
|
394
|
-
id: string;
|
|
395
|
-
name?: string;
|
|
396
|
-
outline: {
|
|
397
|
-
x: number;
|
|
398
|
-
y: number;
|
|
399
|
-
}[];
|
|
400
|
-
}[];
|
|
409
|
+
sectionOutlines: SectionFootprint[];
|
|
401
410
|
}
|
|
402
411
|
/** Module-local main track centre-line (A→B), sampling arcs for curves/corners.
|
|
403
412
|
* An authored `mainPath` wins — the owner drew the real shape; otherwise the
|
|
@@ -434,6 +443,18 @@ declare function sectionedCenterline(doc: {
|
|
|
434
443
|
} | null | undefined): BenchworkPoint[];
|
|
435
444
|
/** Benchwork band: the centre-line offset ±half-width, tapering widthA→widthB. */
|
|
436
445
|
declare function benchworkBand(center: BenchworkPoint[], widthA?: number, widthB?: number, offsetA?: number, offsetB?: number): BenchworkPoint[];
|
|
446
|
+
/** The sub-polyline of a centre-line between two arc-length positions, with
|
|
447
|
+
* the cut ends interpolated so a slice starts and finishes exactly on them. */
|
|
448
|
+
declare function sliceCenterline(center: BenchworkPoint[], fromPos: number, toPos: number): BenchworkPoint[];
|
|
449
|
+
/** One section's bench-work as a band over its own stretch of centre-line —
|
|
450
|
+
* the per-section equivalent of `benchworkBand` (#96 phase 2b). Width and
|
|
451
|
+
* plate offset are interpolated from the module's ends exactly as the whole
|
|
452
|
+
* band does, so a section's derived shape lines up with its neighbours.
|
|
453
|
+
*
|
|
454
|
+
* This is what makes an outline BELONG to the section: a section without an
|
|
455
|
+
* authored polygon gets one derived from its span, so resizing the board
|
|
456
|
+
* reshapes it instead of leaving a hand-drawn outline stranded. */
|
|
457
|
+
declare function sectionBand(center: BenchworkPoint[], fromPos: number, toPos: number, widthA?: number, widthB?: number, offsetA?: number, offsetB?: number): BenchworkPoint[];
|
|
437
458
|
/** The two endplate faces (the band's flat ends): [A end at widthA, B end at widthB]. */
|
|
438
459
|
declare function endplateFaceSegments(center: BenchworkPoint[], widthA?: number, widthB?: number, offsetA?: number, offsetB?: number): OutlineFace[];
|
|
439
460
|
/**
|
|
@@ -920,4 +941,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
920
941
|
heading: number;
|
|
921
942
|
}>;
|
|
922
943
|
|
|
923
|
-
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, moduleLengthFromSections, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionBreaksFromSections, sectionFootprints, sectionSpans, sectionedCenterline, stateToDoc, trackPath };
|
|
944
|
+
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 SectionFootprint, 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, moduleLengthFromSections, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionBand, sectionBreaksFromSections, sectionFootprints, sectionSpans, sectionedCenterline, sliceCenterline, stateToDoc, trackPath };
|
package/dist/index.d.ts
CHANGED
|
@@ -273,6 +273,18 @@ interface BenchworkPoint {
|
|
|
273
273
|
bulge?: number;
|
|
274
274
|
}
|
|
275
275
|
/** One bench-work section of a module (#96 phase 2). */
|
|
276
|
+
interface SectionFootprint {
|
|
277
|
+
id: string;
|
|
278
|
+
name?: string;
|
|
279
|
+
outline: {
|
|
280
|
+
x: number;
|
|
281
|
+
y: number;
|
|
282
|
+
}[];
|
|
283
|
+
/** True when this shape is DERIVED from the section's span rather than
|
|
284
|
+
* authored — a derived outline follows the board when it's resized, an
|
|
285
|
+
* authored one stays exactly as drawn (#96 phase 2b). */
|
|
286
|
+
derived: boolean;
|
|
287
|
+
}
|
|
276
288
|
interface SchematicSection {
|
|
277
289
|
id: string;
|
|
278
290
|
/** What the owner calls this board — "west transition", "double #3". */
|
|
@@ -314,14 +326,18 @@ declare function moduleSections(doc: {
|
|
|
314
326
|
* bring in real clipping. */
|
|
315
327
|
declare function sectionFootprints(doc: {
|
|
316
328
|
sections?: SchematicSection[] | null;
|
|
317
|
-
} | null | undefined
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
329
|
+
} | null | undefined,
|
|
330
|
+
/** The module's spine and dimensions. Given these, a section with no
|
|
331
|
+
* authored polygon gets a band derived from its own span, so every section
|
|
332
|
+
* has a shape and a resized board reshapes with it (#96 phase 2b). Omit to
|
|
333
|
+
* get authored outlines only. */
|
|
334
|
+
derive?: {
|
|
335
|
+
centerline: BenchworkPoint[];
|
|
336
|
+
widthA: number;
|
|
337
|
+
widthB: number;
|
|
338
|
+
offsetA: number;
|
|
339
|
+
offsetB: number;
|
|
340
|
+
}): SectionFootprint[];
|
|
325
341
|
/**
|
|
326
342
|
* Expand a benchwork outline (whose edges may be arcs) into a dense closed
|
|
327
343
|
* polyline for rendering — the SAME sampling both the Repository preview and
|
|
@@ -387,17 +403,10 @@ interface ModuleFootprint {
|
|
|
387
403
|
/** Authored outline (arc-sampled closed ring) or null → render the band.
|
|
388
404
|
* Null too when `sectionOutlines` is non-empty — the sections ARE the shape. */
|
|
389
405
|
outline: BenchworkPoint[] | null;
|
|
390
|
-
/** Per-section footprints, arc-sampled (#96 phase
|
|
406
|
+
/** Per-section footprints, arc-sampled (#96 phase 2b). Draw every one: together
|
|
391
407
|
* they are the module's footprint. Empty = this module doesn't use sections,
|
|
392
408
|
* so fall back to `outline ?? band` exactly as before. */
|
|
393
|
-
sectionOutlines:
|
|
394
|
-
id: string;
|
|
395
|
-
name?: string;
|
|
396
|
-
outline: {
|
|
397
|
-
x: number;
|
|
398
|
-
y: number;
|
|
399
|
-
}[];
|
|
400
|
-
}[];
|
|
409
|
+
sectionOutlines: SectionFootprint[];
|
|
401
410
|
}
|
|
402
411
|
/** Module-local main track centre-line (A→B), sampling arcs for curves/corners.
|
|
403
412
|
* An authored `mainPath` wins — the owner drew the real shape; otherwise the
|
|
@@ -434,6 +443,18 @@ declare function sectionedCenterline(doc: {
|
|
|
434
443
|
} | null | undefined): BenchworkPoint[];
|
|
435
444
|
/** Benchwork band: the centre-line offset ±half-width, tapering widthA→widthB. */
|
|
436
445
|
declare function benchworkBand(center: BenchworkPoint[], widthA?: number, widthB?: number, offsetA?: number, offsetB?: number): BenchworkPoint[];
|
|
446
|
+
/** The sub-polyline of a centre-line between two arc-length positions, with
|
|
447
|
+
* the cut ends interpolated so a slice starts and finishes exactly on them. */
|
|
448
|
+
declare function sliceCenterline(center: BenchworkPoint[], fromPos: number, toPos: number): BenchworkPoint[];
|
|
449
|
+
/** One section's bench-work as a band over its own stretch of centre-line —
|
|
450
|
+
* the per-section equivalent of `benchworkBand` (#96 phase 2b). Width and
|
|
451
|
+
* plate offset are interpolated from the module's ends exactly as the whole
|
|
452
|
+
* band does, so a section's derived shape lines up with its neighbours.
|
|
453
|
+
*
|
|
454
|
+
* This is what makes an outline BELONG to the section: a section without an
|
|
455
|
+
* authored polygon gets one derived from its span, so resizing the board
|
|
456
|
+
* reshapes it instead of leaving a hand-drawn outline stranded. */
|
|
457
|
+
declare function sectionBand(center: BenchworkPoint[], fromPos: number, toPos: number, widthA?: number, widthB?: number, offsetA?: number, offsetB?: number): BenchworkPoint[];
|
|
437
458
|
/** The two endplate faces (the band's flat ends): [A end at widthA, B end at widthB]. */
|
|
438
459
|
declare function endplateFaceSegments(center: BenchworkPoint[], widthA?: number, widthB?: number, offsetA?: number, offsetB?: number): OutlineFace[];
|
|
439
460
|
/**
|
|
@@ -920,4 +941,4 @@ declare function poseOverridesFromDoc(doc: ModuleSchematicDoc): Record<string, {
|
|
|
920
941
|
heading: number;
|
|
921
942
|
}>;
|
|
922
943
|
|
|
923
|
-
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, moduleLengthFromSections, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionBreaksFromSections, sectionFootprints, sectionSpans, sectionedCenterline, stateToDoc, trackPath };
|
|
944
|
+
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 SectionFootprint, 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, moduleLengthFromSections, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionBand, sectionBreaksFromSections, sectionFootprints, sectionSpans, sectionedCenterline, sliceCenterline, stateToDoc, trackPath };
|
package/dist/index.js
CHANGED
|
@@ -33,12 +33,26 @@ function moduleSections(doc) {
|
|
|
33
33
|
};
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
|
-
function sectionFootprints(doc) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
function sectionFootprints(doc, derive) {
|
|
37
|
+
const spans = derive ? sectionSpans(doc) : [];
|
|
38
|
+
const spanOf = new Map(spans.map((sp) => [sp.id, sp]));
|
|
39
|
+
return moduleSections(doc).map((sec) => {
|
|
40
|
+
const name = sec.name ? { name: sec.name } : {};
|
|
41
|
+
if (sec.outline)
|
|
42
|
+
return { id: sec.id, ...name, outline: sampleBenchworkOutline(sec.outline), derived: false };
|
|
43
|
+
const sp = spanOf.get(sec.id);
|
|
44
|
+
if (!sp || !derive) return null;
|
|
45
|
+
const band = sectionBand(
|
|
46
|
+
derive.centerline,
|
|
47
|
+
sp.fromPos,
|
|
48
|
+
sp.toPos,
|
|
49
|
+
derive.widthA,
|
|
50
|
+
derive.widthB,
|
|
51
|
+
derive.offsetA,
|
|
52
|
+
derive.offsetB
|
|
53
|
+
);
|
|
54
|
+
return band.length >= 3 ? { id: sec.id, ...name, outline: band, derived: true } : null;
|
|
55
|
+
}).filter((x) => x !== null);
|
|
42
56
|
}
|
|
43
57
|
function sampleBenchworkOutline(pts, segsPerArc = 20) {
|
|
44
58
|
const n = pts.length;
|
|
@@ -254,6 +268,63 @@ function benchworkBand(center, widthA = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES
|
|
|
254
268
|
}));
|
|
255
269
|
return [...left, ...right.reverse()];
|
|
256
270
|
}
|
|
271
|
+
function sliceCenterline(center, fromPos, toPos) {
|
|
272
|
+
if (center.length < 2) return [];
|
|
273
|
+
const cum = [0];
|
|
274
|
+
for (let i = 1; i < center.length; i++)
|
|
275
|
+
cum.push(cum[i - 1] + Math.hypot(center[i].x - center[i - 1].x, center[i].y - center[i - 1].y));
|
|
276
|
+
const total = cum[cum.length - 1];
|
|
277
|
+
const a = Math.max(0, Math.min(total, Math.min(fromPos, toPos)));
|
|
278
|
+
const b = Math.max(0, Math.min(total, Math.max(fromPos, toPos)));
|
|
279
|
+
if (b - a <= 0) return [];
|
|
280
|
+
const at = (d) => {
|
|
281
|
+
for (let i = 1; i < center.length; i++) {
|
|
282
|
+
if (d <= cum[i] || i === center.length - 1) {
|
|
283
|
+
const seg = cum[i] - cum[i - 1] || 1;
|
|
284
|
+
const t = Math.max(0, Math.min(1, (d - cum[i - 1]) / seg));
|
|
285
|
+
return {
|
|
286
|
+
x: center[i - 1].x + (center[i].x - center[i - 1].x) * t,
|
|
287
|
+
y: center[i - 1].y + (center[i].y - center[i - 1].y) * t
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return center[center.length - 1];
|
|
292
|
+
};
|
|
293
|
+
const out = [at(a)];
|
|
294
|
+
for (let i = 0; i < center.length; i++) {
|
|
295
|
+
if (cum[i] > a && cum[i] < b) out.push({ x: center[i].x, y: center[i].y });
|
|
296
|
+
}
|
|
297
|
+
out.push(at(b));
|
|
298
|
+
return out;
|
|
299
|
+
}
|
|
300
|
+
function sectionBand(center, fromPos, toPos, widthA = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, widthB = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, offsetA = 0, offsetB = 0) {
|
|
301
|
+
const slice = sliceCenterline(center, fromPos, toPos);
|
|
302
|
+
if (slice.length < 2) return [];
|
|
303
|
+
let total = 0;
|
|
304
|
+
for (let i = 1; i < center.length; i++)
|
|
305
|
+
total += Math.hypot(center[i].x - center[i - 1].x, center[i].y - center[i - 1].y);
|
|
306
|
+
total = total || 1;
|
|
307
|
+
const lo = Math.min(fromPos, toPos);
|
|
308
|
+
let acc = 0;
|
|
309
|
+
const fr = [0];
|
|
310
|
+
for (let i = 1; i < slice.length; i++) {
|
|
311
|
+
acc += Math.hypot(slice[i].x - slice[i - 1].x, slice[i].y - slice[i - 1].y);
|
|
312
|
+
fr.push(acc);
|
|
313
|
+
}
|
|
314
|
+
const f = fr.map((d) => Math.max(0, Math.min(1, (lo + d) / total)));
|
|
315
|
+
const n = centerlineNormals(slice);
|
|
316
|
+
const half = (i) => (widthA * (1 - f[i]) + widthB * f[i]) / 2;
|
|
317
|
+
const off = (i) => offsetA * (1 - f[i]) + offsetB * f[i];
|
|
318
|
+
const left = slice.map((p, i) => ({
|
|
319
|
+
x: p.x + n[i].x * (off(i) + half(i)),
|
|
320
|
+
y: p.y + n[i].y * (off(i) + half(i))
|
|
321
|
+
}));
|
|
322
|
+
const right = slice.map((p, i) => ({
|
|
323
|
+
x: p.x + n[i].x * (off(i) - half(i)),
|
|
324
|
+
y: p.y + n[i].y * (off(i) - half(i))
|
|
325
|
+
}));
|
|
326
|
+
return [...left, ...right.reverse()];
|
|
327
|
+
}
|
|
257
328
|
function endplateFaceSegments(center, widthA = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, widthB = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, offsetA = 0, offsetB = 0) {
|
|
258
329
|
if (center.length < 2) return [];
|
|
259
330
|
const n = centerlineNormals(center);
|
|
@@ -271,7 +342,13 @@ function moduleFootprint(input) {
|
|
|
271
342
|
const authored = benchworkOutline(input);
|
|
272
343
|
const offA = input.endplateTrackOffsets?.["A"] ?? 0;
|
|
273
344
|
const offB = input.endplateTrackOffsets?.["B"] ?? 0;
|
|
274
|
-
const sectionOutlines = sectionFootprints(input
|
|
345
|
+
const sectionOutlines = sectionFootprints(input, {
|
|
346
|
+
centerline,
|
|
347
|
+
widthA,
|
|
348
|
+
widthB,
|
|
349
|
+
offsetA: offA,
|
|
350
|
+
offsetB: offB
|
|
351
|
+
});
|
|
275
352
|
return {
|
|
276
353
|
centerline,
|
|
277
354
|
band: benchworkBand(centerline, widthA, widthB, offA, offB),
|
|
@@ -1192,6 +1269,6 @@ function poseOverridesFromDoc(doc) {
|
|
|
1192
1269
|
return out;
|
|
1193
1270
|
}
|
|
1194
1271
|
|
|
1195
|
-
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, moduleLengthFromSections, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionBreaksFromSections, sectionFootprints, sectionSpans, sectionedCenterline, stateToDoc, trackPath };
|
|
1272
|
+
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, moduleLengthFromSections, moduleSections, nextId, poseNeedsManual, poseOverridesFromDoc, sampleBenchworkOutline, samplePath, scaleFeetToInches, sectionBand, sectionBreaksFromSections, sectionFootprints, sectionSpans, sectionedCenterline, sliceCenterline, stateToDoc, trackPath };
|
|
1196
1273
|
//# sourceMappingURL=index.js.map
|
|
1197
1274
|
//# sourceMappingURL=index.js.map
|