@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 CHANGED
@@ -35,12 +35,26 @@ function moduleSections(doc) {
35
35
  };
36
36
  });
37
37
  }
38
- function sectionFootprints(doc) {
39
- return moduleSections(doc).filter((sec) => sec.outline).map((sec) => ({
40
- id: sec.id,
41
- ...sec.name ? { name: sec.name } : {},
42
- outline: sampleBenchworkOutline(sec.outline)
43
- }));
38
+ function sectionFootprints(doc, derive) {
39
+ const spans = derive ? sectionSpans(doc) : [];
40
+ const spanOf = new Map(spans.map((sp) => [sp.id, sp]));
41
+ return moduleSections(doc).map((sec) => {
42
+ const name = sec.name ? { name: sec.name } : {};
43
+ if (sec.outline)
44
+ return { id: sec.id, ...name, outline: sampleBenchworkOutline(sec.outline), derived: false };
45
+ const sp = spanOf.get(sec.id);
46
+ if (!sp || !derive) return null;
47
+ const band = sectionBand(
48
+ derive.centerline,
49
+ sp.fromPos,
50
+ sp.toPos,
51
+ derive.widthA,
52
+ derive.widthB,
53
+ derive.offsetA,
54
+ derive.offsetB
55
+ );
56
+ return band.length >= 3 ? { id: sec.id, ...name, outline: band, derived: true } : null;
57
+ }).filter((x) => x !== null);
44
58
  }
45
59
  function sampleBenchworkOutline(pts, segsPerArc = 20) {
46
60
  const n = pts.length;
@@ -256,6 +270,63 @@ function benchworkBand(center, widthA = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES
256
270
  }));
257
271
  return [...left, ...right.reverse()];
258
272
  }
273
+ function sliceCenterline(center, fromPos, toPos) {
274
+ if (center.length < 2) return [];
275
+ const cum = [0];
276
+ for (let i = 1; i < center.length; i++)
277
+ cum.push(cum[i - 1] + Math.hypot(center[i].x - center[i - 1].x, center[i].y - center[i - 1].y));
278
+ const total = cum[cum.length - 1];
279
+ const a = Math.max(0, Math.min(total, Math.min(fromPos, toPos)));
280
+ const b = Math.max(0, Math.min(total, Math.max(fromPos, toPos)));
281
+ if (b - a <= 0) return [];
282
+ const at = (d) => {
283
+ for (let i = 1; i < center.length; i++) {
284
+ if (d <= cum[i] || i === center.length - 1) {
285
+ const seg = cum[i] - cum[i - 1] || 1;
286
+ const t = Math.max(0, Math.min(1, (d - cum[i - 1]) / seg));
287
+ return {
288
+ x: center[i - 1].x + (center[i].x - center[i - 1].x) * t,
289
+ y: center[i - 1].y + (center[i].y - center[i - 1].y) * t
290
+ };
291
+ }
292
+ }
293
+ return center[center.length - 1];
294
+ };
295
+ const out = [at(a)];
296
+ for (let i = 0; i < center.length; i++) {
297
+ if (cum[i] > a && cum[i] < b) out.push({ x: center[i].x, y: center[i].y });
298
+ }
299
+ out.push(at(b));
300
+ return out;
301
+ }
302
+ function sectionBand(center, fromPos, toPos, widthA = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, widthB = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, offsetA = 0, offsetB = 0) {
303
+ const slice = sliceCenterline(center, fromPos, toPos);
304
+ if (slice.length < 2) return [];
305
+ let total = 0;
306
+ for (let i = 1; i < center.length; i++)
307
+ total += Math.hypot(center[i].x - center[i - 1].x, center[i].y - center[i - 1].y);
308
+ total = total || 1;
309
+ const lo = Math.min(fromPos, toPos);
310
+ let acc = 0;
311
+ const fr = [0];
312
+ for (let i = 1; i < slice.length; i++) {
313
+ acc += Math.hypot(slice[i].x - slice[i - 1].x, slice[i].y - slice[i - 1].y);
314
+ fr.push(acc);
315
+ }
316
+ const f = fr.map((d) => Math.max(0, Math.min(1, (lo + d) / total)));
317
+ const n = centerlineNormals(slice);
318
+ const half = (i) => (widthA * (1 - f[i]) + widthB * f[i]) / 2;
319
+ const off = (i) => offsetA * (1 - f[i]) + offsetB * f[i];
320
+ const left = slice.map((p, i) => ({
321
+ x: p.x + n[i].x * (off(i) + half(i)),
322
+ y: p.y + n[i].y * (off(i) + half(i))
323
+ }));
324
+ const right = slice.map((p, i) => ({
325
+ x: p.x + n[i].x * (off(i) - half(i)),
326
+ y: p.y + n[i].y * (off(i) - half(i))
327
+ }));
328
+ return [...left, ...right.reverse()];
329
+ }
259
330
  function endplateFaceSegments(center, widthA = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, widthB = FREEMO_ENDPLATE_WIDTH_RECOMMENDED_INCHES, offsetA = 0, offsetB = 0) {
260
331
  if (center.length < 2) return [];
261
332
  const n = centerlineNormals(center);
@@ -273,7 +344,13 @@ function moduleFootprint(input) {
273
344
  const authored = benchworkOutline(input);
274
345
  const offA = input.endplateTrackOffsets?.["A"] ?? 0;
275
346
  const offB = input.endplateTrackOffsets?.["B"] ?? 0;
276
- const sectionOutlines = sectionFootprints(input);
347
+ const sectionOutlines = sectionFootprints(input, {
348
+ centerline,
349
+ widthA,
350
+ widthB,
351
+ offsetA: offA,
352
+ offsetB: offB
353
+ });
277
354
  return {
278
355
  centerline,
279
356
  band: benchworkBand(centerline, widthA, widthB, offA, offB),
@@ -1233,10 +1310,12 @@ exports.poseOverridesFromDoc = poseOverridesFromDoc;
1233
1310
  exports.sampleBenchworkOutline = sampleBenchworkOutline;
1234
1311
  exports.samplePath = samplePath;
1235
1312
  exports.scaleFeetToInches = scaleFeetToInches;
1313
+ exports.sectionBand = sectionBand;
1236
1314
  exports.sectionBreaksFromSections = sectionBreaksFromSections;
1237
1315
  exports.sectionFootprints = sectionFootprints;
1238
1316
  exports.sectionSpans = sectionSpans;
1239
1317
  exports.sectionedCenterline = sectionedCenterline;
1318
+ exports.sliceCenterline = sliceCenterline;
1240
1319
  exports.stateToDoc = stateToDoc;
1241
1320
  exports.trackPath = trackPath;
1242
1321
  //# sourceMappingURL=index.cjs.map