@willcgage/module-schematic 0.45.0 → 0.47.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.d.cts CHANGED
@@ -412,6 +412,9 @@ interface ModuleFootprintInput {
412
412
  * When present it wins over the geometry-derived centre-line — the owner drew
413
413
  * the real shape (#2d-track, physical view only). */
414
414
  mainPath?: BenchworkPoint[] | null;
415
+ /** A balloon / return loop — the centre-line turns back on itself, so its far
416
+ * end is the THROAT, not an endplate; only endplate A's face is emitted (#loop). */
417
+ loop?: boolean;
415
418
  }
416
419
  interface OutlineFace {
417
420
  /** The endplate face's two corners + midpoint (the track point). */
@@ -1067,6 +1070,11 @@ interface ModuleGeometryInput {
1067
1070
  * so endplate B lands at the end of the CHAINED boards rather than where a
1068
1071
  * single module-level geometry would have put it (#108). */
1069
1072
  sections?: SchematicSection[] | null;
1073
+ /** A balloon / return loop: the main runs out and turns back on itself, so the
1074
+ * module has ONE endplate (A). No far endplate B is derived — the chain closes
1075
+ * back near the throat, and a B there would just be a spurious plate on the
1076
+ * loop. An interchange endplate on the balloon is placed separately (#loop). */
1077
+ loop?: boolean;
1070
1078
  }
1071
1079
  /** Signed turn a module applies to the through track (CCW/left positive). */
1072
1080
  declare function geometryTurnDegrees(geometryType?: string | null, geometryDegrees?: number | null): number;
package/dist/index.d.ts CHANGED
@@ -412,6 +412,9 @@ interface ModuleFootprintInput {
412
412
  * When present it wins over the geometry-derived centre-line — the owner drew
413
413
  * the real shape (#2d-track, physical view only). */
414
414
  mainPath?: BenchworkPoint[] | null;
415
+ /** A balloon / return loop — the centre-line turns back on itself, so its far
416
+ * end is the THROAT, not an endplate; only endplate A's face is emitted (#loop). */
417
+ loop?: boolean;
415
418
  }
416
419
  interface OutlineFace {
417
420
  /** The endplate face's two corners + midpoint (the track point). */
@@ -1067,6 +1070,11 @@ interface ModuleGeometryInput {
1067
1070
  * so endplate B lands at the end of the CHAINED boards rather than where a
1068
1071
  * single module-level geometry would have put it (#108). */
1069
1072
  sections?: SchematicSection[] | null;
1073
+ /** A balloon / return loop: the main runs out and turns back on itself, so the
1074
+ * module has ONE endplate (A). No far endplate B is derived — the chain closes
1075
+ * back near the throat, and a B there would just be a spurious plate on the
1076
+ * loop. An interchange endplate on the balloon is placed separately (#loop). */
1077
+ loop?: boolean;
1070
1078
  }
1071
1079
  /** Signed turn a module applies to the through track (CCW/left positive). */
1072
1080
  declare function geometryTurnDegrees(geometryType?: string | null, geometryDegrees?: number | null): number;
package/dist/index.js CHANGED
@@ -472,7 +472,9 @@ function moduleFootprint(input) {
472
472
  return {
473
473
  centerline,
474
474
  band: benchworkBand(centerline, widthA, widthB, offA, offB),
475
- endplateFaces: endplateFaceSegments(centerline, widthA, widthB, offA, offB),
475
+ // A loop's centre-line ends at the throat, not a far endplate — keep only
476
+ // endplate A's face (the far face would be a spurious plate at the throat).
477
+ endplateFaces: input.loop ? endplateFaceSegments(centerline, widthA, widthB, offA, offB).slice(0, 1) : endplateFaceSegments(centerline, widthA, widthB, offA, offB),
476
478
  outline: sectionOutlines.length || !authored ? null : sampleBenchworkOutline(authored),
477
479
  sectionOutlines
478
480
  };
@@ -1354,7 +1356,7 @@ function deriveEndplatePoses(geo) {
1354
1356
  trackOffsets: offsetsFor(cfg(0), half)
1355
1357
  })
1356
1358
  );
1357
- const noB = geo.geometryType === "dead_end";
1359
+ const noB = geo.geometryType === "dead_end" || geo.loop === true;
1358
1360
  const end = sectionedEndPose({ sections: geo.sections });
1359
1361
  if (!noB && end) {
1360
1362
  poses.push(