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/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(model19) {
187
- return model19;
186
+ function defineModelRenderer(model21) {
187
+ return model21;
188
188
  }
189
189
  var ModelRendererRegistry = class {
190
190
  models = /* @__PURE__ */ new Map();
191
- register(model19) {
192
- if (typeof model19.name !== "string" || !/^[a-z]+$/.test(model19.name)) {
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(model19.name)) {
198
- throw new Error(`Model renderer "${model19.name}" is already registered`);
197
+ if (this.models.has(model21.name)) {
198
+ throw new Error(`Model renderer "${model21.name}" is already registered`);
199
199
  }
200
- if (model19.pads !== "none" && model19.pads !== "footprinter") {
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 } = model19;
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 model14 = defineModelRenderer({
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 register14(registry) {
2897
- registry.register(model14);
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 model15 = defineModelRenderer({
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 register15(registry) {
2919
- registry.register(model15);
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 model16 = defineModelRenderer({
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 register16(registry) {
3076
- registry.register(model16);
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 model17 = defineModelRenderer({
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 register17(registry) {
3163
- registry.register(model17);
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 model18 = defineModelRenderer({
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 register18(registry) {
3362
- registry.register(model18);
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 model19 = mp3.string(footprint).json();
10942
- const renderer = modelRendererRegistry.get(model19.fn);
11292
+ const model21 = mp3.string(footprint).json();
11293
+ const renderer = modelRendererRegistry.get(model21.fn);
10943
11294
  if (renderer) {
10944
- return renderer.render(model19);
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, jscad4) {
11778
- const geometries = renderNode(root, void 0, { jscad: jscad4 });
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, jscad4) {
12221
+ function getJscadModelForFootprint(footprint, jscad6) {
11871
12222
  const vnode = h(Footprinter3d, { footprint });
11872
- return render(vnode, jscad4);
12223
+ return render(vnode, jscad6);
11873
12224
  }
11874
- function getJscadModelForFootprintWithPads(footprint, jscad4) {
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, jscad4);
12232
+ return render(vnode, jscad6);
11882
12233
  }
11883
- function createJSCADRenderer(jscad4) {
12234
+ function createJSCADRenderer(jscad6) {
11884
12235
  function createJSCADRoot(container) {
11885
12236
  return {
11886
12237
  render(element) {
11887
- const { geometries } = render(element, jscad4);
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,