jscad-electronics 0.0.194 → 0.0.196

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
@@ -179,28 +179,28 @@ var FootprintPlatedHole = ({
179
179
  throw new Error("Shape not supported: " + hole.shape);
180
180
  };
181
181
 
182
- // lib/models/flexscreen/register.tsx
183
- import { flexScreenModelDefinitionSchema } from "@tscircuit/modelprinter";
182
+ // lib/models/flatheadscrew/register.tsx
183
+ import { flatHeadScrewModelDefinitionSchema } from "@tscircuit/modelprinter";
184
184
 
185
185
  // lib/model-registry.ts
186
- function defineModelRenderer(model9) {
187
- return model9;
186
+ function defineModelRenderer(model11) {
187
+ return model11;
188
188
  }
189
189
  var ModelRendererRegistry = class {
190
190
  models = /* @__PURE__ */ new Map();
191
- register(model9) {
192
- if (typeof model9.name !== "string" || !/^[a-z]+$/.test(model9.name)) {
191
+ register(model11) {
192
+ if (typeof model11.name !== "string" || !/^[a-z]+$/.test(model11.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(model9.name)) {
198
- throw new Error(`Model renderer "${model9.name}" is already registered`);
197
+ if (this.models.has(model11.name)) {
198
+ throw new Error(`Model renderer "${model11.name}" is already registered`);
199
199
  }
200
- if (model9.pads !== "none" && model9.pads !== "footprinter") {
200
+ if (model11.pads !== "none" && model11.pads !== "footprinter") {
201
201
  throw new Error('Model renderer pads must be "none" or "footprinter"');
202
202
  }
203
- const { name, schema, render: render2, pads } = model9;
203
+ const { name, schema, render: render2, pads } = model11;
204
204
  this.models.set(name, {
205
205
  name,
206
206
  schema,
@@ -226,6 +226,161 @@ var ModelRendererRegistry = class {
226
226
  }
227
227
  };
228
228
 
229
+ // lib/models/flatheadscrew/mesh.ts
230
+ import {
231
+ flatHeadScrewModelPropsSchema
232
+ } from "@tscircuit/modelprinter";
233
+ function createFlatHeadScrewMesh(input, options = {}) {
234
+ const p = flatHeadScrewModelPropsSchema.parse(input);
235
+ const segments = options.radialSegments ?? 96;
236
+ const axial = options.threadStepsPerTurn ?? 24;
237
+ if (!Number.isInteger(segments) || segments < 24 || segments > 192 || segments % 24 !== 0 || !Number.isInteger(axial) || axial < 24 || axial > 96)
238
+ throw new Error(
239
+ "Screw mesh resolution requires 24..192 radial segments divisible by 24 and 24..96 thread steps"
240
+ );
241
+ const positions = [], indices = [];
242
+ const welded = /* @__PURE__ */ new Map();
243
+ const vertex = (x, y, z) => {
244
+ const key = [x, y, z].map((v) => Math.round(v * 1e10)).join(":");
245
+ const existing = welded.get(key);
246
+ if (existing !== void 0) return existing;
247
+ const index = positions.length / 3;
248
+ positions.push(x, y, z);
249
+ welded.set(key, index);
250
+ return index;
251
+ };
252
+ const triangle = (a, b, c) => {
253
+ if (a === b || b === c || c === a) return;
254
+ const point = (i) => positions.slice(3 * i, 3 * i + 3);
255
+ const A = point(a), B = point(b), C = point(c);
256
+ const u = B.map((v2, i) => v2 - A[i]), v = C.map((w, i) => w - A[i]);
257
+ const area = Math.hypot(
258
+ u[1] * v[2] - u[2] * v[1],
259
+ u[2] * v[0] - u[0] * v[2],
260
+ u[0] * v[1] - u[1] * v[0]
261
+ );
262
+ if (area > 1e-12) indices.push(a, b, c);
263
+ };
264
+ const ring = (radiusAt, zAt) => Array.from({ length: segments }, (_, i) => {
265
+ const theta = i * 2 * Math.PI / segments, r = radiusAt(theta);
266
+ return vertex(
267
+ r * Math.cos(theta),
268
+ r * Math.sin(theta),
269
+ typeof zAt === "number" ? zAt : zAt(theta)
270
+ );
271
+ });
272
+ const connect = (a, b) => {
273
+ for (let i = 0; i < segments; i++) {
274
+ const n = (i + 1) % segments;
275
+ triangle(a[i], a[n], b[n]);
276
+ triangle(a[i], b[n], b[i]);
277
+ }
278
+ };
279
+ const cap = (a, z, up) => {
280
+ const c = vertex(0, 0, z);
281
+ for (let i = 0; i < segments; i++) {
282
+ const n = (i + 1) % segments;
283
+ up ? triangle(c, a[i], a[n]) : triangle(c, a[n], a[i]);
284
+ }
285
+ };
286
+ let previous = [];
287
+ const add = (radiusAt, zAt) => {
288
+ const r = ring(radiusAt, zAt);
289
+ if (previous.length) connect(previous, r);
290
+ previous = r;
291
+ return r;
292
+ };
293
+ const major = p.diameter / 2, minor = p.threadRootDiameter / 2, pitch = p.threadPitch;
294
+ const shaftEnd = -p.headHeight - p.underHeadRadius * (Math.sqrt(2) - 1);
295
+ const steps = p.showThreads ? Math.ceil((shaftEnd + p.length) / pitch * axial) : 1;
296
+ if ((steps + 100) * segments > 4e5)
297
+ throw new Error("Screw exceeds mesh resolution limit");
298
+ const levels = /* @__PURE__ */ new Set([
299
+ -p.length,
300
+ -p.length + p.tipChamfer,
301
+ shaftEnd
302
+ ]);
303
+ if (p.showThreads)
304
+ for (let i = 0; i <= steps; i++)
305
+ levels.add(-p.length + (shaftEnd + p.length) * i / steps);
306
+ for (const z of [...levels].sort((a, b) => a - b)) {
307
+ const r = add((theta) => {
308
+ const phase = (((z + p.length) / pitch - (p.threadHand === "right" ? 1 : -1) * theta / (2 * Math.PI)) % 1 + 1) % 1;
309
+ const d = Math.min(phase, 1 - phase);
310
+ const groove = Math.min(
311
+ major - minor,
312
+ Math.max(0, (d - 1 / 16) * pitch * Math.sqrt(3))
313
+ );
314
+ const thread = p.showThreads ? major - groove : major;
315
+ return Math.min(
316
+ thread,
317
+ major - Math.max(0, p.tipChamfer - (z + p.length))
318
+ );
319
+ }, z);
320
+ if (z === -p.length) cap(r, z, false);
321
+ }
322
+ add(() => major, shaftEnd);
323
+ const filletCenterR = major + p.underHeadRadius;
324
+ const filletCenterZ = shaftEnd;
325
+ for (let i = 1; i <= 16; i++) {
326
+ const angle = Math.PI - (Math.PI - 3 * Math.PI / 4) * i / 16;
327
+ add(
328
+ () => filletCenterR + p.underHeadRadius * Math.cos(angle),
329
+ filletCenterZ + p.underHeadRadius * Math.sin(angle)
330
+ );
331
+ }
332
+ const hexRadius = (theta) => p.socketAcrossFlats / 2 / Math.max(
333
+ Math.abs(Math.sin(theta)),
334
+ Math.abs(Math.sin(theta + 2 * Math.PI / 3)),
335
+ Math.abs(Math.sin(theta + 4 * Math.PI / 3))
336
+ );
337
+ add(() => p.headDiameter / 2, 0);
338
+ add(hexRadius, 0);
339
+ add(hexRadius, -p.socketDepth);
340
+ cap(previous, -p.socketDepth, true);
341
+ return { positions, indices };
342
+ }
343
+
344
+ // lib/mechanical/indexedMeshToGeom3.ts
345
+ import jscad from "@jscad/modeling";
346
+ function indexedMeshToGeom3(mesh) {
347
+ const polygons = [];
348
+ for (let i = 0; i < mesh.indices.length; i += 3)
349
+ polygons.push(
350
+ mesh.indices.slice(i, i + 3).map((index) => [
351
+ mesh.positions[index * 3],
352
+ mesh.positions[index * 3 + 1],
353
+ mesh.positions[index * 3 + 2]
354
+ ])
355
+ );
356
+ return jscad.geometries.geom3.fromPoints(polygons);
357
+ }
358
+
359
+ // lib/models/flatheadscrew/FlatHeadScrew.tsx
360
+ function createFlatHeadScrewGeom(input, options) {
361
+ return indexedMeshToGeom3(createFlatHeadScrewMesh(input, options));
362
+ }
363
+ function FlatHeadScrew({
364
+ color = "#737e8f",
365
+ ...props
366
+ }) {
367
+ return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsx(Custom, { geometry: createFlatHeadScrewGeom(props) }) });
368
+ }
369
+
370
+ // lib/models/flatheadscrew/register.tsx
371
+ var model = defineModelRenderer({
372
+ name: "flatheadscrew",
373
+ schema: flatHeadScrewModelDefinitionSchema,
374
+ render: ({ fn, ...props }) => /* @__PURE__ */ jsx(FlatHeadScrew, { ...props }),
375
+ pads: "none"
376
+ });
377
+ function register(registry) {
378
+ registry.register(model);
379
+ }
380
+
381
+ // lib/models/flexscreen/register.tsx
382
+ import { flexScreenModelDefinitionSchema } from "@tscircuit/modelprinter";
383
+
229
384
  // lib/Screen.tsx
230
385
  var Screen = ({
231
386
  width: width10 = 30,
@@ -898,34 +1053,19 @@ var FlexScreen = (props) => {
898
1053
  };
899
1054
 
900
1055
  // lib/models/flexscreen/register.tsx
901
- var model = defineModelRenderer({
1056
+ var model2 = defineModelRenderer({
902
1057
  name: "flexscreen",
903
1058
  schema: flexScreenModelDefinitionSchema,
904
1059
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(FlexScreen, { ...props }),
905
1060
  pads: "footprinter"
906
1061
  });
907
- function register(registry) {
908
- registry.register(model);
1062
+ function register2(registry) {
1063
+ registry.register(model2);
909
1064
  }
910
1065
 
911
1066
  // lib/models/helicalgear/register.tsx
912
1067
  import { helicalGearModelDefinitionSchema } from "@tscircuit/modelprinter";
913
1068
 
914
- // lib/mechanical/indexedMeshToGeom3.ts
915
- import jscad from "@jscad/modeling";
916
- function indexedMeshToGeom3(mesh) {
917
- const polygons = [];
918
- for (let i = 0; i < mesh.indices.length; i += 3)
919
- polygons.push(
920
- mesh.indices.slice(i, i + 3).map((index) => [
921
- mesh.positions[index * 3],
922
- mesh.positions[index * 3 + 1],
923
- mesh.positions[index * 3 + 2]
924
- ])
925
- );
926
- return jscad.geometries.geom3.fromPoints(polygons);
927
- }
928
-
929
1069
  // lib/mechanical/helical-gear-mesh.ts
930
1070
  import {
931
1071
  getHelicalGearDimensions,
@@ -1126,14 +1266,14 @@ function HelicalGear({ color = "#737e8f", ...props }) {
1126
1266
  }
1127
1267
 
1128
1268
  // lib/models/helicalgear/register.tsx
1129
- var model2 = defineModelRenderer({
1269
+ var model3 = defineModelRenderer({
1130
1270
  name: "helicalgear",
1131
1271
  schema: helicalGearModelDefinitionSchema,
1132
1272
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HelicalGear, { ...props }),
1133
1273
  pads: "none"
1134
1274
  });
1135
- function register2(registry) {
1136
- registry.register(model2);
1275
+ function register3(registry) {
1276
+ registry.register(model3);
1137
1277
  }
1138
1278
 
1139
1279
  // lib/models/hexbolt/register.tsx
@@ -1274,14 +1414,14 @@ function HexBolt({ color = "#737e8f", ...props }) {
1274
1414
  }
1275
1415
 
1276
1416
  // lib/models/hexbolt/register.tsx
1277
- var model3 = defineModelRenderer({
1417
+ var model4 = defineModelRenderer({
1278
1418
  name: "hexbolt",
1279
1419
  schema: hexBoltModelDefinitionSchema,
1280
1420
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HexBolt, { ...props }),
1281
1421
  pads: "none"
1282
1422
  });
1283
- function register3(registry) {
1284
- registry.register(model3);
1423
+ function register4(registry) {
1424
+ registry.register(model4);
1285
1425
  }
1286
1426
 
1287
1427
  // lib/models/hexsocketbolt/register.tsx
@@ -1393,14 +1533,14 @@ function HexSocketBolt({
1393
1533
  }
1394
1534
 
1395
1535
  // lib/models/hexsocketbolt/register.tsx
1396
- var model4 = defineModelRenderer({
1536
+ var model5 = defineModelRenderer({
1397
1537
  name: "hexsocketbolt",
1398
1538
  schema: hexSocketBoltModelDefinitionSchema,
1399
1539
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(HexSocketBolt, { ...props }),
1400
1540
  pads: "none"
1401
1541
  });
1402
- function register4(registry) {
1403
- registry.register(model4);
1542
+ function register5(registry) {
1543
+ registry.register(model5);
1404
1544
  }
1405
1545
 
1406
1546
  // lib/models/nema/register.tsx
@@ -1669,14 +1809,233 @@ var NEMA17 = (props) => /* @__PURE__ */ jsx(NemaMotor, { ...props, nemaSize: 17
1669
1809
  var NEMA23 = (props) => /* @__PURE__ */ jsx(NemaMotor, { ...props, nemaSize: 23 });
1670
1810
 
1671
1811
  // lib/models/nema/register.tsx
1672
- var model5 = defineModelRenderer({
1812
+ var model6 = defineModelRenderer({
1673
1813
  name: "nema",
1674
1814
  schema: nemaMotorModelDefinitionSchema,
1675
1815
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(NemaMotor, { ...props }),
1676
1816
  pads: "none"
1677
1817
  });
1678
- function register5(registry) {
1679
- registry.register(model5);
1818
+ function register6(registry) {
1819
+ registry.register(model6);
1820
+ }
1821
+
1822
+ // lib/models/panscrew/register.tsx
1823
+ import { panScrewModelDefinitionSchema } from "@tscircuit/modelprinter";
1824
+
1825
+ // lib/models/panscrew/mesh.ts
1826
+ import {
1827
+ panScrewModelPropsSchema
1828
+ } from "@tscircuit/modelprinter";
1829
+ function createPanScrewMesh(input, options = {}) {
1830
+ const p = panScrewModelPropsSchema.parse(input);
1831
+ const segments = options.radialSegments ?? 96;
1832
+ const axial = options.threadStepsPerTurn ?? 24;
1833
+ if (!Number.isInteger(segments) || segments < 24 || segments > 192 || segments % 24 !== 0 || !Number.isInteger(axial) || axial < 24 || axial > 96)
1834
+ throw new Error(
1835
+ "Screw mesh resolution requires 24..192 radial segments divisible by 24 and 24..96 thread steps"
1836
+ );
1837
+ const positions = [], indices = [];
1838
+ const welded = /* @__PURE__ */ new Map();
1839
+ const vertex = (x, y, z) => {
1840
+ const key = [x, y, z].map((v) => Math.round(v * 1e10)).join(":");
1841
+ const existing = welded.get(key);
1842
+ if (existing !== void 0) return existing;
1843
+ const index = positions.length / 3;
1844
+ positions.push(x, y, z);
1845
+ welded.set(key, index);
1846
+ return index;
1847
+ };
1848
+ const triangle = (a, b, c) => {
1849
+ if (a === b || b === c || c === a) return;
1850
+ const point2 = (i) => positions.slice(3 * i, 3 * i + 3);
1851
+ const A = point2(a), B = point2(b), C = point2(c);
1852
+ const u = B.map((v2, i) => v2 - A[i]), v = C.map((w, i) => w - A[i]);
1853
+ const area = Math.hypot(
1854
+ u[1] * v[2] - u[2] * v[1],
1855
+ u[2] * v[0] - u[0] * v[2],
1856
+ u[0] * v[1] - u[1] * v[0]
1857
+ );
1858
+ if (area > 1e-12) indices.push(a, b, c);
1859
+ };
1860
+ const ring = (radiusAt, zAt) => Array.from({ length: segments }, (_, i) => {
1861
+ const theta = i * 2 * Math.PI / segments, r = radiusAt(theta);
1862
+ return vertex(
1863
+ r * Math.cos(theta),
1864
+ r * Math.sin(theta),
1865
+ typeof zAt === "number" ? zAt : zAt(theta)
1866
+ );
1867
+ });
1868
+ const connect = (a, b) => {
1869
+ for (let i = 0; i < segments; i++) {
1870
+ const n = (i + 1) % segments;
1871
+ triangle(a[i], a[n], b[n]);
1872
+ triangle(a[i], b[n], b[i]);
1873
+ }
1874
+ };
1875
+ const cap = (a, z, up) => {
1876
+ const c = vertex(0, 0, z);
1877
+ for (let i = 0; i < segments; i++) {
1878
+ const n = (i + 1) % segments;
1879
+ up ? triangle(c, a[i], a[n]) : triangle(c, a[n], a[i]);
1880
+ }
1881
+ };
1882
+ let previous = [];
1883
+ const add = (radiusAt, zAt) => {
1884
+ const r = ring(radiusAt, zAt);
1885
+ if (previous.length) connect(previous, r);
1886
+ previous = r;
1887
+ return r;
1888
+ };
1889
+ const major = p.diameter / 2, minor = p.threadRootDiameter / 2, pitch = p.threadPitch;
1890
+ const shaftEnd = -p.underHeadRadius;
1891
+ const steps = p.showThreads ? Math.ceil((shaftEnd + p.length) / pitch * axial) : 1;
1892
+ if ((steps + 160) * segments > 4e5)
1893
+ throw new Error("Screw exceeds mesh resolution limit");
1894
+ const levels = /* @__PURE__ */ new Set([
1895
+ -p.length,
1896
+ -p.length + p.tipChamfer,
1897
+ shaftEnd
1898
+ ]);
1899
+ if (p.showThreads)
1900
+ for (let i = 0; i <= steps; i++)
1901
+ levels.add(-p.length + (shaftEnd + p.length) * i / steps);
1902
+ for (const z of [...levels].sort((a, b) => a - b)) {
1903
+ const r = add((theta) => {
1904
+ const phase = (((z + p.length) / pitch - (p.threadHand === "right" ? 1 : -1) * theta / (2 * Math.PI)) % 1 + 1) % 1;
1905
+ const d = Math.min(phase, 1 - phase);
1906
+ const groove = Math.min(
1907
+ major - minor,
1908
+ Math.max(0, (d - 1 / 16) * pitch * Math.sqrt(3))
1909
+ );
1910
+ const thread = p.showThreads ? major - groove : major;
1911
+ return Math.min(
1912
+ thread,
1913
+ major - Math.max(0, p.tipChamfer - (z + p.length))
1914
+ );
1915
+ }, z);
1916
+ if (z === -p.length) cap(r, z, false);
1917
+ }
1918
+ add(() => major, shaftEnd);
1919
+ const filletCenterR = major + p.underHeadRadius;
1920
+ const filletCenterZ = shaftEnd;
1921
+ for (let i = 1; i <= 16; i++) {
1922
+ const angle = Math.PI - (Math.PI - Math.PI / 2) * i / 16;
1923
+ add(
1924
+ () => filletCenterR + p.underHeadRadius * Math.cos(angle),
1925
+ filletCenterZ + p.underHeadRadius * Math.sin(angle)
1926
+ );
1927
+ }
1928
+ const crown = (r) => p.headHeight - p.crownRadius + Math.sqrt(p.crownRadius * p.crownRadius - r * r);
1929
+ const rad265 = p.recessOuterWingAngle * Math.PI / 180, rad28 = p.recessInnerWingAngle * Math.PI / 180;
1930
+ const tg = (p.recessReferenceDiameter - p.recessG) / 2 / Math.tan(rad265);
1931
+ const totalDepth = tg + p.recessG / 2 * Math.tan(rad28);
1932
+ const tb = tg + (p.recessG - p.recessB) / 2 * Math.tan(rad28);
1933
+ const beta = p.recessBeta * Math.PI / 180;
1934
+ const alphaProjected = Math.atan(
1935
+ Math.tan(p.recessAlpha * Math.PI / 360) / Math.cos(beta)
1936
+ );
1937
+ const cornerProjected = Math.atan(
1938
+ Math.tan(46 * Math.PI / 180) / Math.cos(beta)
1939
+ );
1940
+ const dre = p.recessE / 2 / Math.tan(alphaProjected);
1941
+ const cornerRadius = (z, theta) => {
1942
+ const depth = p.recessReferencePlaneHeight - z;
1943
+ const b = p.recessB / 2 - (depth - tb) * Math.tan(beta);
1944
+ const delta = Math.abs(
1945
+ (theta - Math.PI / 4 + Math.PI / 4 + 4 * Math.PI) % (Math.PI / 2) - Math.PI / 4
1946
+ );
1947
+ const ca = Math.cos(delta), sa = Math.sin(delta);
1948
+ const tanA = Math.tan(alphaProjected), tanC = Math.tan(cornerProjected);
1949
+ const first = tanA * b / (tanA * ca - sa);
1950
+ const corner = first * ca <= b + dre ? first : (tanC * (b + dre) - p.recessE / 2) / (tanC * ca - sa);
1951
+ return Math.max(0, corner);
1952
+ };
1953
+ const recessRadius = (z, theta) => {
1954
+ const depth = p.recessReferencePlaneHeight - z;
1955
+ const outer = depth <= tg ? p.recessReferenceDiameter / 2 - depth * Math.tan(rad265) : (totalDepth - depth) / Math.tan(rad28);
1956
+ return Math.max(0, Math.min(outer, cornerRadius(z, theta)));
1957
+ };
1958
+ const entryRadius = p.recessRadius, sphereZ = p.headHeight - p.crownRadius, slope = Math.tan(rad265), line = p.recessReferenceDiameter / 2 - slope * p.recessReferencePlaneHeight + entryRadius / Math.cos(rad265), offset = slope * sphereZ + line, innerSphere = p.crownRadius - entryRadius, centerAboveSphere = (-slope * offset + Math.sqrt((1 + slope * slope) * innerSphere ** 2 - offset ** 2)) / (1 + slope * slope), entryCenterZ = sphereZ + centerAboveSphere, entryCenterR = slope * entryCenterZ + line, entryStart = Math.atan2(centerAboveSphere, entryCenterR), entryEnd = Math.PI - rad265, mouthR = entryCenterR + entryRadius * Math.cos(entryStart), wallZ = entryCenterZ + entryRadius * Math.sin(entryEnd);
1959
+ add(() => p.headDiameter / 2, 0);
1960
+ add(() => p.headDiameter / 2, crown(p.headDiameter / 2));
1961
+ const opening = Array.from({ length: segments }, (_, i) => {
1962
+ const theta = i * 2 * Math.PI / segments;
1963
+ let lo = 0, hi = mouthR;
1964
+ for (let n = 0; n < 48; n++) {
1965
+ const r = (lo + hi) / 2;
1966
+ if (r < cornerRadius(crown(r), theta)) lo = r;
1967
+ else hi = r;
1968
+ }
1969
+ return (lo + hi) / 2;
1970
+ });
1971
+ for (let n = 1; n <= 20; n++) {
1972
+ const r = (theta) => {
1973
+ const i = Math.round(theta * segments / (2 * Math.PI)) % segments;
1974
+ return p.headDiameter / 2 + (opening[i] - p.headDiameter / 2) * n / 20;
1975
+ };
1976
+ add(r, (theta) => crown(r(theta)));
1977
+ }
1978
+ const entryClips = Array.from({ length: segments }, (_, i) => {
1979
+ const theta = i * 2 * Math.PI / segments;
1980
+ const point2 = (angle2) => ({
1981
+ r: entryCenterR + entryRadius * Math.cos(angle2),
1982
+ z: entryCenterZ + entryRadius * Math.sin(angle2)
1983
+ });
1984
+ const outside = (angle2) => {
1985
+ const q = point2(angle2);
1986
+ return q.r > cornerRadius(q.z, theta);
1987
+ };
1988
+ if (!outside(entryStart)) return { angle: entryStart, ...point2(entryStart) };
1989
+ if (outside(entryEnd))
1990
+ return { angle: entryEnd, r: cornerRadius(wallZ, theta), z: wallZ };
1991
+ let lo = entryStart, hi = entryEnd;
1992
+ for (let n = 0; n < 48; n++) {
1993
+ const angle2 = (lo + hi) / 2;
1994
+ if (outside(angle2)) lo = angle2;
1995
+ else hi = angle2;
1996
+ }
1997
+ const angle = (lo + hi) / 2;
1998
+ return { angle, ...point2(angle) };
1999
+ });
2000
+ for (let n = 0; n <= 24; n++) {
2001
+ const angle = entryStart + (entryEnd - entryStart) * n / 24;
2002
+ const r = entryCenterR + entryRadius * Math.cos(angle), z = entryCenterZ + entryRadius * Math.sin(angle);
2003
+ const clip = (theta) => entryClips[Math.round(theta * segments / (2 * Math.PI)) % segments];
2004
+ add(
2005
+ (theta) => angle <= clip(theta).angle ? clip(theta).r : r,
2006
+ (theta) => angle <= clip(theta).angle ? clip(theta).z : z
2007
+ );
2008
+ }
2009
+ const floor = p.recessReferencePlaneHeight - totalDepth;
2010
+ const driveLevels = /* @__PURE__ */ new Set([p.recessReferencePlaneHeight - tg]);
2011
+ for (let n = 1; n < 48; n++)
2012
+ driveLevels.add(wallZ + (floor - wallZ) * n / 48);
2013
+ for (const z of [...driveLevels].filter((z2) => z2 < wallZ && z2 > floor).sort((a, b) => b - a)) {
2014
+ add((theta) => recessRadius(z, theta), z);
2015
+ }
2016
+ const point = vertex(0, 0, floor);
2017
+ for (let i = 0; i < segments; i++)
2018
+ triangle(point, previous[i], previous[(i + 1) % segments]);
2019
+ return { positions, indices };
2020
+ }
2021
+
2022
+ // lib/models/panscrew/PanScrew.tsx
2023
+ function createPanScrewGeom(input, options) {
2024
+ return indexedMeshToGeom3(createPanScrewMesh(input, options));
2025
+ }
2026
+ function PanScrew({ color = "#737e8f", ...props }) {
2027
+ return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsx(Custom, { geometry: createPanScrewGeom(props) }) });
2028
+ }
2029
+
2030
+ // lib/models/panscrew/register.tsx
2031
+ var model7 = defineModelRenderer({
2032
+ name: "panscrew",
2033
+ schema: panScrewModelDefinitionSchema,
2034
+ render: ({ fn, ...props }) => /* @__PURE__ */ jsx(PanScrew, { ...props }),
2035
+ pads: "none"
2036
+ });
2037
+ function register7(registry) {
2038
+ registry.register(model7);
1680
2039
  }
1681
2040
 
1682
2041
  // lib/models/sheetmetal/register.tsx
@@ -1836,14 +2195,14 @@ function SheetMetal({ color = "#737e8f", ...props }) {
1836
2195
  }
1837
2196
 
1838
2197
  // lib/models/sheetmetal/register.tsx
1839
- var model6 = defineModelRenderer({
2198
+ var model8 = defineModelRenderer({
1840
2199
  name: "sheetmetal",
1841
2200
  schema: sheetMetalModelDefinitionSchema,
1842
2201
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SheetMetal, { ...props }),
1843
2202
  pads: "none"
1844
2203
  });
1845
- function register6(registry) {
1846
- registry.register(model6);
2204
+ function register8(registry) {
2205
+ registry.register(model8);
1847
2206
  }
1848
2207
 
1849
2208
  // lib/models/spurgear/register.tsx
@@ -1858,14 +2217,14 @@ function SpurGear({ color = "#737e8f", ...props }) {
1858
2217
  }
1859
2218
 
1860
2219
  // lib/models/spurgear/register.tsx
1861
- var model7 = defineModelRenderer({
2220
+ var model9 = defineModelRenderer({
1862
2221
  name: "spurgear",
1863
2222
  schema: spurGearModelDefinitionSchema,
1864
2223
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SpurGear, { ...props }),
1865
2224
  pads: "none"
1866
2225
  });
1867
- function register7(registry) {
1868
- registry.register(model7);
2226
+ function register9(registry) {
2227
+ registry.register(model9);
1869
2228
  }
1870
2229
 
1871
2230
  // lib/models/wormgear/register.tsx
@@ -2057,14 +2416,14 @@ function WormGear({ color = "#737e8f", ...props }) {
2057
2416
  }
2058
2417
 
2059
2418
  // lib/models/wormgear/register.tsx
2060
- var model8 = defineModelRenderer({
2419
+ var model10 = defineModelRenderer({
2061
2420
  name: "wormgear",
2062
2421
  schema: wormGearModelDefinitionSchema,
2063
2422
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(WormGear, { ...props }),
2064
2423
  pads: "none"
2065
2424
  });
2066
- function register8(registry) {
2067
- registry.register(model8);
2425
+ function register10(registry) {
2426
+ registry.register(model10);
2068
2427
  }
2069
2428
 
2070
2429
  // lib/generated/model-renderers.ts
@@ -2077,6 +2436,8 @@ function registerAllModelRenderers(registry) {
2077
2436
  register6(registry);
2078
2437
  register7(registry);
2079
2438
  register8(registry);
2439
+ register9(registry);
2440
+ register10(registry);
2080
2441
  }
2081
2442
 
2082
2443
  // lib/default-model-registry.ts
@@ -9633,10 +9994,10 @@ var SOT143 = ({ footprint = "sot143" }) => {
9633
9994
  var Footprinter3d = ({ footprint }) => {
9634
9995
  const modelFn = mp3.string(footprint.split("_", 1)[0]).params().fn;
9635
9996
  if (mp3.getModelNames().includes(modelFn)) {
9636
- const model9 = mp3.string(footprint).json();
9637
- const renderer = modelRendererRegistry.get(model9.fn);
9997
+ const model11 = mp3.string(footprint).json();
9998
+ const renderer = modelRendererRegistry.get(model11.fn);
9638
9999
  if (renderer) {
9639
- return renderer.render(model9);
10000
+ return renderer.render(model11);
9640
10001
  }
9641
10002
  }
9642
10003
  let normalizedFootprint = footprint;
@@ -10587,6 +10948,7 @@ function createJSCADRenderer(jscad4) {
10587
10948
  return { createJSCADRoot };
10588
10949
  }
10589
10950
  export {
10951
+ FlatHeadScrew,
10590
10952
  Fragment,
10591
10953
  HelicalGear,
10592
10954
  HexBolt,
@@ -10595,10 +10957,13 @@ export {
10595
10957
  NEMA23,
10596
10958
  NEMA8,
10597
10959
  NemaMotor,
10960
+ PanScrew,
10598
10961
  SheetMetal,
10599
10962
  SpurGear,
10600
10963
  WormGear,
10601
10964
  convertCSGToThreeGeom,
10965
+ createFlatHeadScrewGeom,
10966
+ createFlatHeadScrewMesh,
10602
10967
  createHelicalGearGeom,
10603
10968
  createHelicalGearMesh,
10604
10969
  createHexBoltGeom,
@@ -10606,6 +10971,8 @@ export {
10606
10971
  createHexSocketBoltGeom,
10607
10972
  createHexSocketBoltMesh,
10608
10973
  createJSCADRenderer,
10974
+ createPanScrewGeom,
10975
+ createPanScrewMesh,
10609
10976
  createSheetMetalGeom,
10610
10977
  createSheetMetalMesh,
10611
10978
  createSpurGearGeom,