jscad-electronics 0.0.185 → 0.0.186
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 +16 -2
- package/dist/index.js +1072 -1011
- package/dist/index.js.map +1 -1
- package/dist/vanilla.d.ts +16 -2
- package/dist/vanilla.js +231 -172
- package/dist/vanilla.js.map +1 -1
- package/package.json +2 -2
package/dist/vanilla.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BufferGeometry } from 'three';
|
|
2
2
|
import * as jscadModeling from '@jscad/modeling';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
-
import { NemaMotorModelPropsInput, HexSocketBoltModelPropsInput, SheetMetalModelPropsInput, SpurGearModelPropsInput, WormGearModelPropsInput } from '@tscircuit/modelprinter';
|
|
4
|
+
import { NemaMotorModelPropsInput, HexSocketBoltModelPropsInput, SheetMetalModelPropsInput, SpurGearModelPropsInput, HelicalGearModelPropsInput, WormGearModelPropsInput } from '@tscircuit/modelprinter';
|
|
5
5
|
import * as _jscad_modeling_src_geometries_types from '@jscad/modeling/src/geometries/types';
|
|
6
6
|
|
|
7
7
|
type VNode = {
|
|
@@ -93,6 +93,20 @@ interface SpurGearMesh {
|
|
|
93
93
|
*/
|
|
94
94
|
declare function createSpurGearMesh(input: SpurGearModelPropsInput): SpurGearMesh;
|
|
95
95
|
|
|
96
|
+
type HelicalGearMesh = SpurGearMesh;
|
|
97
|
+
/**
|
|
98
|
+
* Twisted transverse involute teeth from Z=0 to faceWidth, with a stationary
|
|
99
|
+
* round bore and optional hub. Zero helix angle reproduces the spur mesh.
|
|
100
|
+
*/
|
|
101
|
+
declare function createHelicalGearMesh(input: HelicalGearModelPropsInput): HelicalGearMesh;
|
|
102
|
+
|
|
103
|
+
type HelicalGearProps = HelicalGearModelPropsInput & {
|
|
104
|
+
color?: string;
|
|
105
|
+
};
|
|
106
|
+
/** Axis +Z, lower face Z=0; optional hub extends above the gear face. */
|
|
107
|
+
declare function createHelicalGearGeom(input: HelicalGearModelPropsInput): _jscad_modeling_src_geometries_types.Geom3;
|
|
108
|
+
declare function HelicalGear({ color, ...props }: HelicalGearProps): react_jsx_runtime.JSX.Element;
|
|
109
|
+
|
|
96
110
|
type SpurGearProps = SpurGearModelPropsInput & {
|
|
97
111
|
color?: string;
|
|
98
112
|
};
|
|
@@ -128,4 +142,4 @@ declare function createJSCADRenderer(jscad: typeof jscadModeling): {
|
|
|
128
142
|
};
|
|
129
143
|
};
|
|
130
144
|
|
|
131
|
-
export { type ColoredGeom, Fragment, 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, createHexSocketBoltGeom, createHexSocketBoltMesh, createJSCADRenderer, createSheetMetalGeom, createSheetMetalMesh, createSpurGearGeom, createSpurGearMesh, createWormGearGeom, createWormGearMesh, getJscadModelForFootprint, getJscadModelForFootprintWithPads, h };
|
|
145
|
+
export { type ColoredGeom, Fragment, HelicalGear, type HelicalGearMesh, type HelicalGearProps, 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, createHelicalGearGeom, createHelicalGearMesh, createHexSocketBoltGeom, createHexSocketBoltMesh, createJSCADRenderer, createSheetMetalGeom, createSheetMetalMesh, createSpurGearGeom, createSpurGearMesh, createWormGearGeom, createWormGearMesh, getJscadModelForFootprint, getJscadModelForFootprintWithPads, h };
|
package/dist/vanilla.js
CHANGED
|
@@ -172,9 +172,14 @@ var ExtrudedPads = ({
|
|
|
172
172
|
circuitJson,
|
|
173
173
|
footprint
|
|
174
174
|
}) => {
|
|
175
|
-
if (!circuitJson && footprint && [
|
|
176
|
-
|
|
177
|
-
|
|
175
|
+
if (!circuitJson && footprint && [
|
|
176
|
+
"nema",
|
|
177
|
+
"hexsocketbolt",
|
|
178
|
+
"sheetmetal",
|
|
179
|
+
"spurgear",
|
|
180
|
+
"wormgear",
|
|
181
|
+
"helicalgear"
|
|
182
|
+
].includes(mp.string(footprint.split("_", 1)[0]).params().fn)) {
|
|
178
183
|
mp.string(footprint).json();
|
|
179
184
|
return null;
|
|
180
185
|
}
|
|
@@ -201,6 +206,220 @@ var ExtrudedPads = ({
|
|
|
201
206
|
] });
|
|
202
207
|
};
|
|
203
208
|
|
|
209
|
+
// lib/mechanical/indexedMeshToGeom3.ts
|
|
210
|
+
import jscad from "@jscad/modeling";
|
|
211
|
+
function indexedMeshToGeom3(mesh) {
|
|
212
|
+
const polygons = [];
|
|
213
|
+
for (let i = 0; i < mesh.indices.length; i += 3)
|
|
214
|
+
polygons.push(
|
|
215
|
+
mesh.indices.slice(i, i + 3).map((index) => [
|
|
216
|
+
mesh.positions[index * 3],
|
|
217
|
+
mesh.positions[index * 3 + 1],
|
|
218
|
+
mesh.positions[index * 3 + 2]
|
|
219
|
+
])
|
|
220
|
+
);
|
|
221
|
+
return jscad.geometries.geom3.fromPoints(polygons);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// lib/mechanical/helical-gear-mesh.ts
|
|
225
|
+
import {
|
|
226
|
+
getHelicalGearDimensions,
|
|
227
|
+
helicalGearModelPropsSchema
|
|
228
|
+
} from "@tscircuit/modelprinter";
|
|
229
|
+
|
|
230
|
+
// lib/mechanical/spur-gear-mesh.ts
|
|
231
|
+
import {
|
|
232
|
+
getSpurGearDimensions,
|
|
233
|
+
spurGearModelPropsSchema
|
|
234
|
+
} from "@tscircuit/modelprinter";
|
|
235
|
+
import earcut from "earcut";
|
|
236
|
+
function createSpurGearMesh(input) {
|
|
237
|
+
return createTwistedSpurGearMesh(input);
|
|
238
|
+
}
|
|
239
|
+
function createTwistedSpurGearMesh(input, twist = 0, segmentsPerTurn = 32) {
|
|
240
|
+
const props = spurGearModelPropsSchema.parse(input);
|
|
241
|
+
const dimensions = getSpurGearDimensions(props);
|
|
242
|
+
const pitchRadius = dimensions.pitchDiameter / 2;
|
|
243
|
+
const baseRadius = dimensions.baseDiameter / 2;
|
|
244
|
+
const outsideRadius = dimensions.outsideDiameter / 2;
|
|
245
|
+
const rootRadius = dimensions.rootDiameter / 2;
|
|
246
|
+
const pressureAngle = props.pressureAngle * Math.PI / 180;
|
|
247
|
+
const toothAngle = Math.PI * 2 / props.toothCount;
|
|
248
|
+
const phase = (props.phase % 360 + 360) % 360 * (Math.PI / 180);
|
|
249
|
+
const baseHalfAngle = dimensions.toothThickness / (2 * pitchRadius) + Math.tan(pressureAngle) - pressureAngle;
|
|
250
|
+
const startRadius = Math.max(baseRadius, rootRadius);
|
|
251
|
+
const startT = Math.sqrt(Math.max(0, (startRadius / baseRadius) ** 2 - 1));
|
|
252
|
+
const outsideT = Math.sqrt((outsideRadius / baseRadius) ** 2 - 1);
|
|
253
|
+
const halfAngle = (t) => baseHalfAngle - (t - Math.atan(t));
|
|
254
|
+
const rootHalfAngle = halfAngle(startT);
|
|
255
|
+
const tipHalfAngle = halfAngle(outsideT);
|
|
256
|
+
const flankSteps = Math.max(2, Math.ceil(props.segmentsPerTooth / 2));
|
|
257
|
+
const arcSteps = Math.max(1, Math.ceil(props.segmentsPerTooth / 4));
|
|
258
|
+
const rootValleyAngle = toothAngle - 2 * rootHalfAngle;
|
|
259
|
+
const innerRadius = Math.max(props.boreDiameter, props.hubDiameter) / 2;
|
|
260
|
+
const safeRootStep = innerRadius > 0 ? (twist === 0 ? 1.8 : 0.8) * Math.acos(innerRadius / rootRadius) : Math.PI;
|
|
261
|
+
const rootArcSteps = Math.max(
|
|
262
|
+
arcSteps,
|
|
263
|
+
Math.ceil(rootValleyAngle / safeRootStep)
|
|
264
|
+
);
|
|
265
|
+
const twistStep = Math.min(
|
|
266
|
+
toothAngle / 16,
|
|
267
|
+
2 * Math.PI / segmentsPerTurn,
|
|
268
|
+
safeRootStep
|
|
269
|
+
);
|
|
270
|
+
const layers = Math.max(1, Math.ceil(Math.abs(twist) / twistStep));
|
|
271
|
+
const pointsPerTooth = 2 * flankSteps + arcSteps + rootArcSteps + (rootRadius < baseRadius ? 2 : 0);
|
|
272
|
+
if (!Number.isFinite(rootArcSteps) || !Number.isFinite(layers) || (layers + 1) * props.toothCount * pointsPerTooth + 1024 > 1e6)
|
|
273
|
+
throw new Error(
|
|
274
|
+
"Involute gear exceeds mesh resolution limit (1 million vertices); reduce twist or resolution, or increase bore/hub wall thickness"
|
|
275
|
+
);
|
|
276
|
+
const outline = [];
|
|
277
|
+
const polar = (radius, angle) => {
|
|
278
|
+
outline.push([radius * Math.cos(angle), radius * Math.sin(angle)]);
|
|
279
|
+
};
|
|
280
|
+
for (let tooth = 0; tooth < props.toothCount; tooth++) {
|
|
281
|
+
const center = phase + tooth * toothAngle;
|
|
282
|
+
polar(rootRadius, center - rootHalfAngle);
|
|
283
|
+
if (rootRadius < baseRadius) polar(baseRadius, center - baseHalfAngle);
|
|
284
|
+
for (let step = 1; step <= flankSteps; step++) {
|
|
285
|
+
const t = startT + (outsideT - startT) * step / flankSteps;
|
|
286
|
+
polar(baseRadius * Math.sqrt(1 + t * t), center - halfAngle(t));
|
|
287
|
+
}
|
|
288
|
+
for (let step = 1; step <= arcSteps; step++)
|
|
289
|
+
polar(
|
|
290
|
+
outsideRadius,
|
|
291
|
+
center - tipHalfAngle + 2 * tipHalfAngle * step / arcSteps
|
|
292
|
+
);
|
|
293
|
+
for (let step = flankSteps - 1; step >= 0; step--) {
|
|
294
|
+
const t = startT + (outsideT - startT) * step / flankSteps;
|
|
295
|
+
polar(baseRadius * Math.sqrt(1 + t * t), center + halfAngle(t));
|
|
296
|
+
}
|
|
297
|
+
if (rootRadius < baseRadius) polar(rootRadius, center + baseHalfAngle);
|
|
298
|
+
for (let step = 1; step < rootArcSteps; step++)
|
|
299
|
+
polar(
|
|
300
|
+
rootRadius,
|
|
301
|
+
center + rootHalfAngle + rootValleyAngle * step / rootArcSteps
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
const positions = [];
|
|
305
|
+
const indices = [];
|
|
306
|
+
const ring = (points, z) => {
|
|
307
|
+
const start = positions.length / 3;
|
|
308
|
+
for (const [x, y] of points) positions.push(x, y, z);
|
|
309
|
+
return start;
|
|
310
|
+
};
|
|
311
|
+
const circleSegments = Math.max(48, Math.min(256, props.toothCount * 4));
|
|
312
|
+
const circle2 = (radius) => Array.from({ length: circleSegments }, (_, segment) => {
|
|
313
|
+
const angle = phase + segment * Math.PI * 2 / circleSegments;
|
|
314
|
+
return [radius * Math.cos(angle), radius * Math.sin(angle)];
|
|
315
|
+
});
|
|
316
|
+
const connect = (bottom2, top2, count, inward = false) => {
|
|
317
|
+
for (let i = 0; i < count; i++) {
|
|
318
|
+
const next = (i + 1) % count;
|
|
319
|
+
if (inward)
|
|
320
|
+
indices.push(
|
|
321
|
+
bottom2 + i,
|
|
322
|
+
top2 + next,
|
|
323
|
+
bottom2 + next,
|
|
324
|
+
bottom2 + i,
|
|
325
|
+
top2 + i,
|
|
326
|
+
top2 + next
|
|
327
|
+
);
|
|
328
|
+
else
|
|
329
|
+
indices.push(
|
|
330
|
+
bottom2 + i,
|
|
331
|
+
bottom2 + next,
|
|
332
|
+
top2 + next,
|
|
333
|
+
bottom2 + i,
|
|
334
|
+
top2 + next,
|
|
335
|
+
top2 + i
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
const cap = (outer, outerStart, upward, inner) => {
|
|
340
|
+
const points = inner ? [...outer, ...inner.points] : outer;
|
|
341
|
+
const triangles = earcut(
|
|
342
|
+
points.flatMap(([x, y]) => [x, y]),
|
|
343
|
+
inner ? [outer.length] : []
|
|
344
|
+
);
|
|
345
|
+
const vertex = (index) => index < outer.length ? outerStart + index : inner.start + index - outer.length;
|
|
346
|
+
for (let i = 0; i < triangles.length; i += 3) {
|
|
347
|
+
const a = triangles[i];
|
|
348
|
+
const b = triangles[i + 1];
|
|
349
|
+
const c = triangles[i + 2];
|
|
350
|
+
const pa = points[a];
|
|
351
|
+
const pb = points[b];
|
|
352
|
+
const pc = points[c];
|
|
353
|
+
const area = (pb[0] - pa[0]) * (pc[1] - pa[1]) - (pb[1] - pa[1]) * (pc[0] - pa[0]);
|
|
354
|
+
if (area > 0 === upward) indices.push(vertex(a), vertex(b), vertex(c));
|
|
355
|
+
else indices.push(vertex(a), vertex(c), vertex(b));
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
const bottom = ring(outline, 0);
|
|
359
|
+
let top = bottom;
|
|
360
|
+
let topOutline = outline;
|
|
361
|
+
for (let layer = 1; layer <= layers; layer++) {
|
|
362
|
+
const angle = twist * (layer / layers);
|
|
363
|
+
topOutline = twist === 0 ? outline : outline.map(
|
|
364
|
+
([x, y]) => [
|
|
365
|
+
x * Math.cos(angle) - y * Math.sin(angle),
|
|
366
|
+
x * Math.sin(angle) + y * Math.cos(angle)
|
|
367
|
+
]
|
|
368
|
+
);
|
|
369
|
+
const next = ring(topOutline, props.faceWidth * (layer / layers));
|
|
370
|
+
connect(top, next, outline.length);
|
|
371
|
+
top = next;
|
|
372
|
+
}
|
|
373
|
+
const hasHub = props.hubDiameter > 0 && props.hubLength > 0;
|
|
374
|
+
const height10 = props.faceWidth + (hasHub ? props.hubLength : 0);
|
|
375
|
+
const bore = props.boreDiameter > 0 ? circle2(props.boreDiameter / 2) : void 0;
|
|
376
|
+
const boreBottom = bore ? ring(bore, 0) : void 0;
|
|
377
|
+
const boreTop = bore ? ring(bore, height10) : void 0;
|
|
378
|
+
if (bore) connect(boreBottom, boreTop, bore.length, true);
|
|
379
|
+
cap(
|
|
380
|
+
outline,
|
|
381
|
+
bottom,
|
|
382
|
+
false,
|
|
383
|
+
bore ? { points: bore, start: boreBottom } : void 0
|
|
384
|
+
);
|
|
385
|
+
if (hasHub) {
|
|
386
|
+
const hub = circle2(props.hubDiameter / 2);
|
|
387
|
+
const hubBottom = ring(hub, props.faceWidth);
|
|
388
|
+
const hubTop = ring(hub, height10);
|
|
389
|
+
cap(topOutline, top, true, { points: hub, start: hubBottom });
|
|
390
|
+
connect(hubBottom, hubTop, hub.length);
|
|
391
|
+
if (bore) connect(hubTop, boreTop, hub.length);
|
|
392
|
+
else cap(hub, hubTop, true);
|
|
393
|
+
} else
|
|
394
|
+
cap(
|
|
395
|
+
topOutline,
|
|
396
|
+
top,
|
|
397
|
+
true,
|
|
398
|
+
bore ? { points: bore, start: boreTop } : void 0
|
|
399
|
+
);
|
|
400
|
+
return { positions, indices };
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// lib/mechanical/helical-gear-mesh.ts
|
|
404
|
+
function createHelicalGearMesh(input) {
|
|
405
|
+
const props = helicalGearModelPropsSchema.parse(input);
|
|
406
|
+
const { twistAngle } = getHelicalGearDimensions(props);
|
|
407
|
+
const { helixAngle, handedness, segmentsPerTurn, ...spur } = props;
|
|
408
|
+
return createTwistedSpurGearMesh(
|
|
409
|
+
spur,
|
|
410
|
+
twistAngle * Math.PI / 180,
|
|
411
|
+
segmentsPerTurn
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// lib/HelicalGear.tsx
|
|
416
|
+
function createHelicalGearGeom(input) {
|
|
417
|
+
return indexedMeshToGeom3(createHelicalGearMesh(input));
|
|
418
|
+
}
|
|
419
|
+
function HelicalGear({ color = "#737e8f", ...props }) {
|
|
420
|
+
return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsx(Custom, { geometry: createHelicalGearGeom(props) }) });
|
|
421
|
+
}
|
|
422
|
+
|
|
204
423
|
// lib/mechanical/hex-socket-bolt-mesh.ts
|
|
205
424
|
import {
|
|
206
425
|
hexSocketBoltDimensions,
|
|
@@ -295,21 +514,6 @@ var createHexSocketBoltMesh = (input) => {
|
|
|
295
514
|
return { positions, indices };
|
|
296
515
|
};
|
|
297
516
|
|
|
298
|
-
// lib/mechanical/indexedMeshToGeom3.ts
|
|
299
|
-
import jscad from "@jscad/modeling";
|
|
300
|
-
function indexedMeshToGeom3(mesh) {
|
|
301
|
-
const polygons = [];
|
|
302
|
-
for (let i = 0; i < mesh.indices.length; i += 3)
|
|
303
|
-
polygons.push(
|
|
304
|
-
mesh.indices.slice(i, i + 3).map((index) => [
|
|
305
|
-
mesh.positions[index * 3],
|
|
306
|
-
mesh.positions[index * 3 + 1],
|
|
307
|
-
mesh.positions[index * 3 + 2]
|
|
308
|
-
])
|
|
309
|
-
);
|
|
310
|
-
return jscad.geometries.geom3.fromPoints(polygons);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
517
|
// lib/HexSocketBolt.tsx
|
|
314
518
|
function createHexSocketBoltGeom(input) {
|
|
315
519
|
return indexedMeshToGeom3(createHexSocketBoltMesh(input));
|
|
@@ -322,7 +526,7 @@ function HexSocketBolt({
|
|
|
322
526
|
}
|
|
323
527
|
|
|
324
528
|
// lib/mechanical/sheet-metal-mesh.ts
|
|
325
|
-
import
|
|
529
|
+
import earcut2 from "earcut";
|
|
326
530
|
import {
|
|
327
531
|
sheetMetalModelPropsSchema
|
|
328
532
|
} from "@tscircuit/modelprinter";
|
|
@@ -390,7 +594,7 @@ function createSheetMetalMesh(input) {
|
|
|
390
594
|
const loops = [outline, ...holes.map((hole) => [...hole].reverse())];
|
|
391
595
|
const points = loops.flat();
|
|
392
596
|
const starts = holes.map((_, i) => 4 + i * 64);
|
|
393
|
-
const triangles =
|
|
597
|
+
const triangles = earcut2(
|
|
394
598
|
points.flatMap((p) => [p.u, p.v]),
|
|
395
599
|
starts
|
|
396
600
|
);
|
|
@@ -474,158 +678,6 @@ function SheetMetal({ color = "#737e8f", ...props }) {
|
|
|
474
678
|
return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsx(Custom, { geometry: createSheetMetalGeom(props) }) });
|
|
475
679
|
}
|
|
476
680
|
|
|
477
|
-
// lib/mechanical/spur-gear-mesh.ts
|
|
478
|
-
import {
|
|
479
|
-
getSpurGearDimensions,
|
|
480
|
-
spurGearModelPropsSchema
|
|
481
|
-
} from "@tscircuit/modelprinter";
|
|
482
|
-
import earcut2 from "earcut";
|
|
483
|
-
function createSpurGearMesh(input) {
|
|
484
|
-
const props = spurGearModelPropsSchema.parse(input);
|
|
485
|
-
const dimensions = getSpurGearDimensions(props);
|
|
486
|
-
const pitchRadius = dimensions.pitchDiameter / 2;
|
|
487
|
-
const baseRadius = dimensions.baseDiameter / 2;
|
|
488
|
-
const outsideRadius = dimensions.outsideDiameter / 2;
|
|
489
|
-
const rootRadius = dimensions.rootDiameter / 2;
|
|
490
|
-
const pressureAngle = props.pressureAngle * Math.PI / 180;
|
|
491
|
-
const toothAngle = Math.PI * 2 / props.toothCount;
|
|
492
|
-
const phase = (props.phase % 360 + 360) % 360 * (Math.PI / 180);
|
|
493
|
-
const baseHalfAngle = dimensions.toothThickness / (2 * pitchRadius) + Math.tan(pressureAngle) - pressureAngle;
|
|
494
|
-
const startRadius = Math.max(baseRadius, rootRadius);
|
|
495
|
-
const startT = Math.sqrt(Math.max(0, (startRadius / baseRadius) ** 2 - 1));
|
|
496
|
-
const outsideT = Math.sqrt((outsideRadius / baseRadius) ** 2 - 1);
|
|
497
|
-
const halfAngle = (t) => baseHalfAngle - (t - Math.atan(t));
|
|
498
|
-
const rootHalfAngle = halfAngle(startT);
|
|
499
|
-
const tipHalfAngle = halfAngle(outsideT);
|
|
500
|
-
const flankSteps = Math.max(2, Math.ceil(props.segmentsPerTooth / 2));
|
|
501
|
-
const arcSteps = Math.max(1, Math.ceil(props.segmentsPerTooth / 4));
|
|
502
|
-
const rootValleyAngle = toothAngle - 2 * rootHalfAngle;
|
|
503
|
-
const innerRadius = Math.max(props.boreDiameter, props.hubDiameter) / 2;
|
|
504
|
-
const safeRootStep = innerRadius > 0 ? 1.8 * Math.acos(innerRadius / rootRadius) : Math.PI;
|
|
505
|
-
const rootArcSteps = Math.max(
|
|
506
|
-
arcSteps,
|
|
507
|
-
Math.ceil(rootValleyAngle / safeRootStep)
|
|
508
|
-
);
|
|
509
|
-
const pointsPerTooth = 2 * flankSteps + arcSteps + rootArcSteps + (rootRadius < baseRadius ? 2 : 0);
|
|
510
|
-
if (!Number.isFinite(rootArcSteps) || 2 * props.toothCount * pointsPerTooth + 1024 > 1e6)
|
|
511
|
-
throw new Error(
|
|
512
|
-
"Spur gear bore or hub clearance exceeds mesh resolution limit (1 million vertices)"
|
|
513
|
-
);
|
|
514
|
-
const outline = [];
|
|
515
|
-
const polar = (radius, angle) => {
|
|
516
|
-
outline.push([radius * Math.cos(angle), radius * Math.sin(angle)]);
|
|
517
|
-
};
|
|
518
|
-
for (let tooth = 0; tooth < props.toothCount; tooth++) {
|
|
519
|
-
const center = phase + tooth * toothAngle;
|
|
520
|
-
polar(rootRadius, center - rootHalfAngle);
|
|
521
|
-
if (rootRadius < baseRadius) polar(baseRadius, center - baseHalfAngle);
|
|
522
|
-
for (let step = 1; step <= flankSteps; step++) {
|
|
523
|
-
const t = startT + (outsideT - startT) * step / flankSteps;
|
|
524
|
-
polar(baseRadius * Math.sqrt(1 + t * t), center - halfAngle(t));
|
|
525
|
-
}
|
|
526
|
-
for (let step = 1; step <= arcSteps; step++)
|
|
527
|
-
polar(
|
|
528
|
-
outsideRadius,
|
|
529
|
-
center - tipHalfAngle + 2 * tipHalfAngle * step / arcSteps
|
|
530
|
-
);
|
|
531
|
-
for (let step = flankSteps - 1; step >= 0; step--) {
|
|
532
|
-
const t = startT + (outsideT - startT) * step / flankSteps;
|
|
533
|
-
polar(baseRadius * Math.sqrt(1 + t * t), center + halfAngle(t));
|
|
534
|
-
}
|
|
535
|
-
if (rootRadius < baseRadius) polar(rootRadius, center + baseHalfAngle);
|
|
536
|
-
for (let step = 1; step < rootArcSteps; step++)
|
|
537
|
-
polar(
|
|
538
|
-
rootRadius,
|
|
539
|
-
center + rootHalfAngle + rootValleyAngle * step / rootArcSteps
|
|
540
|
-
);
|
|
541
|
-
}
|
|
542
|
-
const positions = [];
|
|
543
|
-
const indices = [];
|
|
544
|
-
const ring = (points, z) => {
|
|
545
|
-
const start = positions.length / 3;
|
|
546
|
-
for (const [x, y] of points) positions.push(x, y, z);
|
|
547
|
-
return start;
|
|
548
|
-
};
|
|
549
|
-
const circleSegments = Math.max(48, Math.min(256, props.toothCount * 4));
|
|
550
|
-
const circle2 = (radius) => Array.from({ length: circleSegments }, (_, segment) => {
|
|
551
|
-
const angle = phase + segment * Math.PI * 2 / circleSegments;
|
|
552
|
-
return [radius * Math.cos(angle), radius * Math.sin(angle)];
|
|
553
|
-
});
|
|
554
|
-
const connect = (bottom2, top2, count, inward = false) => {
|
|
555
|
-
for (let i = 0; i < count; i++) {
|
|
556
|
-
const next = (i + 1) % count;
|
|
557
|
-
if (inward)
|
|
558
|
-
indices.push(
|
|
559
|
-
bottom2 + i,
|
|
560
|
-
top2 + next,
|
|
561
|
-
bottom2 + next,
|
|
562
|
-
bottom2 + i,
|
|
563
|
-
top2 + i,
|
|
564
|
-
top2 + next
|
|
565
|
-
);
|
|
566
|
-
else
|
|
567
|
-
indices.push(
|
|
568
|
-
bottom2 + i,
|
|
569
|
-
bottom2 + next,
|
|
570
|
-
top2 + next,
|
|
571
|
-
bottom2 + i,
|
|
572
|
-
top2 + next,
|
|
573
|
-
top2 + i
|
|
574
|
-
);
|
|
575
|
-
}
|
|
576
|
-
};
|
|
577
|
-
const cap = (outer, outerStart, upward, inner) => {
|
|
578
|
-
const points = inner ? [...outer, ...inner.points] : outer;
|
|
579
|
-
const triangles = earcut2(
|
|
580
|
-
points.flatMap(([x, y]) => [x, y]),
|
|
581
|
-
inner ? [outer.length] : []
|
|
582
|
-
);
|
|
583
|
-
const vertex = (index) => index < outer.length ? outerStart + index : inner.start + index - outer.length;
|
|
584
|
-
for (let i = 0; i < triangles.length; i += 3) {
|
|
585
|
-
const a = triangles[i];
|
|
586
|
-
const b = triangles[i + 1];
|
|
587
|
-
const c = triangles[i + 2];
|
|
588
|
-
const pa = points[a];
|
|
589
|
-
const pb = points[b];
|
|
590
|
-
const pc = points[c];
|
|
591
|
-
const area = (pb[0] - pa[0]) * (pc[1] - pa[1]) - (pb[1] - pa[1]) * (pc[0] - pa[0]);
|
|
592
|
-
if (area > 0 === upward) indices.push(vertex(a), vertex(b), vertex(c));
|
|
593
|
-
else indices.push(vertex(a), vertex(c), vertex(b));
|
|
594
|
-
}
|
|
595
|
-
};
|
|
596
|
-
const bottom = ring(outline, 0);
|
|
597
|
-
const top = ring(outline, props.faceWidth);
|
|
598
|
-
connect(bottom, top, outline.length);
|
|
599
|
-
const hasHub = props.hubDiameter > 0 && props.hubLength > 0;
|
|
600
|
-
const height10 = props.faceWidth + (hasHub ? props.hubLength : 0);
|
|
601
|
-
const bore = props.boreDiameter > 0 ? circle2(props.boreDiameter / 2) : void 0;
|
|
602
|
-
const boreBottom = bore ? ring(bore, 0) : void 0;
|
|
603
|
-
const boreTop = bore ? ring(bore, height10) : void 0;
|
|
604
|
-
if (bore) connect(boreBottom, boreTop, bore.length, true);
|
|
605
|
-
cap(
|
|
606
|
-
outline,
|
|
607
|
-
bottom,
|
|
608
|
-
false,
|
|
609
|
-
bore ? { points: bore, start: boreBottom } : void 0
|
|
610
|
-
);
|
|
611
|
-
if (hasHub) {
|
|
612
|
-
const hub = circle2(props.hubDiameter / 2);
|
|
613
|
-
const hubBottom = ring(hub, props.faceWidth);
|
|
614
|
-
const hubTop = ring(hub, height10);
|
|
615
|
-
cap(outline, top, true, { points: hub, start: hubBottom });
|
|
616
|
-
connect(hubBottom, hubTop, hub.length);
|
|
617
|
-
if (bore) connect(hubTop, boreTop, hub.length);
|
|
618
|
-
else cap(hub, hubTop, true);
|
|
619
|
-
} else
|
|
620
|
-
cap(
|
|
621
|
-
outline,
|
|
622
|
-
top,
|
|
623
|
-
true,
|
|
624
|
-
bore ? { points: bore, start: boreTop } : void 0
|
|
625
|
-
);
|
|
626
|
-
return { positions, indices };
|
|
627
|
-
}
|
|
628
|
-
|
|
629
681
|
// lib/SpurGear.tsx
|
|
630
682
|
function createSpurGearGeom(input) {
|
|
631
683
|
return indexedMeshToGeom3(createSpurGearMesh(input));
|
|
@@ -9068,6 +9120,10 @@ var Footprinter3d = ({ footprint }) => {
|
|
|
9068
9120
|
const { fn, ...props } = model;
|
|
9069
9121
|
return /* @__PURE__ */ jsx(SheetMetal, { ...props });
|
|
9070
9122
|
}
|
|
9123
|
+
case "helicalgear": {
|
|
9124
|
+
const { fn, ...props } = model;
|
|
9125
|
+
return /* @__PURE__ */ jsx(HelicalGear, { ...props });
|
|
9126
|
+
}
|
|
9071
9127
|
case "spurgear": {
|
|
9072
9128
|
const { fn, ...props } = model;
|
|
9073
9129
|
return /* @__PURE__ */ jsx(SpurGear, { ...props });
|
|
@@ -9997,6 +10053,7 @@ function createJSCADRenderer(jscad4) {
|
|
|
9997
10053
|
}
|
|
9998
10054
|
export {
|
|
9999
10055
|
Fragment,
|
|
10056
|
+
HelicalGear,
|
|
10000
10057
|
HexSocketBolt,
|
|
10001
10058
|
NEMA17,
|
|
10002
10059
|
NEMA23,
|
|
@@ -10006,6 +10063,8 @@ export {
|
|
|
10006
10063
|
SpurGear,
|
|
10007
10064
|
WormGear,
|
|
10008
10065
|
convertCSGToThreeGeom,
|
|
10066
|
+
createHelicalGearGeom,
|
|
10067
|
+
createHelicalGearMesh,
|
|
10009
10068
|
createHexSocketBoltGeom,
|
|
10010
10069
|
createHexSocketBoltMesh,
|
|
10011
10070
|
createJSCADRenderer,
|