@willcgage/module-schematic 0.110.0 → 0.112.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
@@ -93,9 +93,24 @@ declare const FREEMO_ENDPLATE_WIDTH_MIN_INCHES = 12;
93
93
  * ("Endplates shall be 6 inches high and a minimum 12 inches wide"). 24″ is
94
94
  * simply a common real-world width. Don't present it as required. */
95
95
  declare const FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES = 24;
96
- /** Free-moN §2.0 **standard**: "Double track endplates must have a track spacing
96
+ /**
97
+ * Free-moN §2.0 **standard**: "Double track endplates must have a track spacing
97
98
  * of 1.125 inches (1 1/8 inches). Track spacing shall be measured along the
98
- * track center line." The one definition both apps read. */
99
+ * track center line." The one definition both apps read.
100
+ *
101
+ * ⚠️⚠️ **READ THE SCOPE, NOT JUST THE NUMBER.** This governs a **double-track
102
+ * ENDPLATE**, and reaches **4″ inboard** of it — §2.0's other standard is that
103
+ * track crossing an endplate be "perpendicular, straight, and level for at least
104
+ * 4 inches from the outside face". **Beyond those 4 inches the standard says
105
+ * nothing about how far apart the mains run**, and every real crossover draws
106
+ * them closer than this (the Fast Tracks N fixtures are 1.09″).
107
+ *
108
+ * ⛔ So this is a value to BUILD TO at an endplate, and **never a test to
109
+ * measure mid-module track against**. Used as one it amber-flagged ordinary,
110
+ * correctly built trackwork as departing from the standard (Will, 2026-07-28).
111
+ * It is also the default LANE PITCH for drawing parallel track, which is a
112
+ * separate job — a drawing convention, not a rule anything conforms to.
113
+ */
99
114
  declare const FREEMO_TRACK_SPACING_INCHES = 1.125;
100
115
  /** Free-moN §2.0 **standard**: track crossing an endplate must be "not less than
101
116
  * 4 inches from either fascia" (and perpendicular, straight and level for 4″). */
@@ -155,12 +170,17 @@ declare const PINCH_EASE_INCHES = 3;
155
170
  */
156
171
  declare function laneOffsetAt(lane: number, pos: number, pinches?: LanePinch[] | null, spacingInches?: number): number;
157
172
  /**
158
- * The pinches a document's crossovers impose — one per crossover connector that
159
- * names a part whose {@link TrackPart.trackSpacing} differs from the standard.
173
+ * The pinches a document's crossovers impose — one per crossover connector whose
174
+ * part is built to a different spacing from the mains either side of it.
175
+ *
176
+ * ⚠️ A PINCH IS GEOMETRY, NOT A FAULT. §2.0 fixes the 1.125″ spacing AT THE
177
+ * ENDPLATE; what the mains do in between is the builder's business, and every
178
+ * real crossover draws them closer. This says where the drawing must narrow, and
179
+ * nothing about conformance.
160
180
  *
161
- * A crossover with no part named, or one built to the standard spacing, imposes
162
- * nothing: an owner who hasn't said what they built gets the straight pair they
163
- * had before, which is the only honest default.
181
+ * A crossover with no part named, or one built to the same spacing as the mains,
182
+ * imposes nothing: an owner who hasn't said what they built gets the straight
183
+ * pair they had before, which is the only honest default.
164
184
  */
165
185
  declare function crossoverPinches(tracks: Array<{
166
186
  role?: string;
@@ -1773,14 +1793,19 @@ interface TrackPart {
1773
1793
  crossingAngleDeg?: number;
1774
1794
  /** Centre-to-centre distance of the two parallel tracks a {@link kind}
1775
1795
  * `crossover` joins. A crossover fixture is BUILT for one spacing — it is not
1776
- * adjustable — so this decides whether the part suits a given standard at all.
1796
+ * adjustable — so this is what the mains must pinch to where it sits.
1797
+ *
1798
+ * ⚠️ **NOT A CONFORMANCE TEST.** {@link FREEMO_TRACK_SPACING_INCHES} is fixed
1799
+ * by §2.0 **at the endplate** — "double track endplates must have a track
1800
+ * spacing of 1.125 inches", perpendicular, straight and level for 4″ from the
1801
+ * outside face. What the two mains do in between is the module builder's
1802
+ * business, and EVERY real crossover pinches them closer: the Fast Tracks N
1803
+ * fixtures are 1.09″. Earlier wording here said this "decides whether the part
1804
+ * suits a given standard at all", which is wrong and put an amber
1805
+ * non-conformance note on ordinary, correctly built trackwork.
1777
1806
  *
1778
- * ⚠️ READ {@link FREEMO_TRACK_SPACING_INCHES} ALONGSIDE THIS. Free-moN §2.0
1779
- * fixes double-track spacing at exactly 1.125″; the Fast Tracks N crossovers
1780
- * are built to 1.09″. That 0.035″ is small but it is REAL and it is not a
1781
- * tolerance — the fixture cannot be built to another spacing. Recorded rather
1782
- * than reconciled: it is a fact about the product, and an owner deciding what
1783
- * to buy is better served by the true number than by a convenient one. */
1807
+ * Recorded because it is a fact about the product an owner needs when buying,
1808
+ * and because the drawing has to pinch the mains to it. */
1784
1809
  trackSpacing?: PartDimension;
1785
1810
  /** The SECOND frog angle on a part that has two — the SCISSORS of a double
1786
1811
  * crossover, the X where its two opposite diverging routes meet and cross.
package/dist/index.d.ts CHANGED
@@ -93,9 +93,24 @@ declare const FREEMO_ENDPLATE_WIDTH_MIN_INCHES = 12;
93
93
  * ("Endplates shall be 6 inches high and a minimum 12 inches wide"). 24″ is
94
94
  * simply a common real-world width. Don't present it as required. */
95
95
  declare const FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES = 24;
96
- /** Free-moN §2.0 **standard**: "Double track endplates must have a track spacing
96
+ /**
97
+ * Free-moN §2.0 **standard**: "Double track endplates must have a track spacing
97
98
  * of 1.125 inches (1 1/8 inches). Track spacing shall be measured along the
98
- * track center line." The one definition both apps read. */
99
+ * track center line." The one definition both apps read.
100
+ *
101
+ * ⚠️⚠️ **READ THE SCOPE, NOT JUST THE NUMBER.** This governs a **double-track
102
+ * ENDPLATE**, and reaches **4″ inboard** of it — §2.0's other standard is that
103
+ * track crossing an endplate be "perpendicular, straight, and level for at least
104
+ * 4 inches from the outside face". **Beyond those 4 inches the standard says
105
+ * nothing about how far apart the mains run**, and every real crossover draws
106
+ * them closer than this (the Fast Tracks N fixtures are 1.09″).
107
+ *
108
+ * ⛔ So this is a value to BUILD TO at an endplate, and **never a test to
109
+ * measure mid-module track against**. Used as one it amber-flagged ordinary,
110
+ * correctly built trackwork as departing from the standard (Will, 2026-07-28).
111
+ * It is also the default LANE PITCH for drawing parallel track, which is a
112
+ * separate job — a drawing convention, not a rule anything conforms to.
113
+ */
99
114
  declare const FREEMO_TRACK_SPACING_INCHES = 1.125;
100
115
  /** Free-moN §2.0 **standard**: track crossing an endplate must be "not less than
101
116
  * 4 inches from either fascia" (and perpendicular, straight and level for 4″). */
@@ -155,12 +170,17 @@ declare const PINCH_EASE_INCHES = 3;
155
170
  */
156
171
  declare function laneOffsetAt(lane: number, pos: number, pinches?: LanePinch[] | null, spacingInches?: number): number;
157
172
  /**
158
- * The pinches a document's crossovers impose — one per crossover connector that
159
- * names a part whose {@link TrackPart.trackSpacing} differs from the standard.
173
+ * The pinches a document's crossovers impose — one per crossover connector whose
174
+ * part is built to a different spacing from the mains either side of it.
175
+ *
176
+ * ⚠️ A PINCH IS GEOMETRY, NOT A FAULT. §2.0 fixes the 1.125″ spacing AT THE
177
+ * ENDPLATE; what the mains do in between is the builder's business, and every
178
+ * real crossover draws them closer. This says where the drawing must narrow, and
179
+ * nothing about conformance.
160
180
  *
161
- * A crossover with no part named, or one built to the standard spacing, imposes
162
- * nothing: an owner who hasn't said what they built gets the straight pair they
163
- * had before, which is the only honest default.
181
+ * A crossover with no part named, or one built to the same spacing as the mains,
182
+ * imposes nothing: an owner who hasn't said what they built gets the straight
183
+ * pair they had before, which is the only honest default.
164
184
  */
165
185
  declare function crossoverPinches(tracks: Array<{
166
186
  role?: string;
@@ -1773,14 +1793,19 @@ interface TrackPart {
1773
1793
  crossingAngleDeg?: number;
1774
1794
  /** Centre-to-centre distance of the two parallel tracks a {@link kind}
1775
1795
  * `crossover` joins. A crossover fixture is BUILT for one spacing — it is not
1776
- * adjustable — so this decides whether the part suits a given standard at all.
1796
+ * adjustable — so this is what the mains must pinch to where it sits.
1797
+ *
1798
+ * ⚠️ **NOT A CONFORMANCE TEST.** {@link FREEMO_TRACK_SPACING_INCHES} is fixed
1799
+ * by §2.0 **at the endplate** — "double track endplates must have a track
1800
+ * spacing of 1.125 inches", perpendicular, straight and level for 4″ from the
1801
+ * outside face. What the two mains do in between is the module builder's
1802
+ * business, and EVERY real crossover pinches them closer: the Fast Tracks N
1803
+ * fixtures are 1.09″. Earlier wording here said this "decides whether the part
1804
+ * suits a given standard at all", which is wrong and put an amber
1805
+ * non-conformance note on ordinary, correctly built trackwork.
1777
1806
  *
1778
- * ⚠️ READ {@link FREEMO_TRACK_SPACING_INCHES} ALONGSIDE THIS. Free-moN §2.0
1779
- * fixes double-track spacing at exactly 1.125″; the Fast Tracks N crossovers
1780
- * are built to 1.09″. That 0.035″ is small but it is REAL and it is not a
1781
- * tolerance — the fixture cannot be built to another spacing. Recorded rather
1782
- * than reconciled: it is a fact about the product, and an owner deciding what
1783
- * to buy is better served by the true number than by a convenient one. */
1807
+ * Recorded because it is a fact about the product an owner needs when buying,
1808
+ * and because the drawing has to pinch the mains to it. */
1784
1809
  trackSpacing?: PartDimension;
1785
1810
  /** The SECOND frog angle on a part that has two — the SCISSORS of a double
1786
1811
  * crossover, the X where its two opposite diverging routes meet and cross.
package/dist/index.js CHANGED
@@ -3564,9 +3564,16 @@ function docToGraph(doc, answers = {}, library = BUILT_IN_TRACK_PARTS) {
3564
3564
  if (!partner) continue;
3565
3565
  used.add(t.id);
3566
3566
  used.add(partner.id);
3567
- mainToMainPairs.push({ a: t, b: partner });
3567
+ mainToMainPairs.push({
3568
+ a: t,
3569
+ b: partner,
3570
+ pairKey: [t.onTrack, t.divergeTrack].sort().join("\u2194")
3571
+ });
3568
3572
  }
3569
3573
  }
3574
+ const crossingsBetween = /* @__PURE__ */ new Map();
3575
+ for (const p of mainToMainPairs)
3576
+ crossingsBetween.set(p.pairKey, (crossingsBetween.get(p.pairKey) ?? 0) + 1);
3570
3577
  const divergeFarOverride = /* @__PURE__ */ new Map();
3571
3578
  for (const { a, b } of mainToMainPairs) {
3572
3579
  divergeFarOverride.set(a.id, b.pos);
@@ -3650,9 +3657,10 @@ function docToGraph(doc, answers = {}, library = BUILT_IN_TRACK_PARTS) {
3650
3657
  rotationDeg: Math.atan2(dy, dx) * 180 / Math.PI,
3651
3658
  lengthInches: r3(len)
3652
3659
  });
3653
- warnings.push(
3654
- `${pair.a.name || pair.a.id} and ${pair.b.name || pair.b.id} are laid as two separate turnouts with a ${len.toFixed(1)}\u2033 piece of track between them, which is what the document describes. If they are really one crossover assembly, name the product on a connector track and it will be laid as the single piece it is.`
3655
- );
3660
+ if ((crossingsBetween.get(pair.pairKey) ?? 1) > 1)
3661
+ warnings.push(
3662
+ `${pair.a.name || pair.a.id} and ${pair.b.name || pair.b.id} are two of four turnouts crossing between the same pair of mains \u2014 a double crossover. They are laid as separate turnouts with a ${len.toFixed(1)}\u2033 piece of track between them, which is what the document describes. If it is really a one-piece double crossover, name the product on a connector track and it will be laid as the single assembly it is.`
3663
+ );
3656
3664
  }
3657
3665
  let progressed = true;
3658
3666
  while (progressed) {