@willcgage/module-schematic 0.58.0 → 0.60.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 CHANGED
@@ -1446,15 +1446,61 @@ function turnoutClosure(size, opts = {}) {
1446
1446
  const frogSlope = 1 / N;
1447
1447
  const k = (lead / N - g) / (lead * lead);
1448
1448
  const switchSlope = Math.max(0, frogSlope - 2 * k * lead);
1449
+ const target = opts.arriveAtInches;
1450
+ let a = Infinity;
1451
+ let b = 0;
1452
+ if (target != null && target > g) {
1453
+ b = Math.max(0.01, opts.easeInches ?? lead);
1454
+ a = (target - g) / frogSlope - b / 2;
1455
+ if (a < 0) {
1456
+ a = 0;
1457
+ b = 2 * (target - g) / frogSlope;
1458
+ }
1459
+ }
1460
+ const span = target != null && target > g ? lead + a + b : Infinity;
1449
1461
  return {
1450
1462
  lead,
1451
1463
  switchSlope,
1452
1464
  frogSlope,
1453
- // Past the frog the route is straight at the frog angle — the closure curve
1454
- // has done its work, so don't keep bending (that's the tangent Option 1).
1455
- offsetAt: (s) => s <= lead ? switchSlope * s + k * s * s : g + frogSlope * (s - lead)
1465
+ span,
1466
+ easeInches: b,
1467
+ offsetAt: (s) => {
1468
+ if (s <= lead) return switchSlope * s + k * s * s;
1469
+ const past = s - lead;
1470
+ if (past <= a) return g + frogSlope * past;
1471
+ if (target == null) return g + frogSlope * past;
1472
+ const u = Math.min(past - a, b);
1473
+ const eased = g + frogSlope * a + frogSlope * u - frogSlope * u * u / (2 * b);
1474
+ return past - a >= b ? target : eased;
1475
+ }
1456
1476
  };
1457
1477
  }
1478
+ function frogCasting(cl, opts = {}) {
1479
+ const g = opts.gaugeInches ?? RAIL_GAUGE_INCHES;
1480
+ const w = opts.reachInches ?? g * 1.5;
1481
+ const fw = opts.flangewayInches ?? g * 0.12;
1482
+ const m = cl.frogSlope;
1483
+ const lead = cl.lead;
1484
+ const apex = { x: lead, y: g / 2 };
1485
+ const point = [
1486
+ { x: lead + w, y: g / 2 },
1487
+ apex,
1488
+ { x: lead + w, y: g / 2 + m * w }
1489
+ ];
1490
+ const wings = [
1491
+ [
1492
+ { x: lead - w, y: g / 2 - fw },
1493
+ { x: lead - w * 0.35, y: g / 2 - fw },
1494
+ { x: lead + w * 0.35, y: g / 2 - fw * 0.5 }
1495
+ ],
1496
+ [
1497
+ { x: lead - w, y: g / 2 + m * -w + fw },
1498
+ { x: lead - w * 0.35, y: g / 2 + m * -w * 0.35 + fw },
1499
+ { x: lead + w * 0.35, y: g / 2 + m * w * 0.35 + fw * 0.5 }
1500
+ ]
1501
+ ];
1502
+ return { point, wings, apex };
1503
+ }
1458
1504
  function divergeSideForHand(kind, stubDir, flipped) {
1459
1505
  if (kind !== "left" && kind !== "right") return 0;
1460
1506
  const s = (stubDir >= 0 ? 1 : -1) * (flipped ? -1 : 1);
@@ -1521,7 +1567,7 @@ function moduleFeatures(doc) {
1521
1567
  if (parentLane === 0) {
1522
1568
  const [from, to] = ext;
1523
1569
  const far = Math.abs(to - sw.pos) >= Math.abs(from - sw.pos) ? to : from;
1524
- const s = divergeSideForHand(sw.kind, far - sw.pos);
1570
+ const s = divergeSideForHand(sw.kind, far - sw.pos, sw.flipped);
1525
1571
  sign = s !== 0 ? s : Math.sign(trk.lane) || 1;
1526
1572
  } else {
1527
1573
  sign = Math.sign(parentLane) || 1;
@@ -2001,6 +2047,7 @@ exports.endplateLead = endplateLead;
2001
2047
  exports.endplateTrackOffsetFor = endplateTrackOffsetFor;
2002
2048
  exports.endplateTrackOffsetInches = endplateTrackOffsetInches;
2003
2049
  exports.endplateWidthInches = endplateWidthInches;
2050
+ exports.frogCasting = frogCasting;
2004
2051
  exports.frogNumberFromName = frogNumberFromName;
2005
2052
  exports.fromSectionRelative = fromSectionRelative;
2006
2053
  exports.geometryTurnDegrees = geometryTurnDegrees;