jscad-electronics 0.0.204 → 0.0.206
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 +33 -2
- package/dist/index.js +1225 -858
- package/dist/index.js.map +1 -1
- package/dist/vanilla.d.ts +33 -2
- package/dist/vanilla.js +391 -34
- package/dist/vanilla.js.map +1 -1
- package/package.json +1 -1
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 { ButtonScrewModelPropsInput, CableGrommetModelPropsInput, CompressionSpringModelPropsInput, FlangedBushingModelPropsInput, FlatHeadScrewModelPropsInput, SpurGearModelPropsInput, HelicalGearModelPropsInput, HexBoltModelPropsInput, HexNutModelPropsInput, HexSocketBoltModelPropsInput, NemaMotorModelPropsInput, PanScrewModelPropsInput, PlainBushingModelPropsInput, SheetMetalModelPropsInput, TSlotExtrusionModelPropsInput, TSlotInsideCornerModelPropsInput, WormGearModelPropsInput } from '@tscircuit/modelprinter';
|
|
6
|
+
import { ButtonScrewModelPropsInput, CableGrommetModelPropsInput, CompressionSpringModelPropsInput, FlangedBushingModelPropsInput, FlatHeadScrewModelPropsInput, SpurGearModelPropsInput, HelicalGearModelPropsInput, HexBoltModelPropsInput, HexNutModelPropsInput, HexSocketBoltModelPropsInput, NemaMotorModelPropsInput, PanScrewModelPropsInput, PlainBushingModelPropsInput, ShaftCollarModelPropsInput, SheetMetalModelPropsInput, TSlotExtrusionModelPropsInput, TSlotGussetModelPropsInput, TSlotInsideCornerModelPropsInput, WormGearModelPropsInput } from '@tscircuit/modelprinter';
|
|
7
7
|
|
|
8
8
|
type VNode = {
|
|
9
9
|
type: any;
|
|
@@ -243,6 +243,22 @@ type PlainBushingProps = PlainBushingModelPropsInput & {
|
|
|
243
243
|
declare function createPlainBushingGeom(input: PlainBushingModelPropsInput): _jscad_modeling_src_geometries_types.Geom3;
|
|
244
244
|
declare function PlainBushing({ color, ...props }: PlainBushingProps): react_jsx_runtime.JSX.Element;
|
|
245
245
|
|
|
246
|
+
type ShaftMountMesh = {
|
|
247
|
+
positions: number[];
|
|
248
|
+
indices: number[];
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
type ShaftCollarMesh = ShaftMountMesh;
|
|
252
|
+
/** Geometry is driven by the corresponding modelprinter schema and hole layout. */
|
|
253
|
+
declare function createShaftCollarMesh(input: ShaftCollarModelPropsInput): ShaftCollarMesh;
|
|
254
|
+
|
|
255
|
+
type ShaftCollarProps = ShaftCollarModelPropsInput & {
|
|
256
|
+
color?: string;
|
|
257
|
+
};
|
|
258
|
+
/** Datum and mounting-hole coordinates follow the modelprinter contract. */
|
|
259
|
+
declare function createShaftCollarGeom(input: ShaftCollarModelPropsInput): _jscad_modeling_src_geometries_types.Geom3;
|
|
260
|
+
declare function ShaftCollar({ color, ...props }: ShaftCollarProps): react_jsx_runtime.JSX.Element;
|
|
261
|
+
|
|
246
262
|
interface SheetMetalMesh {
|
|
247
263
|
positions: number[];
|
|
248
264
|
indices: number[];
|
|
@@ -284,6 +300,21 @@ type TSlotExtrusionProps = TSlotExtrusionModelPropsInput & {
|
|
|
284
300
|
declare function createTSlotExtrusionGeom(input?: TSlotExtrusionModelPropsInput): _jscad_modeling_src_geometries_types.Geom3;
|
|
285
301
|
declare function TSlotExtrusion({ color, ...props }: TSlotExtrusionProps): react_jsx_runtime.JSX.Element;
|
|
286
302
|
|
|
303
|
+
interface TSlotGussetMesh {
|
|
304
|
+
positions: number[];
|
|
305
|
+
indices: number[];
|
|
306
|
+
}
|
|
307
|
+
/** Right triangular flat plate at Z=0..thickness, with both complete through
|
|
308
|
+
* capsules at the mounting centers/orientations resolved by modelprinter.
|
|
309
|
+
*/
|
|
310
|
+
declare function createTSlotGussetMesh(input?: TSlotGussetModelPropsInput): TSlotGussetMesh;
|
|
311
|
+
|
|
312
|
+
type TSlotGussetProps = TSlotGussetModelPropsInput & {
|
|
313
|
+
color?: string;
|
|
314
|
+
};
|
|
315
|
+
declare function createTSlotGussetGeom(input?: TSlotGussetModelPropsInput): _jscad_modeling_src_geometries_types.Geom3;
|
|
316
|
+
declare function TSlotGusset({ color, ...props }: TSlotGussetProps): react_jsx_runtime.JSX.Element;
|
|
317
|
+
|
|
287
318
|
interface TSlotInsideCornerMesh {
|
|
288
319
|
positions: number[];
|
|
289
320
|
indices: number[];
|
|
@@ -327,4 +358,4 @@ declare function createJSCADRenderer(jscad: typeof jscadModeling): {
|
|
|
327
358
|
};
|
|
328
359
|
};
|
|
329
360
|
|
|
330
|
-
export { ButtonScrew, type ButtonScrewMesh, type ButtonScrewMeshOptions, type ButtonScrewProps, CableGrommet, type CableGrommetMesh, type CableGrommetMeshOptions, type CableGrommetProps, type ColoredGeom, CompressionSpring, type CompressionSpringMesh, type CompressionSpringMeshOptions, type CompressionSpringProps, FlangedBushing, type FlangedBushingMesh, type FlangedBushingProps, FlatHeadScrew, type FlatHeadScrewMesh, type FlatHeadScrewMeshOptions, type FlatHeadScrewProps, Fragment, HelicalGear, type HelicalGearMesh, type HelicalGearProps, HexBolt, type HexBoltMesh, type HexBoltMeshOptions, type HexBoltProps, HexNut, type HexNutMesh, type HexNutMeshOptions, type HexNutProps, HexSocketBolt, type HexSocketBoltMesh, type HexSocketBoltProps, NEMA17, NEMA23, NEMA8, type NemaFrameMotorProps, NemaMotor, type NemaMotorProps, PanScrew, type PanScrewMesh, type PanScrewMeshOptions, type PanScrewProps, PlainBushing, type PlainBushingMesh, type PlainBushingProps, type RenderResult, SheetMetal, type SheetMetalMesh, type SheetMetalProps, SpurGear, type SpurGearMesh, type SpurGearProps, TSlotExtrusion, type TSlotExtrusionMesh, type TSlotExtrusionProps, TSlotInsideCorner, type TSlotInsideCornerMesh, type TSlotInsideCornerProps, type VNode, WormGear, type WormGearMesh, type WormGearProps, convertCSGToThreeGeom, createButtonScrewGeom, createButtonScrewMesh, createCableGrommetGeom, createCableGrommetMesh, createCompressionSpringGeom, createCompressionSpringMesh, createFlangedBushingGeom, createFlangedBushingMesh, createFlatHeadScrewGeom, createFlatHeadScrewMesh, createHelicalGearGeom, createHelicalGearMesh, createHexBoltGeom, createHexBoltMesh, createHexNutGeom, createHexNutMesh, createHexSocketBoltGeom, createHexSocketBoltMesh, createJSCADRenderer, createPanScrewGeom, createPanScrewMesh, createPlainBushingGeom, createPlainBushingMesh, createSheetMetalGeom, createSheetMetalMesh, createSpurGearGeom, createSpurGearMesh, createTSlotExtrusionGeom, createTSlotExtrusionMesh, createTSlotInsideCornerGeom, createTSlotInsideCornerMesh, createWormGearGeom, createWormGearMesh, getJscadModelForFootprint, getJscadModelForFootprintWithPads, h };
|
|
361
|
+
export { ButtonScrew, type ButtonScrewMesh, type ButtonScrewMeshOptions, type ButtonScrewProps, CableGrommet, type CableGrommetMesh, type CableGrommetMeshOptions, type CableGrommetProps, type ColoredGeom, CompressionSpring, type CompressionSpringMesh, type CompressionSpringMeshOptions, type CompressionSpringProps, FlangedBushing, type FlangedBushingMesh, type FlangedBushingProps, FlatHeadScrew, type FlatHeadScrewMesh, type FlatHeadScrewMeshOptions, type FlatHeadScrewProps, Fragment, HelicalGear, type HelicalGearMesh, type HelicalGearProps, HexBolt, type HexBoltMesh, type HexBoltMeshOptions, type HexBoltProps, HexNut, type HexNutMesh, type HexNutMeshOptions, type HexNutProps, HexSocketBolt, type HexSocketBoltMesh, type HexSocketBoltProps, NEMA17, NEMA23, NEMA8, type NemaFrameMotorProps, NemaMotor, type NemaMotorProps, PanScrew, type PanScrewMesh, type PanScrewMeshOptions, type PanScrewProps, PlainBushing, type PlainBushingMesh, type PlainBushingProps, type RenderResult, ShaftCollar, type ShaftCollarMesh, type ShaftCollarProps, SheetMetal, type SheetMetalMesh, type SheetMetalProps, SpurGear, type SpurGearMesh, type SpurGearProps, TSlotExtrusion, type TSlotExtrusionMesh, type TSlotExtrusionProps, TSlotGusset, type TSlotGussetMesh, type TSlotGussetProps, TSlotInsideCorner, type TSlotInsideCornerMesh, type TSlotInsideCornerProps, type VNode, WormGear, type WormGearMesh, type WormGearProps, convertCSGToThreeGeom, createButtonScrewGeom, createButtonScrewMesh, createCableGrommetGeom, createCableGrommetMesh, createCompressionSpringGeom, createCompressionSpringMesh, createFlangedBushingGeom, createFlangedBushingMesh, createFlatHeadScrewGeom, createFlatHeadScrewMesh, createHelicalGearGeom, createHelicalGearMesh, createHexBoltGeom, createHexBoltMesh, createHexNutGeom, createHexNutMesh, createHexSocketBoltGeom, createHexSocketBoltMesh, createJSCADRenderer, createPanScrewGeom, createPanScrewMesh, createPlainBushingGeom, createPlainBushingMesh, createShaftCollarGeom, createShaftCollarMesh, createSheetMetalGeom, createSheetMetalMesh, createSpurGearGeom, createSpurGearMesh, createTSlotExtrusionGeom, createTSlotExtrusionMesh, createTSlotGussetGeom, createTSlotGussetMesh, createTSlotInsideCornerGeom, createTSlotInsideCornerMesh, createWormGearGeom, createWormGearMesh, getJscadModelForFootprint, getJscadModelForFootprintWithPads, h };
|
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(model21) {
|
|
187
|
+
return model21;
|
|
188
188
|
}
|
|
189
189
|
var ModelRendererRegistry = class {
|
|
190
190
|
models = /* @__PURE__ */ new Map();
|
|
191
|
-
register(
|
|
192
|
-
if (typeof
|
|
191
|
+
register(model21) {
|
|
192
|
+
if (typeof model21.name !== "string" || !/^[a-z]+$/.test(model21.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(model21.name)) {
|
|
198
|
+
throw new Error(`Model renderer "${model21.name}" is already registered`);
|
|
199
199
|
}
|
|
200
|
-
if (
|
|
200
|
+
if (model21.pads !== "none" && model21.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 } = model21;
|
|
204
204
|
this.models.set(name, {
|
|
205
205
|
name,
|
|
206
206
|
schema,
|
|
@@ -2730,6 +2730,295 @@ function register13(registry) {
|
|
|
2730
2730
|
registry.register(model13);
|
|
2731
2731
|
}
|
|
2732
2732
|
|
|
2733
|
+
// lib/models/shaftcollar/register.tsx
|
|
2734
|
+
import { shaftCollarModelDefinitionSchema } from "@tscircuit/modelprinter";
|
|
2735
|
+
|
|
2736
|
+
// lib/models/shaftcollar/mesh.ts
|
|
2737
|
+
import "@jscad/modeling";
|
|
2738
|
+
import {
|
|
2739
|
+
shaftCollarModelPropsSchema,
|
|
2740
|
+
getShaftCollarDimensions
|
|
2741
|
+
} from "@tscircuit/modelprinter";
|
|
2742
|
+
|
|
2743
|
+
// lib/mechanical/shaft-mount-geometry.ts
|
|
2744
|
+
import jscad4 from "@jscad/modeling";
|
|
2745
|
+
var bodySegments = 64;
|
|
2746
|
+
var threadSegments = 24;
|
|
2747
|
+
var samplesPerTurn = 12;
|
|
2748
|
+
function assertShaftMountResolution(holes) {
|
|
2749
|
+
let triangles = 0;
|
|
2750
|
+
for (const hole of holes) {
|
|
2751
|
+
const steps = hole.threadPitch ? Math.ceil(hole.depth / hole.threadPitch * samplesPerTurn) : 1;
|
|
2752
|
+
if (!Number.isFinite(steps) || steps > 768)
|
|
2753
|
+
throw new Error(
|
|
2754
|
+
"Shaft mount exceeds mesh resolution limit (64 thread turns per hole)"
|
|
2755
|
+
);
|
|
2756
|
+
triangles += (steps + 1) * threadSegments * 2;
|
|
2757
|
+
}
|
|
2758
|
+
if (triangles > 1e5)
|
|
2759
|
+
throw new Error("Shaft mount exceeds total mesh resolution limit");
|
|
2760
|
+
}
|
|
2761
|
+
function createAnnularSleeve({
|
|
2762
|
+
outerRadius,
|
|
2763
|
+
boreARadius,
|
|
2764
|
+
boreBRadius = boreARadius,
|
|
2765
|
+
length,
|
|
2766
|
+
chamfer,
|
|
2767
|
+
stepZ = length / 2
|
|
2768
|
+
}) {
|
|
2769
|
+
const halfAngle = Math.PI / bodySegments;
|
|
2770
|
+
const cosine = Math.cos(halfAngle);
|
|
2771
|
+
if ((Math.max(boreARadius, boreBRadius) + chamfer) / cosine >= (outerRadius - chamfer) * cosine - 1e-6)
|
|
2772
|
+
throw new Error(
|
|
2773
|
+
"Shaft mount wall/chamfer ligament exceeds mesh resolution limit"
|
|
2774
|
+
);
|
|
2775
|
+
const raw = [
|
|
2776
|
+
[0, outerRadius - chamfer, false],
|
|
2777
|
+
[chamfer, outerRadius, false],
|
|
2778
|
+
[length - chamfer, outerRadius, false],
|
|
2779
|
+
[length, outerRadius - chamfer, false],
|
|
2780
|
+
[length, boreBRadius + chamfer, true],
|
|
2781
|
+
[length - chamfer, boreBRadius, true],
|
|
2782
|
+
[stepZ, boreBRadius, true],
|
|
2783
|
+
[stepZ, boreARadius, true],
|
|
2784
|
+
[chamfer, boreARadius, true],
|
|
2785
|
+
[0, boreARadius + chamfer, true]
|
|
2786
|
+
];
|
|
2787
|
+
const profile = raw.filter(
|
|
2788
|
+
([z, r], i) => i === 0 || z !== raw[i - 1][0] || r !== raw[i - 1][1]
|
|
2789
|
+
);
|
|
2790
|
+
const positions = [];
|
|
2791
|
+
const indices = [];
|
|
2792
|
+
for (const [z, r, isBore] of profile)
|
|
2793
|
+
for (let i = 0; i < bodySegments; i++) {
|
|
2794
|
+
const angle = (i + (isBore ? 0.5 : 0)) * Math.PI * 2 / bodySegments;
|
|
2795
|
+
const radius = isBore ? r / cosine : r;
|
|
2796
|
+
positions.push(radius * Math.cos(angle), radius * Math.sin(angle), z);
|
|
2797
|
+
}
|
|
2798
|
+
for (let row = 0; row < profile.length; row++)
|
|
2799
|
+
for (let i = 0; i < bodySegments; i++) {
|
|
2800
|
+
const next = (i + 1) % bodySegments;
|
|
2801
|
+
const a = row * bodySegments + i, b = row * bodySegments + next;
|
|
2802
|
+
const c = (row + 1) % profile.length * bodySegments + next, d = (row + 1) % profile.length * bodySegments + i;
|
|
2803
|
+
indices.push(a, b, c, a, c, d);
|
|
2804
|
+
}
|
|
2805
|
+
return indexedMeshToGeom3({ positions, indices });
|
|
2806
|
+
}
|
|
2807
|
+
function createMountingHoleCutter(hole) {
|
|
2808
|
+
assertShaftMountResolution([hole]);
|
|
2809
|
+
const pitch = hole.threadPitch;
|
|
2810
|
+
const steps = pitch ? Math.max(2, Math.ceil(hole.depth / pitch * samplesPerTurn)) : 1;
|
|
2811
|
+
const segments = pitch ? threadSegments : 48;
|
|
2812
|
+
const extension = 1e-4;
|
|
2813
|
+
const radius = hole.diameter / 2;
|
|
2814
|
+
const threadDepth = pitch ? Math.min(pitch * 0.541266, radius * 0.8) : 0;
|
|
2815
|
+
const hand = hole.threadHand === "left" ? -1 : 1;
|
|
2816
|
+
const positions = [];
|
|
2817
|
+
const indices = [];
|
|
2818
|
+
const [dx, dy, dz] = hole.direction;
|
|
2819
|
+
if (Math.abs(dz) > 1e-10 || Math.abs(Math.hypot(dx, dy) - 1) > 1e-10)
|
|
2820
|
+
throw new Error("Expected a horizontal unit hole axis");
|
|
2821
|
+
const push = (x, y, z) => {
|
|
2822
|
+
positions.push(
|
|
2823
|
+
hole.start[0] + y * dy + z * dx,
|
|
2824
|
+
hole.start[1] - y * dx + z * dy,
|
|
2825
|
+
hole.start[2] + x
|
|
2826
|
+
);
|
|
2827
|
+
};
|
|
2828
|
+
for (let row = 0; row <= steps; row++) {
|
|
2829
|
+
const z = -extension + (hole.depth + 2 * extension) * row / steps;
|
|
2830
|
+
for (let i = 0; i < segments; i++) {
|
|
2831
|
+
const angle = i * Math.PI * 2 / segments;
|
|
2832
|
+
const phase = pitch ? ((z / pitch - hand * angle / (Math.PI * 2)) % 1 + 1) % 1 : 0;
|
|
2833
|
+
const distance2 = Math.min(phase, 1 - phase);
|
|
2834
|
+
const r = radius - Math.min(
|
|
2835
|
+
threadDepth,
|
|
2836
|
+
Math.max(0, (distance2 - 1 / 8) * (pitch ?? 0) * Math.sqrt(3))
|
|
2837
|
+
);
|
|
2838
|
+
push(r * Math.cos(angle), r * Math.sin(angle), z);
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2841
|
+
for (let row = 0; row < steps; row++)
|
|
2842
|
+
for (let i = 0; i < segments; i++) {
|
|
2843
|
+
const next = (i + 1) % segments;
|
|
2844
|
+
const a = row * segments + i, b = row * segments + next, c = (row + 1) * segments + next, d = (row + 1) * segments + i;
|
|
2845
|
+
indices.push(a, b, c, a, c, d);
|
|
2846
|
+
}
|
|
2847
|
+
for (const end of [0, steps]) {
|
|
2848
|
+
const center = positions.length / 3;
|
|
2849
|
+
push(0, 0, end === 0 ? -extension : hole.depth + extension);
|
|
2850
|
+
for (let i = 0; i < segments; i++) {
|
|
2851
|
+
const a = end * segments + i, b = end * segments + (i + 1) % segments;
|
|
2852
|
+
indices.push(center, end === 0 ? b : a, end === 0 ? a : b);
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
2855
|
+
return indexedMeshToGeom3({ positions, indices });
|
|
2856
|
+
}
|
|
2857
|
+
function subtractShaftMountParts(body, ...cutters) {
|
|
2858
|
+
const factor = 100;
|
|
2859
|
+
const scaled = [body, ...cutters].map(
|
|
2860
|
+
(geometry) => jscad4.transforms.scale([factor, factor, factor], geometry)
|
|
2861
|
+
);
|
|
2862
|
+
const result = jscad4.booleans.subtract(scaled[0], ...scaled.slice(1));
|
|
2863
|
+
return jscad4.transforms.scale([1 / factor, 1 / factor, 1 / factor], result);
|
|
2864
|
+
}
|
|
2865
|
+
function finishShaftMountMesh(geometry) {
|
|
2866
|
+
const positions = [];
|
|
2867
|
+
const vertices = /* @__PURE__ */ new Map();
|
|
2868
|
+
const tolerance = 1e-6;
|
|
2869
|
+
const weld = (point) => {
|
|
2870
|
+
const cell = point.map((v) => Math.floor(v / tolerance));
|
|
2871
|
+
for (let x = -1; x <= 1; x++)
|
|
2872
|
+
for (let y = -1; y <= 1; y++)
|
|
2873
|
+
for (let z = -1; z <= 1; z++) {
|
|
2874
|
+
const nearby = vertices.get(
|
|
2875
|
+
[cell[0] + x, cell[1] + y, cell[2] + z].join(",")
|
|
2876
|
+
) ?? [];
|
|
2877
|
+
for (const index2 of nearby)
|
|
2878
|
+
if (Math.hypot(
|
|
2879
|
+
...point.map((v, axis) => v - positions[index2 * 3 + axis])
|
|
2880
|
+
) < tolerance)
|
|
2881
|
+
return index2;
|
|
2882
|
+
}
|
|
2883
|
+
const index = positions.length / 3;
|
|
2884
|
+
positions.push(...point);
|
|
2885
|
+
const key = cell.join(",");
|
|
2886
|
+
vertices.set(key, [...vertices.get(key) ?? [], index]);
|
|
2887
|
+
return index;
|
|
2888
|
+
};
|
|
2889
|
+
const polygons = jscad4.geometries.geom3.toPolygons(geometry).map(
|
|
2890
|
+
(polygon) => polygon.vertices.map(weld).filter((id, i, ids) => id !== ids[(i + ids.length - 1) % ids.length])
|
|
2891
|
+
).map((ids) => [...new Set(ids)]).filter((ids) => ids.length >= 3).filter((ids) => {
|
|
2892
|
+
let longest = 0;
|
|
2893
|
+
let origin = [];
|
|
2894
|
+
let direction = [];
|
|
2895
|
+
for (let i = 0; i < ids.length; i++)
|
|
2896
|
+
for (let j = i + 1; j < ids.length; j++) {
|
|
2897
|
+
const a = positions.slice(ids[i] * 3, ids[i] * 3 + 3);
|
|
2898
|
+
const delta = positions.slice(ids[j] * 3, ids[j] * 3 + 3).map((v, axis) => v - a[axis]);
|
|
2899
|
+
const squared = delta.reduce((sum, v) => sum + v * v, 0);
|
|
2900
|
+
if (squared > longest) {
|
|
2901
|
+
longest = squared;
|
|
2902
|
+
origin = a;
|
|
2903
|
+
direction = delta;
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
return ids.some((id) => {
|
|
2907
|
+
const delta = positions.slice(id * 3, id * 3 + 3).map((v, axis) => v - origin[axis]);
|
|
2908
|
+
const t = delta.reduce((sum, v, axis) => sum + v * direction[axis], 0) / longest;
|
|
2909
|
+
return Math.hypot(...delta.map((v, axis) => v - t * direction[axis])) >= tolerance;
|
|
2910
|
+
});
|
|
2911
|
+
});
|
|
2912
|
+
const edgeKey = (a, b) => `${Math.min(a, b)},${Math.max(a, b)}`;
|
|
2913
|
+
const edges = /* @__PURE__ */ new Map();
|
|
2914
|
+
for (const polygon of polygons)
|
|
2915
|
+
for (let i = 0; i < polygon.length; i++) {
|
|
2916
|
+
const a = polygon[i], b = polygon[(i + 1) % polygon.length], key = edgeKey(a, b);
|
|
2917
|
+
const edge = edges.get(key) ?? { a, b, count: 0 };
|
|
2918
|
+
edge.count++;
|
|
2919
|
+
edges.set(key, edge);
|
|
2920
|
+
}
|
|
2921
|
+
const unmatched = [...edges.values()].filter((edge) => edge.count === 1);
|
|
2922
|
+
const candidates = [...new Set(unmatched.flatMap((edge) => [edge.a, edge.b]))];
|
|
2923
|
+
const splits = /* @__PURE__ */ new Map();
|
|
2924
|
+
for (const { a, b } of unmatched) {
|
|
2925
|
+
const origin = positions.slice(a * 3, a * 3 + 3);
|
|
2926
|
+
const direction = positions.slice(b * 3, b * 3 + 3).map((v, axis) => v - origin[axis]);
|
|
2927
|
+
const squared = direction.reduce((sum, v) => sum + v * v, 0);
|
|
2928
|
+
const points = [];
|
|
2929
|
+
for (const id of candidates) {
|
|
2930
|
+
if (id === a || id === b) continue;
|
|
2931
|
+
const delta = positions.slice(id * 3, id * 3 + 3).map((v, axis) => v - origin[axis]);
|
|
2932
|
+
const t = delta.reduce((sum, v, axis) => sum + v * direction[axis], 0) / squared;
|
|
2933
|
+
if (t <= 0 || t >= 1) continue;
|
|
2934
|
+
const distance2 = Math.hypot(
|
|
2935
|
+
...delta.map((v, axis) => v - t * direction[axis])
|
|
2936
|
+
);
|
|
2937
|
+
if (distance2 < tolerance) points.push({ id, t });
|
|
2938
|
+
}
|
|
2939
|
+
points.sort((p, q) => p.t - q.t);
|
|
2940
|
+
splits.set(
|
|
2941
|
+
`${a},${b}`,
|
|
2942
|
+
points.map((p) => p.id)
|
|
2943
|
+
);
|
|
2944
|
+
splits.set(`${b},${a}`, points.map((p) => p.id).reverse());
|
|
2945
|
+
}
|
|
2946
|
+
const indices = [];
|
|
2947
|
+
for (const polygon of polygons) {
|
|
2948
|
+
const perimeter = polygon.flatMap((a, i) => [
|
|
2949
|
+
a,
|
|
2950
|
+
...(splits.get(`${a},${polygon[(i + 1) % polygon.length]}`) ?? []).filter((id) => !polygon.includes(id))
|
|
2951
|
+
]);
|
|
2952
|
+
const unique = perimeter.filter(
|
|
2953
|
+
(id, i) => id !== perimeter[(i + perimeter.length - 1) % perimeter.length]
|
|
2954
|
+
);
|
|
2955
|
+
if (unique.length === 3) {
|
|
2956
|
+
indices.push(...unique);
|
|
2957
|
+
continue;
|
|
2958
|
+
}
|
|
2959
|
+
const center = positions.length / 3;
|
|
2960
|
+
positions.push(
|
|
2961
|
+
...[0, 1, 2].map(
|
|
2962
|
+
(axis) => unique.reduce((sum, id) => sum + positions[id * 3 + axis], 0) / unique.length
|
|
2963
|
+
)
|
|
2964
|
+
);
|
|
2965
|
+
for (let i = 0; i < unique.length; i++)
|
|
2966
|
+
indices.push(center, unique[i], unique[(i + 1) % unique.length]);
|
|
2967
|
+
}
|
|
2968
|
+
const compact = [];
|
|
2969
|
+
const remap = /* @__PURE__ */ new Map();
|
|
2970
|
+
return {
|
|
2971
|
+
positions: compact,
|
|
2972
|
+
indices: indices.map((index) => {
|
|
2973
|
+
let next = remap.get(index);
|
|
2974
|
+
if (next === void 0) {
|
|
2975
|
+
next = compact.length / 3;
|
|
2976
|
+
remap.set(index, next);
|
|
2977
|
+
compact.push(...positions.slice(index * 3, index * 3 + 3));
|
|
2978
|
+
}
|
|
2979
|
+
return next;
|
|
2980
|
+
})
|
|
2981
|
+
};
|
|
2982
|
+
}
|
|
2983
|
+
|
|
2984
|
+
// lib/models/shaftcollar/mesh.ts
|
|
2985
|
+
function createShaftCollarMesh(input) {
|
|
2986
|
+
const props = shaftCollarModelPropsSchema.parse(input);
|
|
2987
|
+
const dimensions = getShaftCollarDimensions(props);
|
|
2988
|
+
assertShaftMountResolution([dimensions.screwHole]);
|
|
2989
|
+
const body = createAnnularSleeve({
|
|
2990
|
+
outerRadius: props.outerDiameter / 2,
|
|
2991
|
+
boreARadius: props.boreDiameter / 2,
|
|
2992
|
+
length: props.width,
|
|
2993
|
+
chamfer: props.chamfer
|
|
2994
|
+
});
|
|
2995
|
+
return finishShaftMountMesh(
|
|
2996
|
+
subtractShaftMountParts(
|
|
2997
|
+
body,
|
|
2998
|
+
createMountingHoleCutter(dimensions.screwHole)
|
|
2999
|
+
)
|
|
3000
|
+
);
|
|
3001
|
+
}
|
|
3002
|
+
|
|
3003
|
+
// lib/models/shaftcollar/ShaftCollar.tsx
|
|
3004
|
+
function createShaftCollarGeom(input) {
|
|
3005
|
+
return indexedMeshToGeom3(createShaftCollarMesh(input));
|
|
3006
|
+
}
|
|
3007
|
+
function ShaftCollar({ color = "#737e8f", ...props }) {
|
|
3008
|
+
return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsx(Custom, { geometry: createShaftCollarGeom(props) }) });
|
|
3009
|
+
}
|
|
3010
|
+
|
|
3011
|
+
// lib/models/shaftcollar/register.tsx
|
|
3012
|
+
var model14 = defineModelRenderer({
|
|
3013
|
+
name: "shaftcollar",
|
|
3014
|
+
schema: shaftCollarModelDefinitionSchema,
|
|
3015
|
+
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(ShaftCollar, { ...props }),
|
|
3016
|
+
pads: "none"
|
|
3017
|
+
});
|
|
3018
|
+
function register14(registry) {
|
|
3019
|
+
registry.register(model14);
|
|
3020
|
+
}
|
|
3021
|
+
|
|
2733
3022
|
// lib/models/sheetmetal/register.tsx
|
|
2734
3023
|
import { sheetMetalModelDefinitionSchema } from "@tscircuit/modelprinter";
|
|
2735
3024
|
|
|
@@ -2887,14 +3176,14 @@ function SheetMetal({ color = "#737e8f", ...props }) {
|
|
|
2887
3176
|
}
|
|
2888
3177
|
|
|
2889
3178
|
// lib/models/sheetmetal/register.tsx
|
|
2890
|
-
var
|
|
3179
|
+
var model15 = defineModelRenderer({
|
|
2891
3180
|
name: "sheetmetal",
|
|
2892
3181
|
schema: sheetMetalModelDefinitionSchema,
|
|
2893
3182
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SheetMetal, { ...props }),
|
|
2894
3183
|
pads: "none"
|
|
2895
3184
|
});
|
|
2896
|
-
function
|
|
2897
|
-
registry.register(
|
|
3185
|
+
function register15(registry) {
|
|
3186
|
+
registry.register(model15);
|
|
2898
3187
|
}
|
|
2899
3188
|
|
|
2900
3189
|
// lib/models/spurgear/register.tsx
|
|
@@ -2909,14 +3198,14 @@ function SpurGear({ color = "#737e8f", ...props }) {
|
|
|
2909
3198
|
}
|
|
2910
3199
|
|
|
2911
3200
|
// lib/models/spurgear/register.tsx
|
|
2912
|
-
var
|
|
3201
|
+
var model16 = defineModelRenderer({
|
|
2913
3202
|
name: "spurgear",
|
|
2914
3203
|
schema: spurGearModelDefinitionSchema,
|
|
2915
3204
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(SpurGear, { ...props }),
|
|
2916
3205
|
pads: "none"
|
|
2917
3206
|
});
|
|
2918
|
-
function
|
|
2919
|
-
registry.register(
|
|
3207
|
+
function register16(registry) {
|
|
3208
|
+
registry.register(model16);
|
|
2920
3209
|
}
|
|
2921
3210
|
|
|
2922
3211
|
// lib/models/tslotextrusion/register.tsx
|
|
@@ -3066,14 +3355,74 @@ function TSlotExtrusion({
|
|
|
3066
3355
|
}
|
|
3067
3356
|
|
|
3068
3357
|
// lib/models/tslotextrusion/register.tsx
|
|
3069
|
-
var
|
|
3358
|
+
var model17 = defineModelRenderer({
|
|
3070
3359
|
name: "tslotextrusion",
|
|
3071
3360
|
schema: tSlotExtrusionModelDefinitionSchema,
|
|
3072
3361
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(TSlotExtrusion, { ...props }),
|
|
3073
3362
|
pads: "none"
|
|
3074
3363
|
});
|
|
3075
|
-
function
|
|
3076
|
-
registry.register(
|
|
3364
|
+
function register17(registry) {
|
|
3365
|
+
registry.register(model17);
|
|
3366
|
+
}
|
|
3367
|
+
|
|
3368
|
+
// lib/models/tslotgusset/register.tsx
|
|
3369
|
+
import { tSlotGussetModelDefinitionSchema } from "@tscircuit/modelprinter";
|
|
3370
|
+
|
|
3371
|
+
// lib/models/tslotgusset/mesh.ts
|
|
3372
|
+
import {
|
|
3373
|
+
getTSlotGussetMountingSlots,
|
|
3374
|
+
tSlotGussetModelPropsSchema
|
|
3375
|
+
} from "@tscircuit/modelprinter";
|
|
3376
|
+
function createTSlotGussetMesh(input = {}) {
|
|
3377
|
+
const props = tSlotGussetModelPropsSchema.parse(input);
|
|
3378
|
+
const holes = getTSlotGussetMountingSlots(props).map((slot) => {
|
|
3379
|
+
const radius = slot.width / 2;
|
|
3380
|
+
const halfStraight = (slot.length - slot.width) / 2;
|
|
3381
|
+
const rotate = (u, v) => slot.orientation === 0 ? [slot.center.x + u, slot.center.y + v] : [slot.center.x - v, slot.center.y + u];
|
|
3382
|
+
if (halfStraight === 0)
|
|
3383
|
+
return circularProfile(0, 0, radius).map(([u, v]) => rotate(u, v));
|
|
3384
|
+
const loop = [];
|
|
3385
|
+
for (const side of [1, -1])
|
|
3386
|
+
for (let step = 0; step <= 48; step++) {
|
|
3387
|
+
const angle = -Math.PI / 2 + step * Math.PI / 48 + (side < 0 ? Math.PI : 0);
|
|
3388
|
+
loop.push(
|
|
3389
|
+
rotate(
|
|
3390
|
+
side * halfStraight + radius * Math.cos(angle),
|
|
3391
|
+
radius * Math.sin(angle)
|
|
3392
|
+
)
|
|
3393
|
+
);
|
|
3394
|
+
}
|
|
3395
|
+
return loop;
|
|
3396
|
+
});
|
|
3397
|
+
return extrudePlanarProfile({
|
|
3398
|
+
outer: [
|
|
3399
|
+
[0, 0],
|
|
3400
|
+
[props.width, 0],
|
|
3401
|
+
[0, props.height]
|
|
3402
|
+
],
|
|
3403
|
+
holes,
|
|
3404
|
+
start: 0,
|
|
3405
|
+
end: props.thickness
|
|
3406
|
+
});
|
|
3407
|
+
}
|
|
3408
|
+
|
|
3409
|
+
// lib/models/tslotgusset/TSlotGusset.tsx
|
|
3410
|
+
function createTSlotGussetGeom(input = {}) {
|
|
3411
|
+
return indexedMeshToGeom3(createTSlotGussetMesh(input));
|
|
3412
|
+
}
|
|
3413
|
+
function TSlotGusset({ color = "#8995a3", ...props }) {
|
|
3414
|
+
return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsx(Custom, { geometry: createTSlotGussetGeom(props) }) });
|
|
3415
|
+
}
|
|
3416
|
+
|
|
3417
|
+
// lib/models/tslotgusset/register.tsx
|
|
3418
|
+
var model18 = defineModelRenderer({
|
|
3419
|
+
name: "tslotgusset",
|
|
3420
|
+
schema: tSlotGussetModelDefinitionSchema,
|
|
3421
|
+
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(TSlotGusset, { ...props }),
|
|
3422
|
+
pads: "none"
|
|
3423
|
+
});
|
|
3424
|
+
function register18(registry) {
|
|
3425
|
+
registry.register(model18);
|
|
3077
3426
|
}
|
|
3078
3427
|
|
|
3079
3428
|
// lib/models/tslotinsidecorner/register.tsx
|
|
@@ -3153,14 +3502,14 @@ function TSlotInsideCorner({
|
|
|
3153
3502
|
}
|
|
3154
3503
|
|
|
3155
3504
|
// lib/models/tslotinsidecorner/register.tsx
|
|
3156
|
-
var
|
|
3505
|
+
var model19 = defineModelRenderer({
|
|
3157
3506
|
name: "tslotinsidecorner",
|
|
3158
3507
|
schema: tSlotInsideCornerModelDefinitionSchema,
|
|
3159
3508
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(TSlotInsideCorner, { ...props }),
|
|
3160
3509
|
pads: "none"
|
|
3161
3510
|
});
|
|
3162
|
-
function
|
|
3163
|
-
registry.register(
|
|
3511
|
+
function register19(registry) {
|
|
3512
|
+
registry.register(model19);
|
|
3164
3513
|
}
|
|
3165
3514
|
|
|
3166
3515
|
// lib/models/wormgear/register.tsx
|
|
@@ -3352,14 +3701,14 @@ function WormGear({ color = "#737e8f", ...props }) {
|
|
|
3352
3701
|
}
|
|
3353
3702
|
|
|
3354
3703
|
// lib/models/wormgear/register.tsx
|
|
3355
|
-
var
|
|
3704
|
+
var model20 = defineModelRenderer({
|
|
3356
3705
|
name: "wormgear",
|
|
3357
3706
|
schema: wormGearModelDefinitionSchema,
|
|
3358
3707
|
render: ({ fn, ...props }) => /* @__PURE__ */ jsx(WormGear, { ...props }),
|
|
3359
3708
|
pads: "none"
|
|
3360
3709
|
});
|
|
3361
|
-
function
|
|
3362
|
-
registry.register(
|
|
3710
|
+
function register20(registry) {
|
|
3711
|
+
registry.register(model20);
|
|
3363
3712
|
}
|
|
3364
3713
|
|
|
3365
3714
|
// lib/generated/model-renderers.ts
|
|
@@ -3382,6 +3731,8 @@ function registerAllModelRenderers(registry) {
|
|
|
3382
3731
|
register16(registry);
|
|
3383
3732
|
register17(registry);
|
|
3384
3733
|
register18(registry);
|
|
3734
|
+
register19(registry);
|
|
3735
|
+
register20(registry);
|
|
3385
3736
|
}
|
|
3386
3737
|
|
|
3387
3738
|
// lib/default-model-registry.ts
|
|
@@ -10938,10 +11289,10 @@ var SOT143 = ({ footprint = "sot143" }) => {
|
|
|
10938
11289
|
var Footprinter3d = ({ footprint }) => {
|
|
10939
11290
|
const modelFn = mp3.string(footprint.split("_", 1)[0]).params().fn;
|
|
10940
11291
|
if (mp3.getModelNames().includes(modelFn)) {
|
|
10941
|
-
const
|
|
10942
|
-
const renderer = modelRendererRegistry.get(
|
|
11292
|
+
const model21 = mp3.string(footprint).json();
|
|
11293
|
+
const renderer = modelRendererRegistry.get(model21.fn);
|
|
10943
11294
|
if (renderer) {
|
|
10944
|
-
return renderer.render(
|
|
11295
|
+
return renderer.render(model21);
|
|
10945
11296
|
}
|
|
10946
11297
|
}
|
|
10947
11298
|
let normalizedFootprint = footprint;
|
|
@@ -11774,8 +12125,8 @@ function renderNode(node, colorCtx, renderCtx) {
|
|
|
11774
12125
|
}
|
|
11775
12126
|
return (children ?? []).flatMap((c) => renderNode(c, colorCtx, renderCtx));
|
|
11776
12127
|
}
|
|
11777
|
-
function render(root,
|
|
11778
|
-
const geometries = renderNode(root, void 0, { jscad:
|
|
12128
|
+
function render(root, jscad6) {
|
|
12129
|
+
const geometries = renderNode(root, void 0, { jscad: jscad6 });
|
|
11779
12130
|
return {
|
|
11780
12131
|
geometries: geometries.map(
|
|
11781
12132
|
(entry) => entry.material ? { ...entry, geom: { ...entry.geom, material: entry.material } } : entry
|
|
@@ -11867,24 +12218,24 @@ function convertCSGToThreeGeom(csg) {
|
|
|
11867
12218
|
}
|
|
11868
12219
|
|
|
11869
12220
|
// lib/vanilla/index.ts
|
|
11870
|
-
function getJscadModelForFootprint(footprint,
|
|
12221
|
+
function getJscadModelForFootprint(footprint, jscad6) {
|
|
11871
12222
|
const vnode = h(Footprinter3d, { footprint });
|
|
11872
|
-
return render(vnode,
|
|
12223
|
+
return render(vnode, jscad6);
|
|
11873
12224
|
}
|
|
11874
|
-
function getJscadModelForFootprintWithPads(footprint,
|
|
12225
|
+
function getJscadModelForFootprintWithPads(footprint, jscad6) {
|
|
11875
12226
|
const vnode = h(
|
|
11876
12227
|
Fragment,
|
|
11877
12228
|
{},
|
|
11878
12229
|
h(Footprinter3d, { footprint }),
|
|
11879
12230
|
h(ExtrudedPads, { footprint })
|
|
11880
12231
|
);
|
|
11881
|
-
return render(vnode,
|
|
12232
|
+
return render(vnode, jscad6);
|
|
11882
12233
|
}
|
|
11883
|
-
function createJSCADRenderer(
|
|
12234
|
+
function createJSCADRenderer(jscad6) {
|
|
11884
12235
|
function createJSCADRoot(container) {
|
|
11885
12236
|
return {
|
|
11886
12237
|
render(element) {
|
|
11887
|
-
const { geometries } = render(element,
|
|
12238
|
+
const { geometries } = render(element, jscad6);
|
|
11888
12239
|
container.splice(0, container.length, ...geometries);
|
|
11889
12240
|
}
|
|
11890
12241
|
};
|
|
@@ -11908,9 +12259,11 @@ export {
|
|
|
11908
12259
|
NemaMotor,
|
|
11909
12260
|
PanScrew,
|
|
11910
12261
|
PlainBushing,
|
|
12262
|
+
ShaftCollar,
|
|
11911
12263
|
SheetMetal,
|
|
11912
12264
|
SpurGear,
|
|
11913
12265
|
TSlotExtrusion,
|
|
12266
|
+
TSlotGusset,
|
|
11914
12267
|
TSlotInsideCorner,
|
|
11915
12268
|
WormGear,
|
|
11916
12269
|
convertCSGToThreeGeom,
|
|
@@ -11937,12 +12290,16 @@ export {
|
|
|
11937
12290
|
createPanScrewMesh,
|
|
11938
12291
|
createPlainBushingGeom,
|
|
11939
12292
|
createPlainBushingMesh,
|
|
12293
|
+
createShaftCollarGeom,
|
|
12294
|
+
createShaftCollarMesh,
|
|
11940
12295
|
createSheetMetalGeom,
|
|
11941
12296
|
createSheetMetalMesh,
|
|
11942
12297
|
createSpurGearGeom,
|
|
11943
12298
|
createSpurGearMesh,
|
|
11944
12299
|
createTSlotExtrusionGeom,
|
|
11945
12300
|
createTSlotExtrusionMesh,
|
|
12301
|
+
createTSlotGussetGeom,
|
|
12302
|
+
createTSlotGussetMesh,
|
|
11946
12303
|
createTSlotInsideCornerGeom,
|
|
11947
12304
|
createTSlotInsideCornerMesh,
|
|
11948
12305
|
createWormGearGeom,
|