jscad-electronics 0.0.201 → 0.0.203
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.ts +34 -2
- package/dist/index.js +1328 -959
- package/dist/index.js.map +1 -1
- package/dist/vanilla.d.ts +34 -2
- package/dist/vanilla.js +415 -56
- package/dist/vanilla.js.map +1 -1
- package/package.json +1 -1
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(
|
|
187
|
-
return
|
|
186
|
+
function defineModelRenderer(model18) {
|
|
187
|
+
return model18;
|
|
188
188
|
}
|
|
189
189
|
var ModelRendererRegistry = class {
|
|
190
190
|
models = /* @__PURE__ */ new Map();
|
|
191
|
-
register(
|
|
192
|
-
if (typeof
|
|
191
|
+
register(model18) {
|
|
192
|
+
if (typeof model18.name !== "string" || !/^[a-z]+$/.test(model18.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(
|
|
198
|
-
throw new Error(`Model renderer "${
|
|
197
|
+
if (this.models.has(model18.name)) {
|
|
198
|
+
throw new Error(`Model renderer "${model18.name}" is already registered`);
|
|
199
199
|
}
|
|
200
|
-
if (
|
|
200
|
+
if (model18.pads !== "none" && model18.pads !== "footprinter") {
|
|
201
201
|
throw new Error('Model renderer pads must be "none" or "footprinter"');
|
|
202
202
|
}
|
|
203
|
-
const { name, schema, render: render2, pads } =
|
|
203
|
+
const { name, schema, render: render2, pads } = model18;
|
|
204
204
|
this.models.set(name, {
|
|
205
205
|
name,
|
|
206
206
|
schema,
|
|
@@ -454,6 +454,219 @@ function register2(registry) {
|
|
|
454
454
|
registry.register(model2);
|
|
455
455
|
}
|
|
456
456
|
|
|
457
|
+
// lib/models/compressionspring/register.tsx
|
|
458
|
+
import { compressionSpringModelDefinitionSchema } from "@tscircuit/modelprinter";
|
|
459
|
+
|
|
460
|
+
// lib/models/compressionspring/mesh.ts
|
|
461
|
+
import {
|
|
462
|
+
compressionSpringModelPropsSchema,
|
|
463
|
+
getCompressionSpringCenterlinePoint,
|
|
464
|
+
getCompressionSpringDimensions
|
|
465
|
+
} from "@tscircuit/modelprinter";
|
|
466
|
+
|
|
467
|
+
// lib/mechanical/clip-mesh-to-z-range.ts
|
|
468
|
+
import earcut from "earcut";
|
|
469
|
+
function clipMeshToZRange(mesh, lower, upper) {
|
|
470
|
+
const originals = [];
|
|
471
|
+
const tolerance = 32 * Number.EPSILON * (upper - lower);
|
|
472
|
+
for (let index = 0; index < mesh.positions.length / 3; index++)
|
|
473
|
+
originals.push({
|
|
474
|
+
key: `v${index}`,
|
|
475
|
+
coordinates: [
|
|
476
|
+
mesh.positions[index * 3],
|
|
477
|
+
mesh.positions[index * 3 + 1],
|
|
478
|
+
Math.abs(mesh.positions[index * 3 + 2] - lower) <= tolerance ? lower : Math.abs(mesh.positions[index * 3 + 2] - upper) <= tolerance ? upper : mesh.positions[index * 3 + 2]
|
|
479
|
+
]
|
|
480
|
+
});
|
|
481
|
+
const intersections = /* @__PURE__ */ new Map();
|
|
482
|
+
const crossing = (a, b, plane) => {
|
|
483
|
+
if (a.coordinates[2] === plane) return a;
|
|
484
|
+
if (b.coordinates[2] === plane) return b;
|
|
485
|
+
const [first, second] = a.key < b.key ? [a, b] : [b, a];
|
|
486
|
+
const key = `${plane}:${first.key}:${second.key}`;
|
|
487
|
+
let point = intersections.get(key);
|
|
488
|
+
if (!point) {
|
|
489
|
+
const fraction = (plane - first.coordinates[2]) / (second.coordinates[2] - first.coordinates[2]);
|
|
490
|
+
point = {
|
|
491
|
+
key,
|
|
492
|
+
coordinates: [
|
|
493
|
+
first.coordinates[0] + fraction * (second.coordinates[0] - first.coordinates[0]),
|
|
494
|
+
first.coordinates[1] + fraction * (second.coordinates[1] - first.coordinates[1]),
|
|
495
|
+
plane
|
|
496
|
+
]
|
|
497
|
+
};
|
|
498
|
+
intersections.set(key, point);
|
|
499
|
+
}
|
|
500
|
+
return point;
|
|
501
|
+
};
|
|
502
|
+
const clip = (polygon, plane, keepAbove) => {
|
|
503
|
+
const result = [];
|
|
504
|
+
const inside = (point) => keepAbove ? point.coordinates[2] >= plane : point.coordinates[2] <= plane;
|
|
505
|
+
for (let index = 0; index < polygon.length; index++) {
|
|
506
|
+
const a = polygon[index];
|
|
507
|
+
const b = polygon[(index + 1) % polygon.length];
|
|
508
|
+
if (inside(a)) result.push(a);
|
|
509
|
+
if (inside(a) !== inside(b)) result.push(crossing(a, b, plane));
|
|
510
|
+
}
|
|
511
|
+
return result.filter(
|
|
512
|
+
(point, index) => point.key !== result[(index + result.length - 1) % result.length]?.key
|
|
513
|
+
);
|
|
514
|
+
};
|
|
515
|
+
const positions = [];
|
|
516
|
+
const indices = [];
|
|
517
|
+
const pointIndices = /* @__PURE__ */ new Map();
|
|
518
|
+
const vertex = (point) => {
|
|
519
|
+
let index = pointIndices.get(point.key);
|
|
520
|
+
if (index === void 0) {
|
|
521
|
+
index = positions.length / 3;
|
|
522
|
+
positions.push(...point.coordinates);
|
|
523
|
+
pointIndices.set(point.key, index);
|
|
524
|
+
}
|
|
525
|
+
return index;
|
|
526
|
+
};
|
|
527
|
+
for (let index = 0; index < mesh.indices.length; index += 3) {
|
|
528
|
+
const triangle = mesh.indices.slice(index, index + 3).map((i) => originals[i]);
|
|
529
|
+
const polygon = clip(clip(triangle, lower, true), upper, false);
|
|
530
|
+
for (let corner = 1; corner + 1 < polygon.length; corner++) {
|
|
531
|
+
const points = [polygon[0], polygon[corner], polygon[corner + 1]];
|
|
532
|
+
if (new Set(points.map((point) => point.key)).size === 3)
|
|
533
|
+
indices.push(...points.map(vertex));
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
const edges = /* @__PURE__ */ new Map();
|
|
537
|
+
for (let index = 0; index < indices.length; index += 3)
|
|
538
|
+
for (let side = 0; side < 3; side++) {
|
|
539
|
+
const from = indices[index + side];
|
|
540
|
+
const to = indices[index + (side + 1) % 3];
|
|
541
|
+
const key = `${Math.min(from, to)},${Math.max(from, to)}`;
|
|
542
|
+
const prior = edges.get(key);
|
|
543
|
+
if (prior) prior.count++;
|
|
544
|
+
else edges.set(key, { from, to, count: 1 });
|
|
545
|
+
}
|
|
546
|
+
const boundary = [...edges.values()].filter((edge) => edge.count === 1);
|
|
547
|
+
const outgoing = new Map(boundary.map(({ from, to }) => [from, to]));
|
|
548
|
+
if (outgoing.size !== boundary.length)
|
|
549
|
+
throw new Error("Ground clipping produced an ambiguous boundary");
|
|
550
|
+
while (outgoing.size > 0) {
|
|
551
|
+
const start = outgoing.keys().next().value;
|
|
552
|
+
const loop = [];
|
|
553
|
+
let current = start;
|
|
554
|
+
do {
|
|
555
|
+
loop.push(current);
|
|
556
|
+
const next = outgoing.get(current);
|
|
557
|
+
if (next === void 0)
|
|
558
|
+
throw new Error("Ground clipping produced an open boundary");
|
|
559
|
+
outgoing.delete(current);
|
|
560
|
+
current = next;
|
|
561
|
+
} while (current !== start);
|
|
562
|
+
const plane = positions[3 * start + 2];
|
|
563
|
+
if (plane !== lower && plane !== upper || loop.some((i) => positions[3 * i + 2] !== plane))
|
|
564
|
+
throw new Error("Ground clipping boundary must lie on an end plane");
|
|
565
|
+
const coordinates = loop.flatMap((i) => [
|
|
566
|
+
positions[3 * i],
|
|
567
|
+
positions[3 * i + 1]
|
|
568
|
+
]);
|
|
569
|
+
const cap = earcut(coordinates);
|
|
570
|
+
for (let index = 0; index < cap.length; index += 3) {
|
|
571
|
+
const a = loop[cap[index]];
|
|
572
|
+
let b = loop[cap[index + 1]];
|
|
573
|
+
let c = loop[cap[index + 2]];
|
|
574
|
+
const cross = (positions[b * 3] - positions[a * 3]) * (positions[c * 3 + 1] - positions[a * 3 + 1]) - (positions[b * 3 + 1] - positions[a * 3 + 1]) * (positions[c * 3] - positions[a * 3]);
|
|
575
|
+
if (plane === lower && cross > 0 || plane === upper && cross < 0)
|
|
576
|
+
[b, c] = [c, b];
|
|
577
|
+
indices.push(a, b, c);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
return { positions, indices };
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// lib/models/compressionspring/mesh.ts
|
|
584
|
+
function createCompressionSpringMesh(input, options = {}) {
|
|
585
|
+
const props = compressionSpringModelPropsSchema.parse(input);
|
|
586
|
+
const dimensions = getCompressionSpringDimensions(props);
|
|
587
|
+
const segmentsPerTurn = options.segmentsPerTurn ?? 64;
|
|
588
|
+
const wireSegments = options.wireSegments ?? 24;
|
|
589
|
+
for (const [name, value, minimum, maximum] of [
|
|
590
|
+
["segmentsPerTurn", segmentsPerTurn, 16, 256],
|
|
591
|
+
["wireSegments", wireSegments, 8, 64]
|
|
592
|
+
])
|
|
593
|
+
if (!Number.isInteger(value) || value < minimum || value > maximum || value % 4 !== 0)
|
|
594
|
+
throw new Error(
|
|
595
|
+
`${name} must be a multiple of four in [${minimum},${maximum}]`
|
|
596
|
+
);
|
|
597
|
+
const steps = props.totalTurns * segmentsPerTurn;
|
|
598
|
+
if (!Number.isSafeInteger(steps) || (steps + 1) * wireSegments > 25e4)
|
|
599
|
+
throw new Error("Spring exceeds mesh resolution limit (250000 vertices)");
|
|
600
|
+
const scale = Math.max(props.outerDiameter, props.freeLength);
|
|
601
|
+
if (dimensions.activePitch - props.wireDiameter <= scale * 1e-10 || props.wireDiameter <= scale * 1e-10 || dimensions.insideDiameter <= scale * 1e-10)
|
|
602
|
+
throw new Error("Spring clearance exceeds mesh resolution limit");
|
|
603
|
+
const positions = [];
|
|
604
|
+
const indices = [];
|
|
605
|
+
const wireRadius = props.wireDiameter / 2;
|
|
606
|
+
for (let step = 0; step <= steps; step++) {
|
|
607
|
+
const center = getCompressionSpringCenterlinePoint(
|
|
608
|
+
props,
|
|
609
|
+
step / segmentsPerTurn
|
|
610
|
+
);
|
|
611
|
+
const meanRadius = Math.hypot(center.x, center.y);
|
|
612
|
+
for (let sample = 0; sample < wireSegments; sample++) {
|
|
613
|
+
const angle = sample * 2 * Math.PI / wireSegments;
|
|
614
|
+
const cosine = sample === wireSegments / 4 || sample === 3 * wireSegments / 4 ? 0 : Math.cos(angle);
|
|
615
|
+
const sine = sample === 0 || sample === wireSegments / 2 ? 0 : Math.sin(angle);
|
|
616
|
+
const radialOffset = wireRadius * cosine;
|
|
617
|
+
positions.push(
|
|
618
|
+
center.x + radialOffset * center.x / meanRadius,
|
|
619
|
+
center.y + radialOffset * center.y / meanRadius,
|
|
620
|
+
center.z + wireRadius * sine
|
|
621
|
+
);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
const triangle = (a, b, c) => {
|
|
625
|
+
if (props.hand === "left") indices.push(a, c, b);
|
|
626
|
+
else indices.push(a, b, c);
|
|
627
|
+
};
|
|
628
|
+
for (let step = 0; step < steps; step++)
|
|
629
|
+
for (let sample = 0; sample < wireSegments; sample++) {
|
|
630
|
+
const next = (sample + 1) % wireSegments;
|
|
631
|
+
const a = step * wireSegments;
|
|
632
|
+
const b = (step + 1) * wireSegments;
|
|
633
|
+
triangle(a + sample, b + sample, b + next);
|
|
634
|
+
triangle(a + sample, b + next, a + next);
|
|
635
|
+
}
|
|
636
|
+
for (let corner = 1; corner + 1 < wireSegments; corner++) {
|
|
637
|
+
triangle(0, corner, corner + 1);
|
|
638
|
+
const end = steps * wireSegments;
|
|
639
|
+
triangle(end, end + corner + 1, end + corner);
|
|
640
|
+
}
|
|
641
|
+
return clipMeshToZRange(
|
|
642
|
+
{ positions, indices },
|
|
643
|
+
dimensions.lowerBearingZ,
|
|
644
|
+
dimensions.upperBearingZ
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// lib/models/compressionspring/CompressionSpring.tsx
|
|
649
|
+
function createCompressionSpringGeom(input) {
|
|
650
|
+
return indexedMeshToGeom3(createCompressionSpringMesh(input));
|
|
651
|
+
}
|
|
652
|
+
function CompressionSpring({
|
|
653
|
+
color = "#737e8f",
|
|
654
|
+
...props
|
|
655
|
+
}) {
|
|
656
|
+
return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsx(Custom, { geometry: createCompressionSpringGeom(props) }) });
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// lib/models/compressionspring/register.tsx
|
|
660
|
+
var model3 = defineModelRenderer({
|
|
661
|
+
name: "compressionspring",
|
|
662
|
+
schema: compressionSpringModelDefinitionSchema,
|
|
663
|
+
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(CompressionSpring, { ...props }),
|
|
664
|
+
pads: "none"
|
|
665
|
+
});
|
|
666
|
+
function register3(registry) {
|
|
667
|
+
registry.register(model3);
|
|
668
|
+
}
|
|
669
|
+
|
|
457
670
|
// lib/models/flangedbushing/register.tsx
|
|
458
671
|
import { flangedBushingModelDefinitionSchema } from "@tscircuit/modelprinter";
|
|
459
672
|
|
|
@@ -507,14 +720,14 @@ function FlangedBushing({
|
|
|
507
720
|
}
|
|
508
721
|
|
|
509
722
|
// lib/models/flangedbushing/register.tsx
|
|
510
|
-
var
|
|
723
|
+
var model4 = defineModelRenderer({
|
|
511
724
|
name: "flangedbushing",
|
|
512
725
|
schema: flangedBushingModelDefinitionSchema,
|
|
513
726
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(FlangedBushing, { ...props }),
|
|
514
727
|
pads: "none"
|
|
515
728
|
});
|
|
516
|
-
function
|
|
517
|
-
registry.register(
|
|
729
|
+
function register4(registry) {
|
|
730
|
+
registry.register(model4);
|
|
518
731
|
}
|
|
519
732
|
|
|
520
733
|
// lib/models/flatheadscrew/register.tsx
|
|
@@ -647,14 +860,14 @@ function FlatHeadScrew({
|
|
|
647
860
|
}
|
|
648
861
|
|
|
649
862
|
// lib/models/flatheadscrew/register.tsx
|
|
650
|
-
var
|
|
863
|
+
var model5 = defineModelRenderer({
|
|
651
864
|
name: "flatheadscrew",
|
|
652
865
|
schema: flatHeadScrewModelDefinitionSchema,
|
|
653
866
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(FlatHeadScrew, { ...props }),
|
|
654
867
|
pads: "none"
|
|
655
868
|
});
|
|
656
|
-
function
|
|
657
|
-
registry.register(
|
|
869
|
+
function register5(registry) {
|
|
870
|
+
registry.register(model5);
|
|
658
871
|
}
|
|
659
872
|
|
|
660
873
|
// lib/models/flexscreen/register.tsx
|
|
@@ -1332,14 +1545,14 @@ var FlexScreen = (props) => {
|
|
|
1332
1545
|
};
|
|
1333
1546
|
|
|
1334
1547
|
// lib/models/flexscreen/register.tsx
|
|
1335
|
-
var
|
|
1548
|
+
var model6 = defineModelRenderer({
|
|
1336
1549
|
name: "flexscreen",
|
|
1337
1550
|
schema: flexScreenModelDefinitionSchema,
|
|
1338
1551
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(FlexScreen, { ...props }),
|
|
1339
1552
|
pads: "footprinter"
|
|
1340
1553
|
});
|
|
1341
|
-
function
|
|
1342
|
-
registry.register(
|
|
1554
|
+
function register6(registry) {
|
|
1555
|
+
registry.register(model6);
|
|
1343
1556
|
}
|
|
1344
1557
|
|
|
1345
1558
|
// lib/models/helicalgear/register.tsx
|
|
@@ -1356,7 +1569,7 @@ import {
|
|
|
1356
1569
|
getSpurGearDimensions,
|
|
1357
1570
|
spurGearModelPropsSchema
|
|
1358
1571
|
} from "@tscircuit/modelprinter";
|
|
1359
|
-
import
|
|
1572
|
+
import earcut2 from "earcut";
|
|
1360
1573
|
function createSpurGearMesh(input) {
|
|
1361
1574
|
return createTwistedSpurGearMesh(input);
|
|
1362
1575
|
}
|
|
@@ -1462,7 +1675,7 @@ function createTwistedSpurGearMesh(input, twist = 0, segmentsPerTurn = 32) {
|
|
|
1462
1675
|
};
|
|
1463
1676
|
const cap = (outer, outerStart, upward, inner) => {
|
|
1464
1677
|
const points = inner ? [...outer, ...inner.points] : outer;
|
|
1465
|
-
const triangles =
|
|
1678
|
+
const triangles = earcut2(
|
|
1466
1679
|
points.flatMap(([x, y]) => [x, y]),
|
|
1467
1680
|
inner ? [outer.length] : []
|
|
1468
1681
|
);
|
|
@@ -1545,14 +1758,14 @@ function HelicalGear({ color = "#737e8f", ...props }) {
|
|
|
1545
1758
|
}
|
|
1546
1759
|
|
|
1547
1760
|
// lib/models/helicalgear/register.tsx
|
|
1548
|
-
var
|
|
1761
|
+
var model7 = defineModelRenderer({
|
|
1549
1762
|
name: "helicalgear",
|
|
1550
1763
|
schema: helicalGearModelDefinitionSchema,
|
|
1551
1764
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HelicalGear, { ...props }),
|
|
1552
1765
|
pads: "none"
|
|
1553
1766
|
});
|
|
1554
|
-
function
|
|
1555
|
-
registry.register(
|
|
1767
|
+
function register7(registry) {
|
|
1768
|
+
registry.register(model7);
|
|
1556
1769
|
}
|
|
1557
1770
|
|
|
1558
1771
|
// lib/models/hexbolt/register.tsx
|
|
@@ -1693,14 +1906,14 @@ function HexBolt({ color = "#737e8f", ...props }) {
|
|
|
1693
1906
|
}
|
|
1694
1907
|
|
|
1695
1908
|
// lib/models/hexbolt/register.tsx
|
|
1696
|
-
var
|
|
1909
|
+
var model8 = defineModelRenderer({
|
|
1697
1910
|
name: "hexbolt",
|
|
1698
1911
|
schema: hexBoltModelDefinitionSchema,
|
|
1699
1912
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HexBolt, { ...props }),
|
|
1700
1913
|
pads: "none"
|
|
1701
1914
|
});
|
|
1702
|
-
function
|
|
1703
|
-
registry.register(
|
|
1915
|
+
function register8(registry) {
|
|
1916
|
+
registry.register(model8);
|
|
1704
1917
|
}
|
|
1705
1918
|
|
|
1706
1919
|
// lib/models/hexnut/register.tsx
|
|
@@ -1823,14 +2036,14 @@ function HexNut({ color = "#737e8f", ...props }) {
|
|
|
1823
2036
|
}
|
|
1824
2037
|
|
|
1825
2038
|
// lib/models/hexnut/register.tsx
|
|
1826
|
-
var
|
|
2039
|
+
var model9 = defineModelRenderer({
|
|
1827
2040
|
name: "hexnut",
|
|
1828
2041
|
schema: hexNutModelDefinitionSchema,
|
|
1829
2042
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HexNut, { ...props }),
|
|
1830
2043
|
pads: "none"
|
|
1831
2044
|
});
|
|
1832
|
-
function
|
|
1833
|
-
registry.register(
|
|
2045
|
+
function register9(registry) {
|
|
2046
|
+
registry.register(model9);
|
|
1834
2047
|
}
|
|
1835
2048
|
|
|
1836
2049
|
// lib/models/hexsocketbolt/register.tsx
|
|
@@ -1942,14 +2155,14 @@ function HexSocketBolt({
|
|
|
1942
2155
|
}
|
|
1943
2156
|
|
|
1944
2157
|
// lib/models/hexsocketbolt/register.tsx
|
|
1945
|
-
var
|
|
2158
|
+
var model10 = defineModelRenderer({
|
|
1946
2159
|
name: "hexsocketbolt",
|
|
1947
2160
|
schema: hexSocketBoltModelDefinitionSchema,
|
|
1948
2161
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HexSocketBolt, { ...props }),
|
|
1949
2162
|
pads: "none"
|
|
1950
2163
|
});
|
|
1951
|
-
function
|
|
1952
|
-
registry.register(
|
|
2164
|
+
function register10(registry) {
|
|
2165
|
+
registry.register(model10);
|
|
1953
2166
|
}
|
|
1954
2167
|
|
|
1955
2168
|
// lib/models/nema/register.tsx
|
|
@@ -2218,14 +2431,14 @@ var NEMA17 = (props) => /* @__PURE__ */ jsx(NemaMotor, { ...props, nemaSize: 17
|
|
|
2218
2431
|
var NEMA23 = (props) => /* @__PURE__ */ jsx(NemaMotor, { ...props, nemaSize: 23 });
|
|
2219
2432
|
|
|
2220
2433
|
// lib/models/nema/register.tsx
|
|
2221
|
-
var
|
|
2434
|
+
var model11 = defineModelRenderer({
|
|
2222
2435
|
name: "nema",
|
|
2223
2436
|
schema: nemaMotorModelDefinitionSchema,
|
|
2224
2437
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(NemaMotor, { ...props }),
|
|
2225
2438
|
pads: "none"
|
|
2226
2439
|
});
|
|
2227
|
-
function
|
|
2228
|
-
registry.register(
|
|
2440
|
+
function register11(registry) {
|
|
2441
|
+
registry.register(model11);
|
|
2229
2442
|
}
|
|
2230
2443
|
|
|
2231
2444
|
// lib/models/panscrew/register.tsx
|
|
@@ -2437,14 +2650,14 @@ function PanScrew({ color = "#737e8f", ...props }) {
|
|
|
2437
2650
|
}
|
|
2438
2651
|
|
|
2439
2652
|
// lib/models/panscrew/register.tsx
|
|
2440
|
-
var
|
|
2653
|
+
var model12 = defineModelRenderer({
|
|
2441
2654
|
name: "panscrew",
|
|
2442
2655
|
schema: panScrewModelDefinitionSchema,
|
|
2443
2656
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(PanScrew, { ...props }),
|
|
2444
2657
|
pads: "none"
|
|
2445
2658
|
});
|
|
2446
|
-
function
|
|
2447
|
-
registry.register(
|
|
2659
|
+
function register12(registry) {
|
|
2660
|
+
registry.register(model12);
|
|
2448
2661
|
}
|
|
2449
2662
|
|
|
2450
2663
|
// lib/models/plainbushing/register.tsx
|
|
@@ -2507,21 +2720,21 @@ function PlainBushing({
|
|
|
2507
2720
|
}
|
|
2508
2721
|
|
|
2509
2722
|
// lib/models/plainbushing/register.tsx
|
|
2510
|
-
var
|
|
2723
|
+
var model13 = defineModelRenderer({
|
|
2511
2724
|
name: "plainbushing",
|
|
2512
2725
|
schema: plainBushingModelDefinitionSchema,
|
|
2513
2726
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(PlainBushing, { ...props }),
|
|
2514
2727
|
pads: "none"
|
|
2515
2728
|
});
|
|
2516
|
-
function
|
|
2517
|
-
registry.register(
|
|
2729
|
+
function register13(registry) {
|
|
2730
|
+
registry.register(model13);
|
|
2518
2731
|
}
|
|
2519
2732
|
|
|
2520
2733
|
// lib/models/sheetmetal/register.tsx
|
|
2521
2734
|
import { sheetMetalModelDefinitionSchema } from "@tscircuit/modelprinter";
|
|
2522
2735
|
|
|
2523
2736
|
// lib/mechanical/sheet-metal-mesh.ts
|
|
2524
|
-
import
|
|
2737
|
+
import earcut3 from "earcut";
|
|
2525
2738
|
import {
|
|
2526
2739
|
sheetMetalModelPropsSchema
|
|
2527
2740
|
} from "@tscircuit/modelprinter";
|
|
@@ -2589,7 +2802,7 @@ function createSheetMetalMesh(input) {
|
|
|
2589
2802
|
const loops = [outline, ...holes.map((hole) => [...hole].reverse())];
|
|
2590
2803
|
const points = loops.flat();
|
|
2591
2804
|
const starts = holes.map((_, i) => 4 + i * 64);
|
|
2592
|
-
const triangles =
|
|
2805
|
+
const triangles = earcut3(
|
|
2593
2806
|
points.flatMap((p) => [p.u, p.v]),
|
|
2594
2807
|
starts
|
|
2595
2808
|
);
|
|
@@ -2674,14 +2887,14 @@ function SheetMetal({ color = "#737e8f", ...props }) {
|
|
|
2674
2887
|
}
|
|
2675
2888
|
|
|
2676
2889
|
// lib/models/sheetmetal/register.tsx
|
|
2677
|
-
var
|
|
2890
|
+
var model14 = defineModelRenderer({
|
|
2678
2891
|
name: "sheetmetal",
|
|
2679
2892
|
schema: sheetMetalModelDefinitionSchema,
|
|
2680
2893
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SheetMetal, { ...props }),
|
|
2681
2894
|
pads: "none"
|
|
2682
2895
|
});
|
|
2683
|
-
function
|
|
2684
|
-
registry.register(
|
|
2896
|
+
function register14(registry) {
|
|
2897
|
+
registry.register(model14);
|
|
2685
2898
|
}
|
|
2686
2899
|
|
|
2687
2900
|
// lib/models/spurgear/register.tsx
|
|
@@ -2696,14 +2909,152 @@ function SpurGear({ color = "#737e8f", ...props }) {
|
|
|
2696
2909
|
}
|
|
2697
2910
|
|
|
2698
2911
|
// lib/models/spurgear/register.tsx
|
|
2699
|
-
var
|
|
2912
|
+
var model15 = defineModelRenderer({
|
|
2700
2913
|
name: "spurgear",
|
|
2701
2914
|
schema: spurGearModelDefinitionSchema,
|
|
2702
2915
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SpurGear, { ...props }),
|
|
2703
2916
|
pads: "none"
|
|
2704
2917
|
});
|
|
2705
|
-
function
|
|
2706
|
-
registry.register(
|
|
2918
|
+
function register15(registry) {
|
|
2919
|
+
registry.register(model15);
|
|
2920
|
+
}
|
|
2921
|
+
|
|
2922
|
+
// lib/models/tslotextrusion/register.tsx
|
|
2923
|
+
import { tSlotExtrusionModelDefinitionSchema } from "@tscircuit/modelprinter";
|
|
2924
|
+
|
|
2925
|
+
// lib/models/tslotextrusion/mesh.ts
|
|
2926
|
+
import {
|
|
2927
|
+
tSlotExtrusionModelPropsSchema
|
|
2928
|
+
} from "@tscircuit/modelprinter";
|
|
2929
|
+
|
|
2930
|
+
// lib/mechanical/extrude-planar-profile.ts
|
|
2931
|
+
import earcut4 from "earcut";
|
|
2932
|
+
function extrudePlanarProfile({
|
|
2933
|
+
outer,
|
|
2934
|
+
holes = [],
|
|
2935
|
+
start,
|
|
2936
|
+
end,
|
|
2937
|
+
project = (u, v, depth) => [u, v, depth],
|
|
2938
|
+
reverse = false,
|
|
2939
|
+
skipWall = () => false
|
|
2940
|
+
}) {
|
|
2941
|
+
const oriented = (loop, clockwise) => {
|
|
2942
|
+
loop = loop.filter((point, index) => {
|
|
2943
|
+
const previous = loop[(index + loop.length - 1) % loop.length];
|
|
2944
|
+
return point[0] !== previous[0] || point[1] !== previous[1];
|
|
2945
|
+
});
|
|
2946
|
+
const area = loop.reduce((sum, a, index) => {
|
|
2947
|
+
const b = loop[(index + 1) % loop.length];
|
|
2948
|
+
return sum + a[0] * b[1] - a[1] * b[0];
|
|
2949
|
+
}, 0);
|
|
2950
|
+
if (!Number.isFinite(area) || area === 0)
|
|
2951
|
+
throw new Error("Profile exceeds mesh resolution limits");
|
|
2952
|
+
return area < 0 === clockwise ? loop : [...loop].reverse();
|
|
2953
|
+
};
|
|
2954
|
+
const loops = [oriented(outer, false), ...holes.map((h2) => oriented(h2, true))];
|
|
2955
|
+
const points = loops.flat();
|
|
2956
|
+
const holeStarts = [];
|
|
2957
|
+
let count = loops[0].length;
|
|
2958
|
+
for (const hole of loops.slice(1)) {
|
|
2959
|
+
holeStarts.push(count);
|
|
2960
|
+
count += hole.length;
|
|
2961
|
+
}
|
|
2962
|
+
const faces = earcut4(points.flat(), holeStarts);
|
|
2963
|
+
const positions = [start, end].flatMap(
|
|
2964
|
+
(depth) => points.flatMap(([u, v]) => project(u, v, depth))
|
|
2965
|
+
);
|
|
2966
|
+
const indices = [];
|
|
2967
|
+
for (let i = 0; i < faces.length; i += 3) {
|
|
2968
|
+
const [a, b, c] = faces.slice(i, i + 3);
|
|
2969
|
+
indices.push(a, c, b, a + count, b + count, c + count);
|
|
2970
|
+
}
|
|
2971
|
+
let offset = 0;
|
|
2972
|
+
for (const [loopIndex, loop] of loops.entries()) {
|
|
2973
|
+
for (let i = 0; i < loop.length; i++) {
|
|
2974
|
+
const next = (i + 1) % loop.length;
|
|
2975
|
+
if (loopIndex === 0 && skipWall(loop[i], loop[next])) continue;
|
|
2976
|
+
const a = offset + i;
|
|
2977
|
+
const b = offset + next;
|
|
2978
|
+
indices.push(a, b, b + count, a, b + count, a + count);
|
|
2979
|
+
}
|
|
2980
|
+
offset += loop.length;
|
|
2981
|
+
}
|
|
2982
|
+
if (reverse)
|
|
2983
|
+
for (let i = 0; i < indices.length; i += 3)
|
|
2984
|
+
[indices[i + 1], indices[i + 2]] = [indices[i + 2], indices[i + 1]];
|
|
2985
|
+
return { positions, indices };
|
|
2986
|
+
}
|
|
2987
|
+
function circularProfile(x, y, radius, segments = 96) {
|
|
2988
|
+
return Array.from({ length: segments }, (_, index) => {
|
|
2989
|
+
const angle = index * 2 * Math.PI / segments;
|
|
2990
|
+
return [x + radius * Math.cos(angle), y + radius * Math.sin(angle)];
|
|
2991
|
+
});
|
|
2992
|
+
}
|
|
2993
|
+
|
|
2994
|
+
// lib/models/tslotextrusion/mesh.ts
|
|
2995
|
+
function createTSlotExtrusionMesh(input = {}) {
|
|
2996
|
+
const props = tSlotExtrusionModelPropsSchema.parse(input);
|
|
2997
|
+
const { width: width10, height: height10, length, cornerRadius, lipThickness, pocketDepth } = props;
|
|
2998
|
+
const slot = props.slotWidth / 2;
|
|
2999
|
+
const pocket = props.pocketWidth / 2;
|
|
3000
|
+
const depth = lipThickness + pocketDepth;
|
|
3001
|
+
const outer = [];
|
|
3002
|
+
for (let face2 = 0; face2 < 4; face2++) {
|
|
3003
|
+
const span = (face2 % 2 === 0 ? width10 : height10) / 2;
|
|
3004
|
+
const extent = (face2 % 2 === 0 ? height10 : width10) / 2;
|
|
3005
|
+
const local = [
|
|
3006
|
+
[-span + cornerRadius, -extent],
|
|
3007
|
+
[-slot, -extent],
|
|
3008
|
+
[-slot, -extent + lipThickness],
|
|
3009
|
+
[-pocket, -extent + lipThickness],
|
|
3010
|
+
[-pocket, -extent + depth],
|
|
3011
|
+
[pocket, -extent + depth],
|
|
3012
|
+
[pocket, -extent + lipThickness],
|
|
3013
|
+
[slot, -extent + lipThickness],
|
|
3014
|
+
[slot, -extent],
|
|
3015
|
+
[span - cornerRadius, -extent]
|
|
3016
|
+
];
|
|
3017
|
+
if (cornerRadius > 0)
|
|
3018
|
+
for (let step = 1; step < 24; step++) {
|
|
3019
|
+
const angle = -Math.PI / 2 + step * Math.PI / 48;
|
|
3020
|
+
local.push([
|
|
3021
|
+
span - cornerRadius + cornerRadius * Math.cos(angle),
|
|
3022
|
+
-extent + cornerRadius + cornerRadius * Math.sin(angle)
|
|
3023
|
+
]);
|
|
3024
|
+
}
|
|
3025
|
+
for (const [u, v] of local)
|
|
3026
|
+
outer.push(
|
|
3027
|
+
face2 === 0 ? [u, v] : face2 === 1 ? [-v, u] : face2 === 2 ? [-u, -v] : [v, -u]
|
|
3028
|
+
);
|
|
3029
|
+
}
|
|
3030
|
+
return extrudePlanarProfile({
|
|
3031
|
+
outer,
|
|
3032
|
+
holes: props.boreDiameter > 0 ? [circularProfile(0, 0, props.boreDiameter / 2)] : [],
|
|
3033
|
+
start: 0,
|
|
3034
|
+
end: length
|
|
3035
|
+
});
|
|
3036
|
+
}
|
|
3037
|
+
|
|
3038
|
+
// lib/models/tslotextrusion/TSlotExtrusion.tsx
|
|
3039
|
+
function createTSlotExtrusionGeom(input = {}) {
|
|
3040
|
+
return indexedMeshToGeom3(createTSlotExtrusionMesh(input));
|
|
3041
|
+
}
|
|
3042
|
+
function TSlotExtrusion({
|
|
3043
|
+
color = "#8995a3",
|
|
3044
|
+
...props
|
|
3045
|
+
}) {
|
|
3046
|
+
return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsx(Custom, { geometry: createTSlotExtrusionGeom(props) }) });
|
|
3047
|
+
}
|
|
3048
|
+
|
|
3049
|
+
// lib/models/tslotextrusion/register.tsx
|
|
3050
|
+
var model16 = defineModelRenderer({
|
|
3051
|
+
name: "tslotextrusion",
|
|
3052
|
+
schema: tSlotExtrusionModelDefinitionSchema,
|
|
3053
|
+
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(TSlotExtrusion, { ...props }),
|
|
3054
|
+
pads: "none"
|
|
3055
|
+
});
|
|
3056
|
+
function register16(registry) {
|
|
3057
|
+
registry.register(model16);
|
|
2707
3058
|
}
|
|
2708
3059
|
|
|
2709
3060
|
// lib/models/wormgear/register.tsx
|
|
@@ -2714,7 +3065,7 @@ import {
|
|
|
2714
3065
|
getWormGearDimensions,
|
|
2715
3066
|
wormGearModelPropsSchema
|
|
2716
3067
|
} from "@tscircuit/modelprinter";
|
|
2717
|
-
import
|
|
3068
|
+
import earcut5 from "earcut";
|
|
2718
3069
|
var createWormGearMesh = (input) => {
|
|
2719
3070
|
const props = wormGearModelPropsSchema.parse(input);
|
|
2720
3071
|
const { outsideDiameter, rootDiameter, axialPitch, lead, toothThickness } = getWormGearDimensions(props);
|
|
@@ -2867,7 +3218,7 @@ var createWormGearMesh = (input) => {
|
|
|
2867
3218
|
positions[vertex * 3],
|
|
2868
3219
|
positions[vertex * 3 + 1]
|
|
2869
3220
|
]);
|
|
2870
|
-
const triangles =
|
|
3221
|
+
const triangles = earcut5(flat, [count], 2);
|
|
2871
3222
|
for (let index = 0; index < triangles.length; index += 3) {
|
|
2872
3223
|
const a = vertices[triangles[index]];
|
|
2873
3224
|
const b = vertices[triangles[index + 1]];
|
|
@@ -2895,14 +3246,14 @@ function WormGear({ color = "#737e8f", ...props }) {
|
|
|
2895
3246
|
}
|
|
2896
3247
|
|
|
2897
3248
|
// lib/models/wormgear/register.tsx
|
|
2898
|
-
var
|
|
3249
|
+
var model17 = defineModelRenderer({
|
|
2899
3250
|
name: "wormgear",
|
|
2900
3251
|
schema: wormGearModelDefinitionSchema,
|
|
2901
3252
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(WormGear, { ...props }),
|
|
2902
3253
|
pads: "none"
|
|
2903
3254
|
});
|
|
2904
|
-
function
|
|
2905
|
-
registry.register(
|
|
3255
|
+
function register17(registry) {
|
|
3256
|
+
registry.register(model17);
|
|
2906
3257
|
}
|
|
2907
3258
|
|
|
2908
3259
|
// lib/generated/model-renderers.ts
|
|
@@ -2922,6 +3273,8 @@ function registerAllModelRenderers(registry) {
|
|
|
2922
3273
|
register13(registry);
|
|
2923
3274
|
register14(registry);
|
|
2924
3275
|
register15(registry);
|
|
3276
|
+
register16(registry);
|
|
3277
|
+
register17(registry);
|
|
2925
3278
|
}
|
|
2926
3279
|
|
|
2927
3280
|
// lib/default-model-registry.ts
|
|
@@ -10478,10 +10831,10 @@ var SOT143 = ({ footprint = "sot143" }) => {
|
|
|
10478
10831
|
var Footprinter3d = ({ footprint }) => {
|
|
10479
10832
|
const modelFn = mp3.string(footprint.split("_", 1)[0]).params().fn;
|
|
10480
10833
|
if (mp3.getModelNames().includes(modelFn)) {
|
|
10481
|
-
const
|
|
10482
|
-
const renderer = modelRendererRegistry.get(
|
|
10834
|
+
const model18 = mp3.string(footprint).json();
|
|
10835
|
+
const renderer = modelRendererRegistry.get(model18.fn);
|
|
10483
10836
|
if (renderer) {
|
|
10484
|
-
return renderer.render(
|
|
10837
|
+
return renderer.render(model18);
|
|
10485
10838
|
}
|
|
10486
10839
|
}
|
|
10487
10840
|
let normalizedFootprint = footprint;
|
|
@@ -11434,6 +11787,7 @@ function createJSCADRenderer(jscad4) {
|
|
|
11434
11787
|
export {
|
|
11435
11788
|
ButtonScrew,
|
|
11436
11789
|
CableGrommet,
|
|
11790
|
+
CompressionSpring,
|
|
11437
11791
|
FlangedBushing,
|
|
11438
11792
|
FlatHeadScrew,
|
|
11439
11793
|
Fragment,
|
|
@@ -11449,12 +11803,15 @@ export {
|
|
|
11449
11803
|
PlainBushing,
|
|
11450
11804
|
SheetMetal,
|
|
11451
11805
|
SpurGear,
|
|
11806
|
+
TSlotExtrusion,
|
|
11452
11807
|
WormGear,
|
|
11453
11808
|
convertCSGToThreeGeom,
|
|
11454
11809
|
createButtonScrewGeom,
|
|
11455
11810
|
createButtonScrewMesh,
|
|
11456
11811
|
createCableGrommetGeom,
|
|
11457
11812
|
createCableGrommetMesh,
|
|
11813
|
+
createCompressionSpringGeom,
|
|
11814
|
+
createCompressionSpringMesh,
|
|
11458
11815
|
createFlangedBushingGeom,
|
|
11459
11816
|
createFlangedBushingMesh,
|
|
11460
11817
|
createFlatHeadScrewGeom,
|
|
@@ -11476,6 +11833,8 @@ export {
|
|
|
11476
11833
|
createSheetMetalMesh,
|
|
11477
11834
|
createSpurGearGeom,
|
|
11478
11835
|
createSpurGearMesh,
|
|
11836
|
+
createTSlotExtrusionGeom,
|
|
11837
|
+
createTSlotExtrusionMesh,
|
|
11479
11838
|
createWormGearGeom,
|
|
11480
11839
|
createWormGearMesh,
|
|
11481
11840
|
getJscadModelForFootprint,
|