jscad-electronics 0.0.206 → 0.0.207

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/vanilla.js CHANGED
@@ -183,24 +183,24 @@ var FootprintPlatedHole = ({
183
183
  import { buttonScrewModelDefinitionSchema } from "@tscircuit/modelprinter";
184
184
 
185
185
  // lib/model-registry.ts
186
- function defineModelRenderer(model21) {
187
- return model21;
186
+ function defineModelRenderer(model22) {
187
+ return model22;
188
188
  }
189
189
  var ModelRendererRegistry = class {
190
190
  models = /* @__PURE__ */ new Map();
191
- register(model21) {
192
- if (typeof model21.name !== "string" || !/^[a-z]+$/.test(model21.name)) {
191
+ register(model22) {
192
+ if (typeof model22.name !== "string" || !/^[a-z]+$/.test(model22.name)) {
193
193
  throw new Error(
194
194
  "Model renderer names must contain only lowercase letters"
195
195
  );
196
196
  }
197
- if (this.models.has(model21.name)) {
198
- throw new Error(`Model renderer "${model21.name}" is already registered`);
197
+ if (this.models.has(model22.name)) {
198
+ throw new Error(`Model renderer "${model22.name}" is already registered`);
199
199
  }
200
- if (model21.pads !== "none" && model21.pads !== "footprinter") {
200
+ if (model22.pads !== "none" && model22.pads !== "footprinter") {
201
201
  throw new Error('Model renderer pads must be "none" or "footprinter"');
202
202
  }
203
- const { name, schema, render: render2, pads } = model21;
203
+ const { name, schema, render: render2, pads } = model22;
204
204
  this.models.set(name, {
205
205
  name,
206
206
  schema,
@@ -454,6 +454,314 @@ function register2(registry) {
454
454
  registry.register(model2);
455
455
  }
456
456
 
457
+ // lib/models/clampingshaftcollar/register.tsx
458
+ import { clampingShaftCollarModelDefinitionSchema } from "@tscircuit/modelprinter";
459
+
460
+ // lib/models/clampingshaftcollar/mesh.ts
461
+ import jscad3 from "@jscad/modeling";
462
+ import {
463
+ clampingShaftCollarModelPropsSchema,
464
+ getClampingShaftCollarDimensions
465
+ } from "@tscircuit/modelprinter";
466
+
467
+ // lib/mechanical/shaft-mount-geometry.ts
468
+ import jscad2 from "@jscad/modeling";
469
+ var bodySegments = 64;
470
+ var threadSegments = 24;
471
+ var samplesPerTurn = 12;
472
+ function assertShaftMountResolution(holes) {
473
+ let triangles = 0;
474
+ for (const hole of holes) {
475
+ const steps = hole.threadPitch ? Math.ceil(hole.depth / hole.threadPitch * samplesPerTurn) : 1;
476
+ if (!Number.isFinite(steps) || steps > 768)
477
+ throw new Error(
478
+ "Shaft mount exceeds mesh resolution limit (64 thread turns per hole)"
479
+ );
480
+ triangles += (steps + 1) * threadSegments * 2;
481
+ }
482
+ if (triangles > 1e5)
483
+ throw new Error("Shaft mount exceeds total mesh resolution limit");
484
+ }
485
+ function createAnnularSleeve({
486
+ outerRadius,
487
+ boreARadius,
488
+ boreBRadius = boreARadius,
489
+ length,
490
+ chamfer,
491
+ stepZ = length / 2
492
+ }) {
493
+ const halfAngle = Math.PI / bodySegments;
494
+ const cosine = Math.cos(halfAngle);
495
+ if ((Math.max(boreARadius, boreBRadius) + chamfer) / cosine >= (outerRadius - chamfer) * cosine - 1e-6)
496
+ throw new Error(
497
+ "Shaft mount wall/chamfer ligament exceeds mesh resolution limit"
498
+ );
499
+ const raw = [
500
+ [0, outerRadius - chamfer, false],
501
+ [chamfer, outerRadius, false],
502
+ [length - chamfer, outerRadius, false],
503
+ [length, outerRadius - chamfer, false],
504
+ [length, boreBRadius + chamfer, true],
505
+ [length - chamfer, boreBRadius, true],
506
+ [stepZ, boreBRadius, true],
507
+ [stepZ, boreARadius, true],
508
+ [chamfer, boreARadius, true],
509
+ [0, boreARadius + chamfer, true]
510
+ ];
511
+ const profile = raw.filter(
512
+ ([z, r], i) => i === 0 || z !== raw[i - 1][0] || r !== raw[i - 1][1]
513
+ );
514
+ const positions = [];
515
+ const indices = [];
516
+ for (const [z, r, isBore] of profile)
517
+ for (let i = 0; i < bodySegments; i++) {
518
+ const angle = (i + (isBore ? 0.5 : 0)) * Math.PI * 2 / bodySegments;
519
+ const radius = isBore ? r / cosine : r;
520
+ positions.push(radius * Math.cos(angle), radius * Math.sin(angle), z);
521
+ }
522
+ for (let row = 0; row < profile.length; row++)
523
+ for (let i = 0; i < bodySegments; i++) {
524
+ const next = (i + 1) % bodySegments;
525
+ const a = row * bodySegments + i, b = row * bodySegments + next;
526
+ const c = (row + 1) % profile.length * bodySegments + next, d = (row + 1) % profile.length * bodySegments + i;
527
+ indices.push(a, b, c, a, c, d);
528
+ }
529
+ return indexedMeshToGeom3({ positions, indices });
530
+ }
531
+ function createMountingHoleCutter(hole) {
532
+ assertShaftMountResolution([hole]);
533
+ const pitch = hole.threadPitch;
534
+ const steps = pitch ? Math.max(2, Math.ceil(hole.depth / pitch * samplesPerTurn)) : 1;
535
+ const segments = pitch ? threadSegments : 48;
536
+ const extension = 1e-4;
537
+ const radius = hole.diameter / 2;
538
+ const threadDepth = pitch ? Math.min(pitch * 0.541266, radius * 0.8) : 0;
539
+ const hand = hole.threadHand === "left" ? -1 : 1;
540
+ const positions = [];
541
+ const indices = [];
542
+ const [dx, dy, dz] = hole.direction;
543
+ if (Math.abs(dz) > 1e-10 || Math.abs(Math.hypot(dx, dy) - 1) > 1e-10)
544
+ throw new Error("Expected a horizontal unit hole axis");
545
+ const push = (x, y, z) => {
546
+ positions.push(
547
+ hole.start[0] + y * dy + z * dx,
548
+ hole.start[1] - y * dx + z * dy,
549
+ hole.start[2] + x
550
+ );
551
+ };
552
+ for (let row = 0; row <= steps; row++) {
553
+ const z = -extension + (hole.depth + 2 * extension) * row / steps;
554
+ for (let i = 0; i < segments; i++) {
555
+ const angle = i * Math.PI * 2 / segments;
556
+ const phase = pitch ? ((z / pitch - hand * angle / (Math.PI * 2)) % 1 + 1) % 1 : 0;
557
+ const distance2 = Math.min(phase, 1 - phase);
558
+ const r = radius - Math.min(
559
+ threadDepth,
560
+ Math.max(0, (distance2 - 1 / 8) * (pitch ?? 0) * Math.sqrt(3))
561
+ );
562
+ push(r * Math.cos(angle), r * Math.sin(angle), z);
563
+ }
564
+ }
565
+ for (let row = 0; row < steps; row++)
566
+ for (let i = 0; i < segments; i++) {
567
+ const next = (i + 1) % segments;
568
+ const a = row * segments + i, b = row * segments + next, c = (row + 1) * segments + next, d = (row + 1) * segments + i;
569
+ indices.push(a, b, c, a, c, d);
570
+ }
571
+ for (const end of [0, steps]) {
572
+ const center = positions.length / 3;
573
+ push(0, 0, end === 0 ? -extension : hole.depth + extension);
574
+ for (let i = 0; i < segments; i++) {
575
+ const a = end * segments + i, b = end * segments + (i + 1) % segments;
576
+ indices.push(center, end === 0 ? b : a, end === 0 ? a : b);
577
+ }
578
+ }
579
+ return indexedMeshToGeom3({ positions, indices });
580
+ }
581
+ function subtractShaftMountParts(body, ...cutters) {
582
+ const factor = 100;
583
+ const scaled = [body, ...cutters].map(
584
+ (geometry) => jscad2.transforms.scale([factor, factor, factor], geometry)
585
+ );
586
+ const result = jscad2.booleans.subtract(scaled[0], ...scaled.slice(1));
587
+ return jscad2.transforms.scale([1 / factor, 1 / factor, 1 / factor], result);
588
+ }
589
+ function finishShaftMountMesh(geometry) {
590
+ const positions = [];
591
+ const vertices = /* @__PURE__ */ new Map();
592
+ const tolerance = 1e-6;
593
+ const weld = (point) => {
594
+ const cell = point.map((v) => Math.floor(v / tolerance));
595
+ for (let x = -1; x <= 1; x++)
596
+ for (let y = -1; y <= 1; y++)
597
+ for (let z = -1; z <= 1; z++) {
598
+ const nearby = vertices.get(
599
+ [cell[0] + x, cell[1] + y, cell[2] + z].join(",")
600
+ ) ?? [];
601
+ for (const index2 of nearby)
602
+ if (Math.hypot(
603
+ ...point.map((v, axis) => v - positions[index2 * 3 + axis])
604
+ ) < tolerance)
605
+ return index2;
606
+ }
607
+ const index = positions.length / 3;
608
+ positions.push(...point);
609
+ const key = cell.join(",");
610
+ vertices.set(key, [...vertices.get(key) ?? [], index]);
611
+ return index;
612
+ };
613
+ const polygons = jscad2.geometries.geom3.toPolygons(geometry).map(
614
+ (polygon) => polygon.vertices.map(weld).filter((id, i, ids) => id !== ids[(i + ids.length - 1) % ids.length])
615
+ ).map((ids) => [...new Set(ids)]).filter((ids) => ids.length >= 3).filter((ids) => {
616
+ let longest = 0;
617
+ let origin = [];
618
+ let direction = [];
619
+ for (let i = 0; i < ids.length; i++)
620
+ for (let j = i + 1; j < ids.length; j++) {
621
+ const a = positions.slice(ids[i] * 3, ids[i] * 3 + 3);
622
+ const delta = positions.slice(ids[j] * 3, ids[j] * 3 + 3).map((v, axis) => v - a[axis]);
623
+ const squared = delta.reduce((sum, v) => sum + v * v, 0);
624
+ if (squared > longest) {
625
+ longest = squared;
626
+ origin = a;
627
+ direction = delta;
628
+ }
629
+ }
630
+ return ids.some((id) => {
631
+ const delta = positions.slice(id * 3, id * 3 + 3).map((v, axis) => v - origin[axis]);
632
+ const t = delta.reduce((sum, v, axis) => sum + v * direction[axis], 0) / longest;
633
+ return Math.hypot(...delta.map((v, axis) => v - t * direction[axis])) >= tolerance;
634
+ });
635
+ });
636
+ const edgeKey = (a, b) => `${Math.min(a, b)},${Math.max(a, b)}`;
637
+ const edges = /* @__PURE__ */ new Map();
638
+ for (const polygon of polygons)
639
+ for (let i = 0; i < polygon.length; i++) {
640
+ const a = polygon[i], b = polygon[(i + 1) % polygon.length], key = edgeKey(a, b);
641
+ const edge = edges.get(key) ?? { a, b, count: 0 };
642
+ edge.count++;
643
+ edges.set(key, edge);
644
+ }
645
+ const unmatched = [...edges.values()].filter((edge) => edge.count === 1);
646
+ const candidates = [...new Set(unmatched.flatMap((edge) => [edge.a, edge.b]))];
647
+ const splits = /* @__PURE__ */ new Map();
648
+ for (const { a, b } of unmatched) {
649
+ const origin = positions.slice(a * 3, a * 3 + 3);
650
+ const direction = positions.slice(b * 3, b * 3 + 3).map((v, axis) => v - origin[axis]);
651
+ const squared = direction.reduce((sum, v) => sum + v * v, 0);
652
+ const points = [];
653
+ for (const id of candidates) {
654
+ if (id === a || id === b) continue;
655
+ const delta = positions.slice(id * 3, id * 3 + 3).map((v, axis) => v - origin[axis]);
656
+ const t = delta.reduce((sum, v, axis) => sum + v * direction[axis], 0) / squared;
657
+ if (t <= 0 || t >= 1) continue;
658
+ const distance2 = Math.hypot(
659
+ ...delta.map((v, axis) => v - t * direction[axis])
660
+ );
661
+ if (distance2 < tolerance) points.push({ id, t });
662
+ }
663
+ points.sort((p, q) => p.t - q.t);
664
+ splits.set(
665
+ `${a},${b}`,
666
+ points.map((p) => p.id)
667
+ );
668
+ splits.set(`${b},${a}`, points.map((p) => p.id).reverse());
669
+ }
670
+ const indices = [];
671
+ for (const polygon of polygons) {
672
+ const perimeter = polygon.flatMap((a, i) => [
673
+ a,
674
+ ...(splits.get(`${a},${polygon[(i + 1) % polygon.length]}`) ?? []).filter((id) => !polygon.includes(id))
675
+ ]);
676
+ const unique = perimeter.filter(
677
+ (id, i) => id !== perimeter[(i + perimeter.length - 1) % perimeter.length]
678
+ );
679
+ if (unique.length === 3) {
680
+ indices.push(...unique);
681
+ continue;
682
+ }
683
+ const center = positions.length / 3;
684
+ positions.push(
685
+ ...[0, 1, 2].map(
686
+ (axis) => unique.reduce((sum, id) => sum + positions[id * 3 + axis], 0) / unique.length
687
+ )
688
+ );
689
+ for (let i = 0; i < unique.length; i++)
690
+ indices.push(center, unique[i], unique[(i + 1) % unique.length]);
691
+ }
692
+ const compact = [];
693
+ const remap = /* @__PURE__ */ new Map();
694
+ return {
695
+ positions: compact,
696
+ indices: indices.map((index) => {
697
+ let next = remap.get(index);
698
+ if (next === void 0) {
699
+ next = compact.length / 3;
700
+ remap.set(index, next);
701
+ compact.push(...positions.slice(index * 3, index * 3 + 3));
702
+ }
703
+ return next;
704
+ })
705
+ };
706
+ }
707
+
708
+ // lib/models/clampingshaftcollar/mesh.ts
709
+ function createClampingShaftCollarMesh(input) {
710
+ const props = clampingShaftCollarModelPropsSchema.parse(input);
711
+ const dimensions = getClampingShaftCollarDimensions(props);
712
+ assertShaftMountResolution([dimensions.threadedHole]);
713
+ const body = createAnnularSleeve({
714
+ outerRadius: props.outerDiameter / 2,
715
+ boreARadius: props.boreDiameter / 2,
716
+ length: props.width,
717
+ chamfer: props.chamfer
718
+ });
719
+ const s = dimensions.split;
720
+ const epsilon = 1e-4;
721
+ const slit = jscad3.primitives.cuboid({
722
+ size: [
723
+ s.xMax - s.xMin + epsilon,
724
+ s.yMax - s.yMin,
725
+ s.zMax - s.zMin + 2 * epsilon
726
+ ],
727
+ center: [
728
+ (s.xMax + s.xMin + epsilon) / 2,
729
+ (s.yMax + s.yMin) / 2,
730
+ (s.zMax + s.zMin) / 2
731
+ ]
732
+ });
733
+ return finishShaftMountMesh(
734
+ subtractShaftMountParts(
735
+ body,
736
+ slit,
737
+ createMountingHoleCutter(dimensions.clearanceHole),
738
+ createMountingHoleCutter(dimensions.threadedHole)
739
+ )
740
+ );
741
+ }
742
+
743
+ // lib/models/clampingshaftcollar/ClampingShaftCollar.tsx
744
+ function createClampingShaftCollarGeom(input) {
745
+ return indexedMeshToGeom3(createClampingShaftCollarMesh(input));
746
+ }
747
+ function ClampingShaftCollar({
748
+ color = "#737e8f",
749
+ ...props
750
+ }) {
751
+ return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsx(Custom, { geometry: createClampingShaftCollarGeom(props) }) });
752
+ }
753
+
754
+ // lib/models/clampingshaftcollar/register.tsx
755
+ var model3 = defineModelRenderer({
756
+ name: "clampingshaftcollar",
757
+ schema: clampingShaftCollarModelDefinitionSchema,
758
+ render: ({ fn, ...props }) => /* @__PURE__ */ jsx(ClampingShaftCollar, { ...props }),
759
+ pads: "none"
760
+ });
761
+ function register3(registry) {
762
+ registry.register(model3);
763
+ }
764
+
457
765
  // lib/models/compressionspring/register.tsx
458
766
  import { compressionSpringModelDefinitionSchema } from "@tscircuit/modelprinter";
459
767
 
@@ -657,14 +965,14 @@ function CompressionSpring({
657
965
  }
658
966
 
659
967
  // lib/models/compressionspring/register.tsx
660
- var model3 = defineModelRenderer({
968
+ var model4 = defineModelRenderer({
661
969
  name: "compressionspring",
662
970
  schema: compressionSpringModelDefinitionSchema,
663
971
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(CompressionSpring, { ...props }),
664
972
  pads: "none"
665
973
  });
666
- function register3(registry) {
667
- registry.register(model3);
974
+ function register4(registry) {
975
+ registry.register(model4);
668
976
  }
669
977
 
670
978
  // lib/models/flangedbushing/register.tsx
@@ -720,14 +1028,14 @@ function FlangedBushing({
720
1028
  }
721
1029
 
722
1030
  // lib/models/flangedbushing/register.tsx
723
- var model4 = defineModelRenderer({
1031
+ var model5 = defineModelRenderer({
724
1032
  name: "flangedbushing",
725
1033
  schema: flangedBushingModelDefinitionSchema,
726
1034
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(FlangedBushing, { ...props }),
727
1035
  pads: "none"
728
1036
  });
729
- function register4(registry) {
730
- registry.register(model4);
1037
+ function register5(registry) {
1038
+ registry.register(model5);
731
1039
  }
732
1040
 
733
1041
  // lib/models/flatheadscrew/register.tsx
@@ -860,14 +1168,14 @@ function FlatHeadScrew({
860
1168
  }
861
1169
 
862
1170
  // lib/models/flatheadscrew/register.tsx
863
- var model5 = defineModelRenderer({
1171
+ var model6 = defineModelRenderer({
864
1172
  name: "flatheadscrew",
865
1173
  schema: flatHeadScrewModelDefinitionSchema,
866
1174
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(FlatHeadScrew, { ...props }),
867
1175
  pads: "none"
868
1176
  });
869
- function register5(registry) {
870
- registry.register(model5);
1177
+ function register6(registry) {
1178
+ registry.register(model6);
871
1179
  }
872
1180
 
873
1181
  // lib/models/flexscreen/register.tsx
@@ -1545,14 +1853,14 @@ var FlexScreen = (props) => {
1545
1853
  };
1546
1854
 
1547
1855
  // lib/models/flexscreen/register.tsx
1548
- var model6 = defineModelRenderer({
1856
+ var model7 = defineModelRenderer({
1549
1857
  name: "flexscreen",
1550
1858
  schema: flexScreenModelDefinitionSchema,
1551
1859
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(FlexScreen, { ...props }),
1552
1860
  pads: "footprinter"
1553
1861
  });
1554
- function register6(registry) {
1555
- registry.register(model6);
1862
+ function register7(registry) {
1863
+ registry.register(model7);
1556
1864
  }
1557
1865
 
1558
1866
  // lib/models/helicalgear/register.tsx
@@ -1758,14 +2066,14 @@ function HelicalGear({ color = "#737e8f", ...props }) {
1758
2066
  }
1759
2067
 
1760
2068
  // lib/models/helicalgear/register.tsx
1761
- var model7 = defineModelRenderer({
2069
+ var model8 = defineModelRenderer({
1762
2070
  name: "helicalgear",
1763
2071
  schema: helicalGearModelDefinitionSchema,
1764
2072
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HelicalGear, { ...props }),
1765
2073
  pads: "none"
1766
2074
  });
1767
- function register7(registry) {
1768
- registry.register(model7);
2075
+ function register8(registry) {
2076
+ registry.register(model8);
1769
2077
  }
1770
2078
 
1771
2079
  // lib/models/hexbolt/register.tsx
@@ -1906,14 +2214,14 @@ function HexBolt({ color = "#737e8f", ...props }) {
1906
2214
  }
1907
2215
 
1908
2216
  // lib/models/hexbolt/register.tsx
1909
- var model8 = defineModelRenderer({
2217
+ var model9 = defineModelRenderer({
1910
2218
  name: "hexbolt",
1911
2219
  schema: hexBoltModelDefinitionSchema,
1912
2220
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HexBolt, { ...props }),
1913
2221
  pads: "none"
1914
2222
  });
1915
- function register8(registry) {
1916
- registry.register(model8);
2223
+ function register9(registry) {
2224
+ registry.register(model9);
1917
2225
  }
1918
2226
 
1919
2227
  // lib/models/hexnut/register.tsx
@@ -2036,14 +2344,14 @@ function HexNut({ color = "#737e8f", ...props }) {
2036
2344
  }
2037
2345
 
2038
2346
  // lib/models/hexnut/register.tsx
2039
- var model9 = defineModelRenderer({
2347
+ var model10 = defineModelRenderer({
2040
2348
  name: "hexnut",
2041
2349
  schema: hexNutModelDefinitionSchema,
2042
2350
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HexNut, { ...props }),
2043
2351
  pads: "none"
2044
2352
  });
2045
- function register9(registry) {
2046
- registry.register(model9);
2353
+ function register10(registry) {
2354
+ registry.register(model10);
2047
2355
  }
2048
2356
 
2049
2357
  // lib/models/hexsocketbolt/register.tsx
@@ -2155,24 +2463,24 @@ function HexSocketBolt({
2155
2463
  }
2156
2464
 
2157
2465
  // lib/models/hexsocketbolt/register.tsx
2158
- var model10 = defineModelRenderer({
2466
+ var model11 = defineModelRenderer({
2159
2467
  name: "hexsocketbolt",
2160
2468
  schema: hexSocketBoltModelDefinitionSchema,
2161
2469
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HexSocketBolt, { ...props }),
2162
2470
  pads: "none"
2163
2471
  });
2164
- function register10(registry) {
2165
- registry.register(model10);
2472
+ function register11(registry) {
2473
+ registry.register(model11);
2166
2474
  }
2167
2475
 
2168
2476
  // lib/models/nema/register.tsx
2169
2477
  import { nemaMotorModelDefinitionSchema } from "@tscircuit/modelprinter";
2170
2478
 
2171
2479
  // lib/NemaMotor.tsx
2172
- import jscad3 from "@jscad/modeling";
2480
+ import jscad5 from "@jscad/modeling";
2173
2481
 
2174
2482
  // lib/utils/nemaMotorWireGeometry.ts
2175
- import jscad2 from "@jscad/modeling";
2483
+ import jscad4 from "@jscad/modeling";
2176
2484
  import {
2177
2485
  getJstMotorConnector,
2178
2486
  getNemaMotorReferencePoints
@@ -2190,9 +2498,9 @@ function createNemaMotorWireGeometry(input) {
2190
2498
  if (p.wireConnection === "none") return [];
2191
2499
  const { position } = getNemaMotorReferencePoints(p).wireside;
2192
2500
  const angle = p.wireSideAngle * Math.PI / 180;
2193
- const place = (geometry) => jscad2.transforms.translate(
2501
+ const place = (geometry) => jscad4.transforms.translate(
2194
2502
  [position.x, position.y, position.z],
2195
- jscad2.transforms.rotateZ(angle, geometry)
2503
+ jscad4.transforms.rotateZ(angle, geometry)
2196
2504
  );
2197
2505
  if (p.wireConnection === "stubs") {
2198
2506
  const colors = [
@@ -2208,15 +2516,15 @@ function createNemaMotorWireGeometry(input) {
2208
2516
  return Array.from({ length: p.wireCount }, (_, i) => ({
2209
2517
  color: colors[i],
2210
2518
  geometry: place(
2211
- jscad2.transforms.translate(
2519
+ jscad4.transforms.translate(
2212
2520
  [
2213
2521
  (p.wireLength - 0.15) / 2,
2214
2522
  (i - (p.wireCount - 1) / 2) * p.wireDiameter * 1.5,
2215
2523
  0
2216
2524
  ],
2217
- jscad2.transforms.rotateY(
2525
+ jscad4.transforms.rotateY(
2218
2526
  Math.PI / 2,
2219
- jscad2.primitives.cylinder({
2527
+ jscad4.primitives.cylinder({
2220
2528
  height: p.wireLength + 0.15,
2221
2529
  radius: p.wireDiameter / 2,
2222
2530
  segments: 24
@@ -2231,12 +2539,12 @@ function createNemaMotorWireGeometry(input) {
2231
2539
  const wall = pitch === 2 ? 0.6 : 0.3;
2232
2540
  const contactLength = pitch === 2 ? 3.4 : 2.4;
2233
2541
  const contactSize = pitch === 2 ? 0.5 : 0.3;
2234
- const shell = jscad2.booleans.subtract(
2235
- jscad2.primitives.cuboid({
2542
+ const shell = jscad4.booleans.subtract(
2543
+ jscad4.primitives.cuboid({
2236
2544
  size: [matingDepth + 0.1, bodyWidth, bodyHeight],
2237
2545
  center: [(matingDepth - 0.1) / 2, 0, 0]
2238
2546
  }),
2239
- jscad2.primitives.cuboid({
2547
+ jscad4.primitives.cuboid({
2240
2548
  size: [matingDepth - 0.5, bodyWidth - 2 * wall, bodyHeight - 2 * wall],
2241
2549
  center: [matingDepth / 2 + 0.55, 0, 0]
2242
2550
  })
@@ -2246,7 +2554,7 @@ function createNemaMotorWireGeometry(input) {
2246
2554
  ...Array.from({ length: pinCount }, (_, i) => ({
2247
2555
  color: "#b8bec6",
2248
2556
  geometry: place(
2249
- jscad2.primitives.cuboid({
2557
+ jscad4.primitives.cuboid({
2250
2558
  size: [contactLength, contactSize, contactSize],
2251
2559
  center: [contactLength / 2, (i - (pinCount - 1) / 2) * pitch, 0]
2252
2560
  })
@@ -2354,7 +2662,7 @@ function createNemaMotorSections(input) {
2354
2662
  }
2355
2663
 
2356
2664
  // lib/NemaMotor.tsx
2357
- var generalize = jscad3.modifiers.generalize;
2665
+ var generalize = jscad5.modifiers.generalize;
2358
2666
  function NemaMotor({
2359
2667
  bodyColor = "#242830",
2360
2668
  capColor = "#aeb5bd",
@@ -2363,7 +2671,7 @@ function NemaMotor({
2363
2671
  ...props
2364
2672
  }) {
2365
2673
  const p = resolveNemaMotorProps(props);
2366
- const screw = p.backFace === "screws" ? jscad3.transforms.rotateX(
2674
+ const screw = p.backFace === "screws" ? jscad5.transforms.rotateX(
2367
2675
  Math.PI,
2368
2676
  createHexSocketBoltGeom({
2369
2677
  metricSize: p.backFaceScrewSize,
@@ -2374,14 +2682,14 @@ function NemaMotor({
2374
2682
  const halfPitch = p.backFaceHoleSpacing / 2;
2375
2683
  return /* @__PURE__ */ jsxs(Fragment2, { children: [
2376
2684
  createNemaMotorSections(p).map((section, index) => {
2377
- const outline = jscad3.geometries.geom2.fromPoints(section.outline);
2378
- const profile = section.holes.length ? jscad3.booleans.subtract(
2685
+ const outline = jscad5.geometries.geom2.fromPoints(section.outline);
2686
+ const profile = section.holes.length ? jscad5.booleans.subtract(
2379
2687
  outline,
2380
- ...section.holes.map((h2) => jscad3.geometries.geom2.fromPoints(h2))
2688
+ ...section.holes.map((h2) => jscad5.geometries.geom2.fromPoints(h2))
2381
2689
  ) : outline;
2382
- const geometry = jscad3.transforms.translate(
2690
+ const geometry = jscad5.transforms.translate(
2383
2691
  [0, 0, section.zMin],
2384
- jscad3.extrusions.extrudeLinear(
2692
+ jscad5.extrusions.extrudeLinear(
2385
2693
  { height: section.zMax - section.zMin },
2386
2694
  profile
2387
2695
  )
@@ -2414,7 +2722,7 @@ function NemaMotor({
2414
2722
  children: /* @__PURE__ */ jsx(
2415
2723
  Custom,
2416
2724
  {
2417
- geometry: jscad3.transforms.translate(
2725
+ geometry: jscad5.transforms.translate(
2418
2726
  [x, y, -p.bodyLength],
2419
2727
  generalize({ simplify: true }, screw)
2420
2728
  )
@@ -2431,14 +2739,14 @@ var NEMA17 = (props) => /* @__PURE__ */ jsx(NemaMotor, { ...props, nemaSize: 17
2431
2739
  var NEMA23 = (props) => /* @__PURE__ */ jsx(NemaMotor, { ...props, nemaSize: 23 });
2432
2740
 
2433
2741
  // lib/models/nema/register.tsx
2434
- var model11 = defineModelRenderer({
2742
+ var model12 = defineModelRenderer({
2435
2743
  name: "nema",
2436
2744
  schema: nemaMotorModelDefinitionSchema,
2437
2745
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(NemaMotor, { ...props }),
2438
2746
  pads: "none"
2439
2747
  });
2440
- function register11(registry) {
2441
- registry.register(model11);
2748
+ function register12(registry) {
2749
+ registry.register(model12);
2442
2750
  }
2443
2751
 
2444
2752
  // lib/models/panscrew/register.tsx
@@ -2650,14 +2958,14 @@ function PanScrew({ color = "#737e8f", ...props }) {
2650
2958
  }
2651
2959
 
2652
2960
  // lib/models/panscrew/register.tsx
2653
- var model12 = defineModelRenderer({
2961
+ var model13 = defineModelRenderer({
2654
2962
  name: "panscrew",
2655
2963
  schema: panScrewModelDefinitionSchema,
2656
2964
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(PanScrew, { ...props }),
2657
2965
  pads: "none"
2658
2966
  });
2659
- function register12(registry) {
2660
- registry.register(model12);
2967
+ function register13(registry) {
2968
+ registry.register(model13);
2661
2969
  }
2662
2970
 
2663
2971
  // lib/models/plainbushing/register.tsx
@@ -2687,301 +2995,58 @@ function createPlainBushingMesh(input) {
2687
2995
  [ro, 0],
2688
2996
  [ro, d.length],
2689
2997
  [ri, d.length],
2690
- [ri, 0]
2691
- ];
2692
- const segments = 96;
2693
- const positions = [];
2694
- const indices = [];
2695
- for (const [radius, z] of profile)
2696
- for (let i = 0; i < segments; i++) {
2697
- const angle = i * Math.PI * 2 / segments;
2698
- positions.push(radius * Math.cos(angle), radius * Math.sin(angle), z);
2699
- }
2700
- for (let ring = 0; ring < profile.length; ring++) {
2701
- const a = ring * segments;
2702
- const b = (ring + 1) % profile.length * segments;
2703
- for (let i = 0; i < segments; i++) {
2704
- const next = (i + 1) % segments;
2705
- indices.push(a + i, a + next, b + next, a + i, b + next, b + i);
2706
- }
2707
- }
2708
- return { positions, indices };
2709
- }
2710
-
2711
- // lib/models/plainbushing/PlainBushing.tsx
2712
- function createPlainBushingGeom(input) {
2713
- return indexedMeshToGeom3(createPlainBushingMesh(input));
2714
- }
2715
- function PlainBushing({
2716
- color = "#a18450",
2717
- ...props
2718
- }) {
2719
- return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsx(Custom, { geometry: createPlainBushingGeom(props) }) });
2720
- }
2721
-
2722
- // lib/models/plainbushing/register.tsx
2723
- var model13 = defineModelRenderer({
2724
- name: "plainbushing",
2725
- schema: plainBushingModelDefinitionSchema,
2726
- render: ({ fn, ...props }) => /* @__PURE__ */ jsx(PlainBushing, { ...props }),
2727
- pads: "none"
2728
- });
2729
- function register13(registry) {
2730
- registry.register(model13);
2731
- }
2732
-
2733
- // lib/models/shaftcollar/register.tsx
2734
- import { shaftCollarModelDefinitionSchema } from "@tscircuit/modelprinter";
2735
-
2736
- // lib/models/shaftcollar/mesh.ts
2737
- import "@jscad/modeling";
2738
- import {
2739
- shaftCollarModelPropsSchema,
2740
- getShaftCollarDimensions
2741
- } from "@tscircuit/modelprinter";
2742
-
2743
- // lib/mechanical/shaft-mount-geometry.ts
2744
- import jscad4 from "@jscad/modeling";
2745
- var bodySegments = 64;
2746
- var threadSegments = 24;
2747
- var samplesPerTurn = 12;
2748
- function assertShaftMountResolution(holes) {
2749
- let triangles = 0;
2750
- for (const hole of holes) {
2751
- const steps = hole.threadPitch ? Math.ceil(hole.depth / hole.threadPitch * samplesPerTurn) : 1;
2752
- if (!Number.isFinite(steps) || steps > 768)
2753
- throw new Error(
2754
- "Shaft mount exceeds mesh resolution limit (64 thread turns per hole)"
2755
- );
2756
- triangles += (steps + 1) * threadSegments * 2;
2757
- }
2758
- if (triangles > 1e5)
2759
- throw new Error("Shaft mount exceeds total mesh resolution limit");
2760
- }
2761
- function createAnnularSleeve({
2762
- outerRadius,
2763
- boreARadius,
2764
- boreBRadius = boreARadius,
2765
- length,
2766
- chamfer,
2767
- stepZ = length / 2
2768
- }) {
2769
- const halfAngle = Math.PI / bodySegments;
2770
- const cosine = Math.cos(halfAngle);
2771
- if ((Math.max(boreARadius, boreBRadius) + chamfer) / cosine >= (outerRadius - chamfer) * cosine - 1e-6)
2772
- throw new Error(
2773
- "Shaft mount wall/chamfer ligament exceeds mesh resolution limit"
2774
- );
2775
- const raw = [
2776
- [0, outerRadius - chamfer, false],
2777
- [chamfer, outerRadius, false],
2778
- [length - chamfer, outerRadius, false],
2779
- [length, outerRadius - chamfer, false],
2780
- [length, boreBRadius + chamfer, true],
2781
- [length - chamfer, boreBRadius, true],
2782
- [stepZ, boreBRadius, true],
2783
- [stepZ, boreARadius, true],
2784
- [chamfer, boreARadius, true],
2785
- [0, boreARadius + chamfer, true]
2998
+ [ri, 0]
2786
2999
  ];
2787
- const profile = raw.filter(
2788
- ([z, r], i) => i === 0 || z !== raw[i - 1][0] || r !== raw[i - 1][1]
2789
- );
2790
- const positions = [];
2791
- const indices = [];
2792
- for (const [z, r, isBore] of profile)
2793
- for (let i = 0; i < bodySegments; i++) {
2794
- const angle = (i + (isBore ? 0.5 : 0)) * Math.PI * 2 / bodySegments;
2795
- const radius = isBore ? r / cosine : r;
2796
- positions.push(radius * Math.cos(angle), radius * Math.sin(angle), z);
2797
- }
2798
- for (let row = 0; row < profile.length; row++)
2799
- for (let i = 0; i < bodySegments; i++) {
2800
- const next = (i + 1) % bodySegments;
2801
- const a = row * bodySegments + i, b = row * bodySegments + next;
2802
- const c = (row + 1) % profile.length * bodySegments + next, d = (row + 1) % profile.length * bodySegments + i;
2803
- indices.push(a, b, c, a, c, d);
2804
- }
2805
- return indexedMeshToGeom3({ positions, indices });
2806
- }
2807
- function createMountingHoleCutter(hole) {
2808
- assertShaftMountResolution([hole]);
2809
- const pitch = hole.threadPitch;
2810
- const steps = pitch ? Math.max(2, Math.ceil(hole.depth / pitch * samplesPerTurn)) : 1;
2811
- const segments = pitch ? threadSegments : 48;
2812
- const extension = 1e-4;
2813
- const radius = hole.diameter / 2;
2814
- const threadDepth = pitch ? Math.min(pitch * 0.541266, radius * 0.8) : 0;
2815
- const hand = hole.threadHand === "left" ? -1 : 1;
3000
+ const segments = 96;
2816
3001
  const positions = [];
2817
3002
  const indices = [];
2818
- const [dx, dy, dz] = hole.direction;
2819
- if (Math.abs(dz) > 1e-10 || Math.abs(Math.hypot(dx, dy) - 1) > 1e-10)
2820
- throw new Error("Expected a horizontal unit hole axis");
2821
- const push = (x, y, z) => {
2822
- positions.push(
2823
- hole.start[0] + y * dy + z * dx,
2824
- hole.start[1] - y * dx + z * dy,
2825
- hole.start[2] + x
2826
- );
2827
- };
2828
- for (let row = 0; row <= steps; row++) {
2829
- const z = -extension + (hole.depth + 2 * extension) * row / steps;
3003
+ for (const [radius, z] of profile)
2830
3004
  for (let i = 0; i < segments; i++) {
2831
3005
  const angle = i * Math.PI * 2 / segments;
2832
- const phase = pitch ? ((z / pitch - hand * angle / (Math.PI * 2)) % 1 + 1) % 1 : 0;
2833
- const distance2 = Math.min(phase, 1 - phase);
2834
- const r = radius - Math.min(
2835
- threadDepth,
2836
- Math.max(0, (distance2 - 1 / 8) * (pitch ?? 0) * Math.sqrt(3))
2837
- );
2838
- push(r * Math.cos(angle), r * Math.sin(angle), z);
3006
+ positions.push(radius * Math.cos(angle), radius * Math.sin(angle), z);
2839
3007
  }
2840
- }
2841
- for (let row = 0; row < steps; row++)
3008
+ for (let ring = 0; ring < profile.length; ring++) {
3009
+ const a = ring * segments;
3010
+ const b = (ring + 1) % profile.length * segments;
2842
3011
  for (let i = 0; i < segments; i++) {
2843
3012
  const next = (i + 1) % segments;
2844
- const a = row * segments + i, b = row * segments + next, c = (row + 1) * segments + next, d = (row + 1) * segments + i;
2845
- indices.push(a, b, c, a, c, d);
2846
- }
2847
- for (const end of [0, steps]) {
2848
- const center = positions.length / 3;
2849
- push(0, 0, end === 0 ? -extension : hole.depth + extension);
2850
- for (let i = 0; i < segments; i++) {
2851
- const a = end * segments + i, b = end * segments + (i + 1) % segments;
2852
- indices.push(center, end === 0 ? b : a, end === 0 ? a : b);
3013
+ indices.push(a + i, a + next, b + next, a + i, b + next, b + i);
2853
3014
  }
2854
3015
  }
2855
- return indexedMeshToGeom3({ positions, indices });
3016
+ return { positions, indices };
2856
3017
  }
2857
- function subtractShaftMountParts(body, ...cutters) {
2858
- const factor = 100;
2859
- const scaled = [body, ...cutters].map(
2860
- (geometry) => jscad4.transforms.scale([factor, factor, factor], geometry)
2861
- );
2862
- const result = jscad4.booleans.subtract(scaled[0], ...scaled.slice(1));
2863
- return jscad4.transforms.scale([1 / factor, 1 / factor, 1 / factor], result);
3018
+
3019
+ // lib/models/plainbushing/PlainBushing.tsx
3020
+ function createPlainBushingGeom(input) {
3021
+ return indexedMeshToGeom3(createPlainBushingMesh(input));
2864
3022
  }
2865
- function finishShaftMountMesh(geometry) {
2866
- const positions = [];
2867
- const vertices = /* @__PURE__ */ new Map();
2868
- const tolerance = 1e-6;
2869
- const weld = (point) => {
2870
- const cell = point.map((v) => Math.floor(v / tolerance));
2871
- for (let x = -1; x <= 1; x++)
2872
- for (let y = -1; y <= 1; y++)
2873
- for (let z = -1; z <= 1; z++) {
2874
- const nearby = vertices.get(
2875
- [cell[0] + x, cell[1] + y, cell[2] + z].join(",")
2876
- ) ?? [];
2877
- for (const index2 of nearby)
2878
- if (Math.hypot(
2879
- ...point.map((v, axis) => v - positions[index2 * 3 + axis])
2880
- ) < tolerance)
2881
- return index2;
2882
- }
2883
- const index = positions.length / 3;
2884
- positions.push(...point);
2885
- const key = cell.join(",");
2886
- vertices.set(key, [...vertices.get(key) ?? [], index]);
2887
- return index;
2888
- };
2889
- const polygons = jscad4.geometries.geom3.toPolygons(geometry).map(
2890
- (polygon) => polygon.vertices.map(weld).filter((id, i, ids) => id !== ids[(i + ids.length - 1) % ids.length])
2891
- ).map((ids) => [...new Set(ids)]).filter((ids) => ids.length >= 3).filter((ids) => {
2892
- let longest = 0;
2893
- let origin = [];
2894
- let direction = [];
2895
- for (let i = 0; i < ids.length; i++)
2896
- for (let j = i + 1; j < ids.length; j++) {
2897
- const a = positions.slice(ids[i] * 3, ids[i] * 3 + 3);
2898
- const delta = positions.slice(ids[j] * 3, ids[j] * 3 + 3).map((v, axis) => v - a[axis]);
2899
- const squared = delta.reduce((sum, v) => sum + v * v, 0);
2900
- if (squared > longest) {
2901
- longest = squared;
2902
- origin = a;
2903
- direction = delta;
2904
- }
2905
- }
2906
- return ids.some((id) => {
2907
- const delta = positions.slice(id * 3, id * 3 + 3).map((v, axis) => v - origin[axis]);
2908
- const t = delta.reduce((sum, v, axis) => sum + v * direction[axis], 0) / longest;
2909
- return Math.hypot(...delta.map((v, axis) => v - t * direction[axis])) >= tolerance;
2910
- });
2911
- });
2912
- const edgeKey = (a, b) => `${Math.min(a, b)},${Math.max(a, b)}`;
2913
- const edges = /* @__PURE__ */ new Map();
2914
- for (const polygon of polygons)
2915
- for (let i = 0; i < polygon.length; i++) {
2916
- const a = polygon[i], b = polygon[(i + 1) % polygon.length], key = edgeKey(a, b);
2917
- const edge = edges.get(key) ?? { a, b, count: 0 };
2918
- edge.count++;
2919
- edges.set(key, edge);
2920
- }
2921
- const unmatched = [...edges.values()].filter((edge) => edge.count === 1);
2922
- const candidates = [...new Set(unmatched.flatMap((edge) => [edge.a, edge.b]))];
2923
- const splits = /* @__PURE__ */ new Map();
2924
- for (const { a, b } of unmatched) {
2925
- const origin = positions.slice(a * 3, a * 3 + 3);
2926
- const direction = positions.slice(b * 3, b * 3 + 3).map((v, axis) => v - origin[axis]);
2927
- const squared = direction.reduce((sum, v) => sum + v * v, 0);
2928
- const points = [];
2929
- for (const id of candidates) {
2930
- if (id === a || id === b) continue;
2931
- const delta = positions.slice(id * 3, id * 3 + 3).map((v, axis) => v - origin[axis]);
2932
- const t = delta.reduce((sum, v, axis) => sum + v * direction[axis], 0) / squared;
2933
- if (t <= 0 || t >= 1) continue;
2934
- const distance2 = Math.hypot(
2935
- ...delta.map((v, axis) => v - t * direction[axis])
2936
- );
2937
- if (distance2 < tolerance) points.push({ id, t });
2938
- }
2939
- points.sort((p, q) => p.t - q.t);
2940
- splits.set(
2941
- `${a},${b}`,
2942
- points.map((p) => p.id)
2943
- );
2944
- splits.set(`${b},${a}`, points.map((p) => p.id).reverse());
2945
- }
2946
- const indices = [];
2947
- for (const polygon of polygons) {
2948
- const perimeter = polygon.flatMap((a, i) => [
2949
- a,
2950
- ...(splits.get(`${a},${polygon[(i + 1) % polygon.length]}`) ?? []).filter((id) => !polygon.includes(id))
2951
- ]);
2952
- const unique = perimeter.filter(
2953
- (id, i) => id !== perimeter[(i + perimeter.length - 1) % perimeter.length]
2954
- );
2955
- if (unique.length === 3) {
2956
- indices.push(...unique);
2957
- continue;
2958
- }
2959
- const center = positions.length / 3;
2960
- positions.push(
2961
- ...[0, 1, 2].map(
2962
- (axis) => unique.reduce((sum, id) => sum + positions[id * 3 + axis], 0) / unique.length
2963
- )
2964
- );
2965
- for (let i = 0; i < unique.length; i++)
2966
- indices.push(center, unique[i], unique[(i + 1) % unique.length]);
2967
- }
2968
- const compact = [];
2969
- const remap = /* @__PURE__ */ new Map();
2970
- return {
2971
- positions: compact,
2972
- indices: indices.map((index) => {
2973
- let next = remap.get(index);
2974
- if (next === void 0) {
2975
- next = compact.length / 3;
2976
- remap.set(index, next);
2977
- compact.push(...positions.slice(index * 3, index * 3 + 3));
2978
- }
2979
- return next;
2980
- })
2981
- };
3023
+ function PlainBushing({
3024
+ color = "#a18450",
3025
+ ...props
3026
+ }) {
3027
+ return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsx(Custom, { geometry: createPlainBushingGeom(props) }) });
3028
+ }
3029
+
3030
+ // lib/models/plainbushing/register.tsx
3031
+ var model14 = defineModelRenderer({
3032
+ name: "plainbushing",
3033
+ schema: plainBushingModelDefinitionSchema,
3034
+ render: ({ fn, ...props }) => /* @__PURE__ */ jsx(PlainBushing, { ...props }),
3035
+ pads: "none"
3036
+ });
3037
+ function register14(registry) {
3038
+ registry.register(model14);
2982
3039
  }
2983
3040
 
3041
+ // lib/models/shaftcollar/register.tsx
3042
+ import { shaftCollarModelDefinitionSchema } from "@tscircuit/modelprinter";
3043
+
2984
3044
  // lib/models/shaftcollar/mesh.ts
3045
+ import "@jscad/modeling";
3046
+ import {
3047
+ shaftCollarModelPropsSchema,
3048
+ getShaftCollarDimensions
3049
+ } from "@tscircuit/modelprinter";
2985
3050
  function createShaftCollarMesh(input) {
2986
3051
  const props = shaftCollarModelPropsSchema.parse(input);
2987
3052
  const dimensions = getShaftCollarDimensions(props);
@@ -3009,14 +3074,14 @@ function ShaftCollar({ color = "#737e8f", ...props }) {
3009
3074
  }
3010
3075
 
3011
3076
  // lib/models/shaftcollar/register.tsx
3012
- var model14 = defineModelRenderer({
3077
+ var model15 = defineModelRenderer({
3013
3078
  name: "shaftcollar",
3014
3079
  schema: shaftCollarModelDefinitionSchema,
3015
3080
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(ShaftCollar, { ...props }),
3016
3081
  pads: "none"
3017
3082
  });
3018
- function register14(registry) {
3019
- registry.register(model14);
3083
+ function register15(registry) {
3084
+ registry.register(model15);
3020
3085
  }
3021
3086
 
3022
3087
  // lib/models/sheetmetal/register.tsx
@@ -3176,14 +3241,14 @@ function SheetMetal({ color = "#737e8f", ...props }) {
3176
3241
  }
3177
3242
 
3178
3243
  // lib/models/sheetmetal/register.tsx
3179
- var model15 = defineModelRenderer({
3244
+ var model16 = defineModelRenderer({
3180
3245
  name: "sheetmetal",
3181
3246
  schema: sheetMetalModelDefinitionSchema,
3182
3247
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SheetMetal, { ...props }),
3183
3248
  pads: "none"
3184
3249
  });
3185
- function register15(registry) {
3186
- registry.register(model15);
3250
+ function register16(registry) {
3251
+ registry.register(model16);
3187
3252
  }
3188
3253
 
3189
3254
  // lib/models/spurgear/register.tsx
@@ -3198,14 +3263,14 @@ function SpurGear({ color = "#737e8f", ...props }) {
3198
3263
  }
3199
3264
 
3200
3265
  // lib/models/spurgear/register.tsx
3201
- var model16 = defineModelRenderer({
3266
+ var model17 = defineModelRenderer({
3202
3267
  name: "spurgear",
3203
3268
  schema: spurGearModelDefinitionSchema,
3204
3269
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SpurGear, { ...props }),
3205
3270
  pads: "none"
3206
3271
  });
3207
- function register16(registry) {
3208
- registry.register(model16);
3272
+ function register17(registry) {
3273
+ registry.register(model17);
3209
3274
  }
3210
3275
 
3211
3276
  // lib/models/tslotextrusion/register.tsx
@@ -3355,14 +3420,14 @@ function TSlotExtrusion({
3355
3420
  }
3356
3421
 
3357
3422
  // lib/models/tslotextrusion/register.tsx
3358
- var model17 = defineModelRenderer({
3423
+ var model18 = defineModelRenderer({
3359
3424
  name: "tslotextrusion",
3360
3425
  schema: tSlotExtrusionModelDefinitionSchema,
3361
3426
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(TSlotExtrusion, { ...props }),
3362
3427
  pads: "none"
3363
3428
  });
3364
- function register17(registry) {
3365
- registry.register(model17);
3429
+ function register18(registry) {
3430
+ registry.register(model18);
3366
3431
  }
3367
3432
 
3368
3433
  // lib/models/tslotgusset/register.tsx
@@ -3415,14 +3480,14 @@ function TSlotGusset({ color = "#8995a3", ...props }) {
3415
3480
  }
3416
3481
 
3417
3482
  // lib/models/tslotgusset/register.tsx
3418
- var model18 = defineModelRenderer({
3483
+ var model19 = defineModelRenderer({
3419
3484
  name: "tslotgusset",
3420
3485
  schema: tSlotGussetModelDefinitionSchema,
3421
3486
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(TSlotGusset, { ...props }),
3422
3487
  pads: "none"
3423
3488
  });
3424
- function register18(registry) {
3425
- registry.register(model18);
3489
+ function register19(registry) {
3490
+ registry.register(model19);
3426
3491
  }
3427
3492
 
3428
3493
  // lib/models/tslotinsidecorner/register.tsx
@@ -3502,14 +3567,14 @@ function TSlotInsideCorner({
3502
3567
  }
3503
3568
 
3504
3569
  // lib/models/tslotinsidecorner/register.tsx
3505
- var model19 = defineModelRenderer({
3570
+ var model20 = defineModelRenderer({
3506
3571
  name: "tslotinsidecorner",
3507
3572
  schema: tSlotInsideCornerModelDefinitionSchema,
3508
3573
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(TSlotInsideCorner, { ...props }),
3509
3574
  pads: "none"
3510
3575
  });
3511
- function register19(registry) {
3512
- registry.register(model19);
3576
+ function register20(registry) {
3577
+ registry.register(model20);
3513
3578
  }
3514
3579
 
3515
3580
  // lib/models/wormgear/register.tsx
@@ -3701,14 +3766,14 @@ function WormGear({ color = "#737e8f", ...props }) {
3701
3766
  }
3702
3767
 
3703
3768
  // lib/models/wormgear/register.tsx
3704
- var model20 = defineModelRenderer({
3769
+ var model21 = defineModelRenderer({
3705
3770
  name: "wormgear",
3706
3771
  schema: wormGearModelDefinitionSchema,
3707
3772
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(WormGear, { ...props }),
3708
3773
  pads: "none"
3709
3774
  });
3710
- function register20(registry) {
3711
- registry.register(model20);
3775
+ function register21(registry) {
3776
+ registry.register(model21);
3712
3777
  }
3713
3778
 
3714
3779
  // lib/generated/model-renderers.ts
@@ -3733,6 +3798,7 @@ function registerAllModelRenderers(registry) {
3733
3798
  register18(registry);
3734
3799
  register19(registry);
3735
3800
  register20(registry);
3801
+ register21(registry);
3736
3802
  }
3737
3803
 
3738
3804
  // lib/default-model-registry.ts
@@ -11289,10 +11355,10 @@ var SOT143 = ({ footprint = "sot143" }) => {
11289
11355
  var Footprinter3d = ({ footprint }) => {
11290
11356
  const modelFn = mp3.string(footprint.split("_", 1)[0]).params().fn;
11291
11357
  if (mp3.getModelNames().includes(modelFn)) {
11292
- const model21 = mp3.string(footprint).json();
11293
- const renderer = modelRendererRegistry.get(model21.fn);
11358
+ const model22 = mp3.string(footprint).json();
11359
+ const renderer = modelRendererRegistry.get(model22.fn);
11294
11360
  if (renderer) {
11295
- return renderer.render(model21);
11361
+ return renderer.render(model22);
11296
11362
  }
11297
11363
  }
11298
11364
  let normalizedFootprint = footprint;
@@ -12125,8 +12191,8 @@ function renderNode(node, colorCtx, renderCtx) {
12125
12191
  }
12126
12192
  return (children ?? []).flatMap((c) => renderNode(c, colorCtx, renderCtx));
12127
12193
  }
12128
- function render(root, jscad6) {
12129
- const geometries = renderNode(root, void 0, { jscad: jscad6 });
12194
+ function render(root, jscad7) {
12195
+ const geometries = renderNode(root, void 0, { jscad: jscad7 });
12130
12196
  return {
12131
12197
  geometries: geometries.map(
12132
12198
  (entry) => entry.material ? { ...entry, geom: { ...entry.geom, material: entry.material } } : entry
@@ -12218,24 +12284,24 @@ function convertCSGToThreeGeom(csg) {
12218
12284
  }
12219
12285
 
12220
12286
  // lib/vanilla/index.ts
12221
- function getJscadModelForFootprint(footprint, jscad6) {
12287
+ function getJscadModelForFootprint(footprint, jscad7) {
12222
12288
  const vnode = h(Footprinter3d, { footprint });
12223
- return render(vnode, jscad6);
12289
+ return render(vnode, jscad7);
12224
12290
  }
12225
- function getJscadModelForFootprintWithPads(footprint, jscad6) {
12291
+ function getJscadModelForFootprintWithPads(footprint, jscad7) {
12226
12292
  const vnode = h(
12227
12293
  Fragment,
12228
12294
  {},
12229
12295
  h(Footprinter3d, { footprint }),
12230
12296
  h(ExtrudedPads, { footprint })
12231
12297
  );
12232
- return render(vnode, jscad6);
12298
+ return render(vnode, jscad7);
12233
12299
  }
12234
- function createJSCADRenderer(jscad6) {
12300
+ function createJSCADRenderer(jscad7) {
12235
12301
  function createJSCADRoot(container) {
12236
12302
  return {
12237
12303
  render(element) {
12238
- const { geometries } = render(element, jscad6);
12304
+ const { geometries } = render(element, jscad7);
12239
12305
  container.splice(0, container.length, ...geometries);
12240
12306
  }
12241
12307
  };
@@ -12245,6 +12311,7 @@ function createJSCADRenderer(jscad6) {
12245
12311
  export {
12246
12312
  ButtonScrew,
12247
12313
  CableGrommet,
12314
+ ClampingShaftCollar,
12248
12315
  CompressionSpring,
12249
12316
  FlangedBushing,
12250
12317
  FlatHeadScrew,
@@ -12271,6 +12338,8 @@ export {
12271
12338
  createButtonScrewMesh,
12272
12339
  createCableGrommetGeom,
12273
12340
  createCableGrommetMesh,
12341
+ createClampingShaftCollarGeom,
12342
+ createClampingShaftCollarMesh,
12274
12343
  createCompressionSpringGeom,
12275
12344
  createCompressionSpringMesh,
12276
12345
  createFlangedBushingGeom,