jscad-electronics 0.0.195 → 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.d.ts CHANGED
@@ -3,7 +3,7 @@ import { BufferGeometry } from 'three';
3
3
  import * as jscadModeling from '@jscad/modeling';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import * as _jscad_modeling_src_geometries_types from '@jscad/modeling/src/geometries/types';
6
- import { FlatHeadScrewModelPropsInput, SpurGearModelPropsInput, HelicalGearModelPropsInput, HexBoltModelPropsInput, HexSocketBoltModelPropsInput, NemaMotorModelPropsInput, SheetMetalModelPropsInput, WormGearModelPropsInput } from '@tscircuit/modelprinter';
6
+ import { FlatHeadScrewModelPropsInput, SpurGearModelPropsInput, HelicalGearModelPropsInput, HexBoltModelPropsInput, HexSocketBoltModelPropsInput, NemaMotorModelPropsInput, PanScrewModelPropsInput, SheetMetalModelPropsInput, WormGearModelPropsInput } from '@tscircuit/modelprinter';
7
7
 
8
8
  type VNode = {
9
9
  type: any;
@@ -124,6 +124,23 @@ declare const NEMA8: (props: NemaFrameMotorProps) => react_jsx_runtime.JSX.Eleme
124
124
  declare const NEMA17: (props: NemaFrameMotorProps) => react_jsx_runtime.JSX.Element;
125
125
  declare const NEMA23: (props: NemaFrameMotorProps) => react_jsx_runtime.JSX.Element;
126
126
 
127
+ interface PanScrewMeshOptions {
128
+ radialSegments?: number;
129
+ threadStepsPerTurn?: number;
130
+ }
131
+ /** Outward-oriented, welded indexed surface, in millimeters. */
132
+ interface PanScrewMesh {
133
+ positions: number[];
134
+ indices: number[];
135
+ }
136
+ declare function createPanScrewMesh(input: PanScrewModelPropsInput, options?: PanScrewMeshOptions): PanScrewMesh;
137
+
138
+ type PanScrewProps = PanScrewModelPropsInput & {
139
+ color?: string;
140
+ };
141
+ declare function createPanScrewGeom(input: PanScrewModelPropsInput, options?: PanScrewMeshOptions): _jscad_modeling_src_geometries_types.Geom3;
142
+ declare function PanScrew({ color, ...props }: PanScrewProps): react_jsx_runtime.JSX.Element;
143
+
127
144
  interface SheetMetalMesh {
128
145
  positions: number[];
129
146
  indices: number[];
@@ -178,4 +195,4 @@ declare function createJSCADRenderer(jscad: typeof jscadModeling): {
178
195
  };
179
196
  };
180
197
 
181
- export { type ColoredGeom, FlatHeadScrew, type FlatHeadScrewMesh, type FlatHeadScrewMeshOptions, type FlatHeadScrewProps, Fragment, HelicalGear, type HelicalGearMesh, type HelicalGearProps, HexBolt, type HexBoltMesh, type HexBoltMeshOptions, type HexBoltProps, HexSocketBolt, type HexSocketBoltMesh, type HexSocketBoltProps, NEMA17, NEMA23, NEMA8, type NemaFrameMotorProps, NemaMotor, type NemaMotorProps, type RenderResult, SheetMetal, type SheetMetalMesh, type SheetMetalProps, SpurGear, type SpurGearMesh, type SpurGearProps, type VNode, WormGear, type WormGearMesh, type WormGearProps, convertCSGToThreeGeom, createFlatHeadScrewGeom, createFlatHeadScrewMesh, createHelicalGearGeom, createHelicalGearMesh, createHexBoltGeom, createHexBoltMesh, createHexSocketBoltGeom, createHexSocketBoltMesh, createJSCADRenderer, createSheetMetalGeom, createSheetMetalMesh, createSpurGearGeom, createSpurGearMesh, createWormGearGeom, createWormGearMesh, getJscadModelForFootprint, getJscadModelForFootprintWithPads, h };
198
+ export { type ColoredGeom, FlatHeadScrew, type FlatHeadScrewMesh, type FlatHeadScrewMeshOptions, type FlatHeadScrewProps, Fragment, HelicalGear, type HelicalGearMesh, type HelicalGearProps, HexBolt, type HexBoltMesh, type HexBoltMeshOptions, type HexBoltProps, HexSocketBolt, type HexSocketBoltMesh, type HexSocketBoltProps, NEMA17, NEMA23, NEMA8, type NemaFrameMotorProps, NemaMotor, type NemaMotorProps, PanScrew, type PanScrewMesh, type PanScrewMeshOptions, type PanScrewProps, type RenderResult, SheetMetal, type SheetMetalMesh, type SheetMetalProps, SpurGear, type SpurGearMesh, type SpurGearProps, type VNode, WormGear, type WormGearMesh, type WormGearProps, convertCSGToThreeGeom, createFlatHeadScrewGeom, createFlatHeadScrewMesh, createHelicalGearGeom, createHelicalGearMesh, createHexBoltGeom, createHexBoltMesh, createHexSocketBoltGeom, createHexSocketBoltMesh, createJSCADRenderer, createPanScrewGeom, createPanScrewMesh, createSheetMetalGeom, createSheetMetalMesh, createSpurGearGeom, createSpurGearMesh, createWormGearGeom, createWormGearMesh, getJscadModelForFootprint, getJscadModelForFootprintWithPads, h };
package/dist/vanilla.js CHANGED
@@ -183,24 +183,24 @@ var FootprintPlatedHole = ({
183
183
  import { flatHeadScrewModelDefinitionSchema } from "@tscircuit/modelprinter";
184
184
 
185
185
  // lib/model-registry.ts
186
- function defineModelRenderer(model10) {
187
- return model10;
186
+ function defineModelRenderer(model11) {
187
+ return model11;
188
188
  }
189
189
  var ModelRendererRegistry = class {
190
190
  models = /* @__PURE__ */ new Map();
191
- register(model10) {
192
- if (typeof model10.name !== "string" || !/^[a-z]+$/.test(model10.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(model10.name)) {
198
- throw new Error(`Model renderer "${model10.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 (model10.pads !== "none" && model10.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 } = model10;
203
+ const { name, schema, render: render2, pads } = model11;
204
204
  this.models.set(name, {
205
205
  name,
206
206
  schema,
@@ -1819,6 +1819,225 @@ function register6(registry) {
1819
1819
  registry.register(model6);
1820
1820
  }
1821
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);
2039
+ }
2040
+
1822
2041
  // lib/models/sheetmetal/register.tsx
1823
2042
  import { sheetMetalModelDefinitionSchema } from "@tscircuit/modelprinter";
1824
2043
 
@@ -1976,14 +2195,14 @@ function SheetMetal({ color = "#737e8f", ...props }) {
1976
2195
  }
1977
2196
 
1978
2197
  // lib/models/sheetmetal/register.tsx
1979
- var model7 = defineModelRenderer({
2198
+ var model8 = defineModelRenderer({
1980
2199
  name: "sheetmetal",
1981
2200
  schema: sheetMetalModelDefinitionSchema,
1982
2201
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SheetMetal, { ...props }),
1983
2202
  pads: "none"
1984
2203
  });
1985
- function register7(registry) {
1986
- registry.register(model7);
2204
+ function register8(registry) {
2205
+ registry.register(model8);
1987
2206
  }
1988
2207
 
1989
2208
  // lib/models/spurgear/register.tsx
@@ -1998,14 +2217,14 @@ function SpurGear({ color = "#737e8f", ...props }) {
1998
2217
  }
1999
2218
 
2000
2219
  // lib/models/spurgear/register.tsx
2001
- var model8 = defineModelRenderer({
2220
+ var model9 = defineModelRenderer({
2002
2221
  name: "spurgear",
2003
2222
  schema: spurGearModelDefinitionSchema,
2004
2223
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SpurGear, { ...props }),
2005
2224
  pads: "none"
2006
2225
  });
2007
- function register8(registry) {
2008
- registry.register(model8);
2226
+ function register9(registry) {
2227
+ registry.register(model9);
2009
2228
  }
2010
2229
 
2011
2230
  // lib/models/wormgear/register.tsx
@@ -2197,14 +2416,14 @@ function WormGear({ color = "#737e8f", ...props }) {
2197
2416
  }
2198
2417
 
2199
2418
  // lib/models/wormgear/register.tsx
2200
- var model9 = defineModelRenderer({
2419
+ var model10 = defineModelRenderer({
2201
2420
  name: "wormgear",
2202
2421
  schema: wormGearModelDefinitionSchema,
2203
2422
  render: ({ fn, ...props }) => /* @__PURE__ */ jsx(WormGear, { ...props }),
2204
2423
  pads: "none"
2205
2424
  });
2206
- function register9(registry) {
2207
- registry.register(model9);
2425
+ function register10(registry) {
2426
+ registry.register(model10);
2208
2427
  }
2209
2428
 
2210
2429
  // lib/generated/model-renderers.ts
@@ -2218,6 +2437,7 @@ function registerAllModelRenderers(registry) {
2218
2437
  register7(registry);
2219
2438
  register8(registry);
2220
2439
  register9(registry);
2440
+ register10(registry);
2221
2441
  }
2222
2442
 
2223
2443
  // lib/default-model-registry.ts
@@ -9774,10 +9994,10 @@ var SOT143 = ({ footprint = "sot143" }) => {
9774
9994
  var Footprinter3d = ({ footprint }) => {
9775
9995
  const modelFn = mp3.string(footprint.split("_", 1)[0]).params().fn;
9776
9996
  if (mp3.getModelNames().includes(modelFn)) {
9777
- const model10 = mp3.string(footprint).json();
9778
- const renderer = modelRendererRegistry.get(model10.fn);
9997
+ const model11 = mp3.string(footprint).json();
9998
+ const renderer = modelRendererRegistry.get(model11.fn);
9779
9999
  if (renderer) {
9780
- return renderer.render(model10);
10000
+ return renderer.render(model11);
9781
10001
  }
9782
10002
  }
9783
10003
  let normalizedFootprint = footprint;
@@ -10737,6 +10957,7 @@ export {
10737
10957
  NEMA23,
10738
10958
  NEMA8,
10739
10959
  NemaMotor,
10960
+ PanScrew,
10740
10961
  SheetMetal,
10741
10962
  SpurGear,
10742
10963
  WormGear,
@@ -10750,6 +10971,8 @@ export {
10750
10971
  createHexSocketBoltGeom,
10751
10972
  createHexSocketBoltMesh,
10752
10973
  createJSCADRenderer,
10974
+ createPanScrewGeom,
10975
+ createPanScrewMesh,
10753
10976
  createSheetMetalGeom,
10754
10977
  createSheetMetalMesh,
10755
10978
  createSpurGearGeom,