@willcgage/module-schematic 0.47.0 → 0.48.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
@@ -1322,6 +1322,83 @@ function moduleFeatures(doc) {
1322
1322
  laneMax: Math.max(...allLanes)
1323
1323
  };
1324
1324
  }
1325
+ function returnLoop(shape, opts) {
1326
+ const L = Math.max(1, opts.leadInches);
1327
+ const R = Math.max(1, opts.radius);
1328
+ const hw = Math.min(opts.boardHalfWidth ?? 6, R - 1);
1329
+ const T = { x: L, y: 0 };
1330
+ const r2 = (v) => Math.round(v * 100) / 100;
1331
+ const rd = (pts) => pts.map((p) => ({ x: r2(p.x), y: r2(p.y) }));
1332
+ const arc = (cx, cy, r, a0, a12, steps) => {
1333
+ const out = [];
1334
+ for (let i = 0; i <= steps; i++) out.push({ x: cx + r * Math.cos(a0 + (a12 - a0) * i / steps), y: cy + r * Math.sin(a0 + (a12 - a0) * i / steps) });
1335
+ return out;
1336
+ };
1337
+ if (shape === "square") {
1338
+ const s = 2 * R;
1339
+ const loop2 = [
1340
+ { x: L, y: 0 },
1341
+ { x: L, y: R },
1342
+ { x: L + s, y: R },
1343
+ { x: L + s, y: -R },
1344
+ { x: L, y: -R },
1345
+ { x: L, y: 0 }
1346
+ ];
1347
+ return {
1348
+ throat: T,
1349
+ loop: rd(loop2),
1350
+ wyeLegs: [rd([T, { x: L, y: R }]), rd([T, { x: L, y: -R }])],
1351
+ wyeHalfAngleDeg: 90,
1352
+ outlineOuter: rd([
1353
+ { x: 0, y: hw },
1354
+ { x: L + s + hw, y: hw },
1355
+ { x: L + s + hw, y: -R - hw },
1356
+ { x: 0, y: -R - hw }
1357
+ ]),
1358
+ outlineInner: rd([
1359
+ { x: L + hw, y: R - hw },
1360
+ { x: L + s - hw, y: R - hw },
1361
+ { x: L + s - hw, y: -R + hw },
1362
+ { x: L + hw, y: -R + hw }
1363
+ ])
1364
+ };
1365
+ }
1366
+ const D = shape === "circle" ? R * 1.15 : R * 1.6;
1367
+ const offY = shape === "offset-teardrop" ? R * 0.7 : 0;
1368
+ const C = { x: L + D, y: offY };
1369
+ const dist = Math.hypot(C.x - T.x, C.y - T.y);
1370
+ const ac = Math.acos(Math.min(1, R / dist));
1371
+ const base = Math.atan2(T.y - C.y, T.x - C.x);
1372
+ const a1 = base + ac;
1373
+ const a2 = base - ac;
1374
+ const P1 = { x: C.x + R * Math.cos(a1), y: C.y + R * Math.sin(a1) };
1375
+ const P2 = { x: C.x + R * Math.cos(a2), y: C.y + R * Math.sin(a2) };
1376
+ const loop = [T, P1, ...arc(C.x, C.y, R, a1, a2 + 2 * Math.PI, 64).slice(1), T];
1377
+ const legDir = (P) => Math.atan2(P.y - T.y, P.x - T.x);
1378
+ const half = Math.abs((legDir(P1) - legDir(P2) + Math.PI) % (2 * Math.PI) - Math.PI) / 2;
1379
+ const ringOuter = (rr) => {
1380
+ const xTop = C.x - Math.sqrt(Math.max(0, rr * rr - (hw - C.y) ** 2));
1381
+ const xBot = C.x - Math.sqrt(Math.max(0, rr * rr - (-hw - C.y) ** 2));
1382
+ const tTop = Math.atan2(hw - C.y, xTop - C.x);
1383
+ const tBot = Math.atan2(-hw - C.y, xBot - C.x);
1384
+ return [
1385
+ { x: 0, y: hw },
1386
+ { x: xTop, y: hw },
1387
+ ...arc(C.x, C.y, rr, tTop, tBot - 2 * Math.PI, 48).slice(1, -1),
1388
+ { x: xBot, y: -hw },
1389
+ { x: 0, y: -hw }
1390
+ ];
1391
+ };
1392
+ const Ri = R - hw;
1393
+ return {
1394
+ throat: T,
1395
+ loop: rd(loop),
1396
+ wyeLegs: [rd([T, P1]), rd([T, P2])],
1397
+ wyeHalfAngleDeg: r2(half * 180 / Math.PI),
1398
+ outlineOuter: rd(ringOuter(R + hw)),
1399
+ outlineInner: Ri > 2 ? rd(arc(C.x, C.y, Ri, 0, 2 * Math.PI, 40)) : []
1400
+ };
1401
+ }
1325
1402
  function geometryTurnDegrees(geometryType, geometryDegrees) {
1326
1403
  switch (geometryType) {
1327
1404
  case "corner_45":
@@ -1535,6 +1612,7 @@ exports.nextId = nextId;
1535
1612
  exports.poseNeedsManual = poseNeedsManual;
1536
1613
  exports.poseOverridesFromDoc = poseOverridesFromDoc;
1537
1614
  exports.remapPos = remapPos;
1615
+ exports.returnLoop = returnLoop;
1538
1616
  exports.sampleBenchworkOutline = sampleBenchworkOutline;
1539
1617
  exports.samplePath = samplePath;
1540
1618
  exports.scaleFeetToInches = scaleFeetToInches;