jscad-electronics 0.0.238 → 0.0.240

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/vanilla.js CHANGED
@@ -12179,7 +12179,7 @@ function getNemaMotorReferencePoints(input) {
12179
12179
  (p.bodyWidth - p.faceCornerChamfer) / (Math.abs(x) + Math.abs(y))
12180
12180
  );
12181
12181
  if (p.nemaSize !== 34 || p.stepped) {
12182
- const profile6 = p.nemaSize === 34 ? {
12182
+ const profile5 = p.nemaSize === 34 ? {
12183
12183
  width: p.bodyWidth,
12184
12184
  chamfer: p.bodyCornerChamfer,
12185
12185
  stepped: p.stepped,
@@ -12195,7 +12195,7 @@ function getNemaMotorReferencePoints(input) {
12195
12195
  let low = 0, high = p.bodyWidth;
12196
12196
  for (let i = 0; i < 50; i++) {
12197
12197
  const mid = (low + high) / 2;
12198
- if (isInsideNemaFace(mid * x, mid * y, profile6)) low = mid;
12198
+ if (isInsideNemaFace(mid * x, mid * y, profile5)) low = mid;
12199
12199
  else high = mid;
12200
12200
  }
12201
12201
  radius = low;
@@ -12383,6 +12383,746 @@ var componentMaterials = {
12383
12383
  steel: { metalness: 1, roughness: 0.25 }
12384
12384
  };
12385
12385
 
12386
+ // node_modules/@tscircuit/jscad/lib/cleanup-subtraction.ts
12387
+ import insertTjunctions from "@jscad/modeling/src/operations/modifiers/insertTjunctions.js";
12388
+ function cleanupSubtraction(kernel, geometry) {
12389
+ const { geom3 } = kernel.geometries;
12390
+ if (!geometry.polygons.length) return geometry;
12391
+ const source = structuredClone(geometry);
12392
+ const polygons = geom3.toPolygons(source);
12393
+ const extent = Math.max(...kernel.measurements.measureDimensions(source));
12394
+ if (!Number.isFinite(extent) || extent <= 0)
12395
+ throw new Error("Subtraction requires finite nonempty geometry");
12396
+ const epsilon = Math.max(extent * 1e-10, 1e-12);
12397
+ source.polygons = polygons.map((polygon4) => ({
12398
+ ...polygon4,
12399
+ vertices: polygon4.vertices.map((point) => {
12400
+ if (!point.every(Number.isFinite))
12401
+ throw new Error("Subtraction requires finite coordinates");
12402
+ return point.map((value) => Math.round(value / epsilon) * epsilon);
12403
+ })
12404
+ }));
12405
+ const triangles = insertTjunctions(source.polygons).flatMap((polygon4) => {
12406
+ if (polygon4.vertices.length === 3) return [polygon4];
12407
+ const center = [0, 0, 0];
12408
+ for (const point of polygon4.vertices)
12409
+ for (let axis = 0; axis < 3; axis++)
12410
+ center[axis] += point[axis] / polygon4.vertices.length;
12411
+ return polygon4.vertices.map((point, index) => {
12412
+ const triangle = kernel.geometries.poly3.create([
12413
+ center,
12414
+ point,
12415
+ polygon4.vertices[(index + 1) % polygon4.vertices.length]
12416
+ ]);
12417
+ if (polygon4.color) triangle.color = polygon4.color;
12418
+ return triangle;
12419
+ });
12420
+ });
12421
+ const cleaned = geom3.create(triangles);
12422
+ return {
12423
+ ...geometry,
12424
+ polygons: cleaned.polygons,
12425
+ transforms: cleaned.transforms
12426
+ };
12427
+ }
12428
+
12429
+ // node_modules/@tscircuit/jscad/lib/with-references.ts
12430
+ import modeling from "@jscad/modeling";
12431
+ var metadata = /* @__PURE__ */ Symbol.for("@tscircuit/jscad/references/v1");
12432
+ var cache = /* @__PURE__ */ new WeakMap();
12433
+ var snapshot = (value) => structuredClone(value);
12434
+ var assertName = (name) => {
12435
+ if (typeof name !== "string" || !name.trim())
12436
+ throw new Error("Reference name must be nonempty");
12437
+ };
12438
+ function withReferences(kernel = modeling) {
12439
+ if (cache.has(kernel)) return cache.get(kernel);
12440
+ const k = kernel;
12441
+ const { mat4 } = k.maths;
12442
+ const identity = () => Array.from(mat4.create());
12443
+ const multiply = (a, b) => Array.from(mat4.multiply(mat4.create(), a, b));
12444
+ const isGeometry = (g) => g && (k.geometries.geom2.isA(g) || k.geometries.path2.isA(g) || k.geometries.geom3.isA(g));
12445
+ const inputs = (args) => args.flat(Infinity).filter(isGeometry);
12446
+ const read = (g) => g?.[metadata] ?? /* @__PURE__ */ Object.create(null);
12447
+ const merge = (geometries9) => {
12448
+ const refs = /* @__PURE__ */ Object.create(null);
12449
+ for (const g of geometries9)
12450
+ for (const [name, ref] of Object.entries(read(g))) {
12451
+ if (Object.hasOwn(refs, name) && refs[name] !== ref)
12452
+ throw new Error(`Duplicate reference: ${name}`);
12453
+ refs[name] = ref;
12454
+ }
12455
+ return refs;
12456
+ };
12457
+ const attach = (g, refs) => {
12458
+ if (!Object.keys(refs).length) return g;
12459
+ if (Array.isArray(g)) return g.map((item) => attach(item, refs));
12460
+ return isGeometry(g) ? Object.assign({}, g, { [metadata]: refs }) : g;
12461
+ };
12462
+ const moved = (refs, matrix) => Object.fromEntries(
12463
+ Object.entries(refs).map(([name, ref]) => [
12464
+ name,
12465
+ { geometry: ref.geometry, matrix: multiply(matrix, ref.matrix) }
12466
+ ])
12467
+ );
12468
+ const add = (refs, name, ref) => {
12469
+ assertName(name);
12470
+ if (Object.hasOwn(refs, name))
12471
+ throw new Error(`Duplicate reference: ${name}`);
12472
+ refs[name] = ref;
12473
+ };
12474
+ const planar = (g) => {
12475
+ if (!k.geometries.geom2.isA(g) && !k.geometries.path2.isA(g))
12476
+ throw new Error("References require native planar geometry");
12477
+ };
12478
+ const references2 = {
12479
+ name(name, geometry) {
12480
+ planar(geometry);
12481
+ const refs = merge([geometry]);
12482
+ add(refs, name, { geometry: snapshot(geometry), matrix: identity() });
12483
+ return attach(geometry, refs);
12484
+ },
12485
+ nameOutlines(geometry, names) {
12486
+ if (!k.geometries.geom2.isA(geometry))
12487
+ throw new Error("nameOutlines requires a native Geom2");
12488
+ const refs = merge([geometry]);
12489
+ const outlines = k.geometries.geom2.toOutlines(
12490
+ snapshot(geometry)
12491
+ );
12492
+ const area = (points) => points.reduce((sum, p, i) => {
12493
+ const q = points[(i + 1) % points.length];
12494
+ return sum + p[0] * q[1] - p[1] * q[0];
12495
+ }, 0);
12496
+ for (const [role, name] of Object.entries(names)) {
12497
+ if (name === void 0) continue;
12498
+ if (role !== "outer" && role !== "hole")
12499
+ throw new Error(`Unknown outline role: ${role}`);
12500
+ const matches = outlines.filter(
12501
+ (points) => role === "outer" ? area(points) > 0 : area(points) < 0
12502
+ );
12503
+ if (matches.length !== 1)
12504
+ throw new Error(
12505
+ `Expected exactly one ${role} outline, found ${matches.length}`
12506
+ );
12507
+ add(refs, name, {
12508
+ geometry: k.geometries.path2.fromPoints({ closed: true }, matches[0]),
12509
+ matrix: identity()
12510
+ });
12511
+ }
12512
+ return attach(geometry, refs);
12513
+ },
12514
+ reference(name, geometry) {
12515
+ return attach(
12516
+ k.geometries.geom3.create(),
12517
+ read(references2.name(name, geometry))
12518
+ );
12519
+ },
12520
+ get(geometry, name) {
12521
+ const ref = read(geometry)[name];
12522
+ if (!Object.hasOwn(read(geometry), name))
12523
+ throw new Error(`Unknown reference: ${name}`);
12524
+ return snapshot(ref);
12525
+ },
12526
+ list(geometry) {
12527
+ return Object.keys(read(geometry));
12528
+ },
12529
+ collect(geometries9) {
12530
+ return snapshot(merge(inputs([geometries9])));
12531
+ }
12532
+ };
12533
+ const wrapped = { ...k, references: references2 };
12534
+ for (const namespace of [
12535
+ "booleans",
12536
+ "hulls",
12537
+ "expansions",
12538
+ "modifiers",
12539
+ "extrusions",
12540
+ "colors"
12541
+ ]) {
12542
+ wrapped[namespace] = { ...k[namespace] };
12543
+ for (const [name, fn] of Object.entries(k[namespace]))
12544
+ if (typeof fn === "function") {
12545
+ wrapped[namespace][name] = (...args) => {
12546
+ const refs = merge(inputs(args));
12547
+ let result = fn(...args);
12548
+ if (namespace === "booleans" && name === "subtract" && k.geometries.geom3.isA(result)) {
12549
+ result = cleanupSubtraction(kernel, result);
12550
+ }
12551
+ return attach(result, refs);
12552
+ };
12553
+ }
12554
+ }
12555
+ const transformResult = (fn, args, offset, boundsBased = false) => {
12556
+ const gs = inputs(args.slice(offset));
12557
+ if (!gs.some((g) => Object.keys(read(g)).length)) return fn(...args);
12558
+ const maps = gs.map((g) => read(g));
12559
+ const before = boundsBased ? gs.map((g) => k.measurements.measureBoundingBox(snapshot(g))[0]) : [];
12560
+ const matrix = boundsBased ? null : fn(...args.slice(0, offset), k.geometries.geom3.create()).transforms;
12561
+ const result = fn(...args);
12562
+ const results = Array.isArray(result) ? result : [result];
12563
+ const output = results.map((g, i) => {
12564
+ let m = matrix;
12565
+ if (boundsBased) {
12566
+ const after = k.measurements.measureBoundingBox(snapshot(g))[0];
12567
+ m = mat4.fromTranslation(
12568
+ mat4.create(),
12569
+ after.map((n, axis) => n - before[i][axis])
12570
+ );
12571
+ }
12572
+ return attach(g, moved(maps[i], Array.from(m)));
12573
+ });
12574
+ return Array.isArray(result) ? output : output[0];
12575
+ };
12576
+ wrapped.transforms = { ...k.transforms };
12577
+ for (const [name, fn] of Object.entries(k.transforms)) {
12578
+ const boundsBased = /^(center|align)/.test(name);
12579
+ const offset = /^center[XYZ]$|^mirror[XYZ]$/.test(name) ? 0 : 1;
12580
+ wrapped.transforms[name] = (...args) => transformResult(fn, args, offset, boundsBased);
12581
+ }
12582
+ wrapped.geometries = { ...k.geometries };
12583
+ for (const ns of ["geom2", "geom3", "path2"]) {
12584
+ wrapped.geometries[ns] = {
12585
+ ...k.geometries[ns],
12586
+ transform: (matrix, g) => attach(k.geometries[ns].transform(matrix, g), moved(read(g), matrix))
12587
+ };
12588
+ }
12589
+ wrapped.extrusions.extrudeLinear = (options, ...objects) => {
12590
+ const gs = inputs(objects);
12591
+ const { topOutlineName, bottomOutlineName } = options ?? {};
12592
+ if (topOutlineName === void 0 && bottomOutlineName === void 0) {
12593
+ const refs2 = gs.map(read);
12594
+ const result = k.extrusions.extrudeLinear(options, ...objects);
12595
+ return Array.isArray(result) ? result.map((g, i) => attach(g, refs2[i])) : attach(result, refs2[0] ?? {});
12596
+ }
12597
+ if (gs.length !== 1)
12598
+ throw new Error("Named extrusion outlines require exactly one profile");
12599
+ const profile5 = gs[0];
12600
+ planar(profile5);
12601
+ if (k.geometries.path2.isA(profile5) && !profile5.isClosed)
12602
+ throw new Error("Named extrusion outlines require a closed path");
12603
+ const { height: height10 = 1, twistAngle = 0, twistSteps = 1 } = options;
12604
+ if (!Number.isFinite(height10) || !Number.isFinite(twistAngle) || !Number.isInteger(twistSteps) || twistSteps < 1)
12605
+ throw new Error(
12606
+ "Invalid named extrusion height, twistAngle or twistSteps"
12607
+ );
12608
+ const refs = merge(gs);
12609
+ const source = snapshot(profile5);
12610
+ const top = multiply(
12611
+ Array.from(mat4.fromTranslation(mat4.create(), [0, 0, height10])),
12612
+ Array.from(mat4.fromZRotation(mat4.create(), twistAngle))
12613
+ );
12614
+ for (const [prefix, matrix] of [
12615
+ [bottomOutlineName, identity()],
12616
+ [topOutlineName, top]
12617
+ ]) {
12618
+ if (prefix === void 0) continue;
12619
+ add(refs, prefix, { geometry: source, matrix });
12620
+ for (const [name, ref] of Object.entries(read(profile5)))
12621
+ add(refs, `${prefix}.${name}`, {
12622
+ geometry: ref.geometry,
12623
+ matrix: multiply(matrix, ref.matrix)
12624
+ });
12625
+ }
12626
+ return attach(k.extrusions.extrudeLinear(options, ...objects), refs);
12627
+ };
12628
+ cache.set(kernel, wrapped);
12629
+ cache.set(wrapped, wrapped);
12630
+ return wrapped;
12631
+ }
12632
+
12633
+ // node_modules/@tscircuit/jscad/lib/geom3-to-indexed-mesh.ts
12634
+ import jscad from "@jscad/modeling";
12635
+ var edgeKey = (a, b) => a < b ? `${a},${b}` : `${b},${a}`;
12636
+ function geom3ToIndexedMesh(input) {
12637
+ const generalize8 = jscad.modifiers.generalize;
12638
+ input = structuredClone(input);
12639
+ const inputExtent = Math.max(...jscad.measurements.measureDimensions(input));
12640
+ if (!Number.isFinite(inputExtent) || inputExtent <= 0)
12641
+ throw new Error("Expected finite nonempty geometry");
12642
+ const weldTolerance = Math.max(inputExtent * 1e-10, 1e-12);
12643
+ const cells = /* @__PURE__ */ new Map();
12644
+ const weld = (v) => {
12645
+ if (v.length !== 3 || v.some((value) => !Number.isFinite(value)))
12646
+ throw new Error("Expected finite mesh coordinates");
12647
+ const cell = v.map((value) => Math.floor(value / weldTolerance));
12648
+ for (let x = -1; x <= 1; x++)
12649
+ for (let y = -1; y <= 1; y++)
12650
+ for (let z = -1; z <= 1; z++) {
12651
+ const entries2 = cells.get(
12652
+ `${cell[0] + x},${cell[1] + y},${cell[2] + z}`
12653
+ );
12654
+ const existing = entries2?.find(
12655
+ (point3) => Math.hypot(...v.map((value, axis) => value - point3[axis])) <= weldTolerance
12656
+ );
12657
+ if (existing) return existing;
12658
+ }
12659
+ const point2 = [v[0], v[1], v[2]], key = cell.join(","), entries = cells.get(key);
12660
+ if (entries) entries.push(point2);
12661
+ else cells.set(key, [point2]);
12662
+ return point2;
12663
+ };
12664
+ const welded = jscad.geometries.geom3.fromPoints(
12665
+ jscad.geometries.geom3.toPolygons(input).map((poly) => poly.vertices.map(weld))
12666
+ );
12667
+ const geom = generalize8({ snap: true, triangulate: true }, welded);
12668
+ const extent = Math.max(...jscad.measurements.measureDimensions(geom));
12669
+ if (!Number.isFinite(extent) || extent <= 0)
12670
+ throw new Error("Expected finite nonempty geometry");
12671
+ const epsilon = Math.max(extent * 1e-10, 1e-12);
12672
+ const snapTolerance = Math.max(
12673
+ 2 * jscad.measurements.measureEpsilon(geom),
12674
+ epsilon
12675
+ );
12676
+ const positions = [], indices = [];
12677
+ const lookup = /* @__PURE__ */ new Map();
12678
+ const point = (index) => [
12679
+ positions[index * 3],
12680
+ positions[index * 3 + 1],
12681
+ positions[index * 3 + 2]
12682
+ ];
12683
+ const vertex = (v) => {
12684
+ if (v.length !== 3 || v.some((value) => !Number.isFinite(value)))
12685
+ throw new Error("Expected finite mesh coordinates");
12686
+ const key = v.map((x) => Math.round(x / epsilon)).join(",");
12687
+ let index = lookup.get(key);
12688
+ if (index === void 0) {
12689
+ index = positions.length / 3;
12690
+ positions.push(...v);
12691
+ lookup.set(key, index);
12692
+ }
12693
+ return index;
12694
+ };
12695
+ const area = ([a, b, c]) => {
12696
+ const pa = point(a), pb = point(b), pc = point(c);
12697
+ const u = pb.map((x, i) => x - pa[i]), v = pc.map((x, i) => x - pa[i]);
12698
+ return Math.hypot(
12699
+ u[1] * v[2] - u[2] * v[1],
12700
+ u[2] * v[0] - u[0] * v[2],
12701
+ u[0] * v[1] - u[1] * v[0]
12702
+ );
12703
+ };
12704
+ const triangles = [];
12705
+ const edges = /* @__PURE__ */ new Map();
12706
+ for (const poly of jscad.geometries.geom3.toPolygons(geom)) {
12707
+ for (let i = 1; i < poly.vertices.length - 1; i++) {
12708
+ const triangle = [
12709
+ vertex(poly.vertices[0]),
12710
+ vertex(poly.vertices[i]),
12711
+ vertex(poly.vertices[i + 1])
12712
+ ];
12713
+ if (area(triangle) <= epsilon * epsilon) continue;
12714
+ triangles.push(triangle);
12715
+ triangle.forEach((a, i2) => {
12716
+ const b = triangle[(i2 + 1) % 3], key = edgeKey(a, b), entry = edges.get(key);
12717
+ if (entry) entry.count++;
12718
+ else edges.set(key, { a, b, count: 1 });
12719
+ });
12720
+ }
12721
+ }
12722
+ const unmatched = [...edges.values()].filter(({ count }) => count === 1);
12723
+ const candidates = [...new Set(unmatched.flatMap(({ a, b }) => [a, b]))];
12724
+ const sorted = [0, 1, 2].map(
12725
+ (axis) => [...candidates].sort(
12726
+ (a, b) => positions[a * 3 + axis] - positions[b * 3 + axis]
12727
+ )
12728
+ );
12729
+ const subdivisions = /* @__PURE__ */ new Map();
12730
+ for (const { a, b } of unmatched) {
12731
+ const pa = point(a), pb = point(b), direction = pb.map((x, i) => x - pa[i]), length32 = Math.hypot(...direction);
12732
+ if (length32 <= epsilon) continue;
12733
+ const axis = direction.reduce(
12734
+ (best, x, i) => Math.abs(x) > Math.abs(direction[best]) ? i : best,
12735
+ 0
12736
+ );
12737
+ const unit = direction.map((x) => x / length32), low = Math.min(pa[axis], pb[axis]), high = Math.max(pa[axis], pb[axis]);
12738
+ const byAxis = sorted[axis];
12739
+ let left = 0, right = byAxis.length;
12740
+ while (left < right) {
12741
+ const mid = left + right >>> 1;
12742
+ if (positions[byAxis[mid] * 3 + axis] < low) left = mid + 1;
12743
+ else right = mid;
12744
+ }
12745
+ const splits = [];
12746
+ for (let i = left; i < byAxis.length; i++) {
12747
+ const index = byAxis[i], p = point(index);
12748
+ if (p[axis] > high) break;
12749
+ if (index === a || index === b) continue;
12750
+ const delta = p.map((x, j) => x - pa[j]), along = delta.reduce((sum, x, j) => sum + x * unit[j], 0);
12751
+ if (along <= epsilon || along >= length32 - epsilon) continue;
12752
+ const distance2 = Math.hypot(...delta.map((x, j) => x - along * unit[j]));
12753
+ if (distance2 <= snapTolerance) splits.push({ index, t: along / length32 });
12754
+ }
12755
+ if (splits.length)
12756
+ subdivisions.set(
12757
+ edgeKey(a, b),
12758
+ splits.sort((x, y) => x.t - y.t).map(({ index }) => index)
12759
+ );
12760
+ }
12761
+ for (const triangle of triangles) {
12762
+ const boundary = triangle.flatMap((a, i) => {
12763
+ const b = triangle[(i + 1) % 3], splits = subdivisions.get(edgeKey(a, b));
12764
+ if (!splits) return [a];
12765
+ const edge = edges.get(edgeKey(a, b));
12766
+ return [a, ...edge.a === a ? splits : [...splits].reverse()];
12767
+ });
12768
+ if (boundary.length === 3) {
12769
+ indices.push(...triangle);
12770
+ continue;
12771
+ }
12772
+ const origin = point(boundary[0]);
12773
+ const center = origin.map(
12774
+ (value, axis) => value + boundary.reduce(
12775
+ (sum, index) => sum + (point(index)[axis] - value) / boundary.length,
12776
+ 0
12777
+ )
12778
+ );
12779
+ const middle = vertex(center);
12780
+ for (let i = 0; i < boundary.length; i++) {
12781
+ const part = [
12782
+ middle,
12783
+ boundary[i],
12784
+ boundary[(i + 1) % boundary.length]
12785
+ ];
12786
+ if (area(part) <= epsilon * epsilon)
12787
+ throw new Error("Unable to preserve a degenerate mesh boundary");
12788
+ indices.push(...part);
12789
+ }
12790
+ }
12791
+ const compactPositions = [], compactIndices = [], remap = /* @__PURE__ */ new Map();
12792
+ for (const original of indices) {
12793
+ let index = remap.get(original);
12794
+ if (index === void 0) {
12795
+ index = compactPositions.length / 3;
12796
+ compactPositions.push(...point(original));
12797
+ remap.set(original, index);
12798
+ }
12799
+ compactIndices.push(index);
12800
+ }
12801
+ if (!compactIndices.length)
12802
+ throw new Error("Expected finite nonempty geometry");
12803
+ return { positions: compactPositions, indices: compactIndices };
12804
+ }
12805
+
12806
+ // node_modules/@tscircuit/jscad/lib/index.ts
12807
+ var jscad2 = withReferences();
12808
+ var {
12809
+ booleans,
12810
+ colors,
12811
+ curves,
12812
+ expansions,
12813
+ extrusions,
12814
+ geometries,
12815
+ hulls,
12816
+ maths,
12817
+ measurements,
12818
+ modifiers,
12819
+ primitives,
12820
+ text,
12821
+ transforms,
12822
+ utils,
12823
+ references
12824
+ } = jscad2;
12825
+
12826
+ // lib/vanilla/render.ts
12827
+ var isVNode = (n) => n && typeof n === "object" && "type" in n;
12828
+ var degToRad = (v) => {
12829
+ if (typeof v === "number") return v;
12830
+ if (typeof v === "string") {
12831
+ const m = /^(-?\d+(?:\.\d+)?)\s*deg$/i.exec(v);
12832
+ if (m) return parseFloat(m[1]) * Math.PI / 180;
12833
+ const n = Number(v);
12834
+ if (!Number.isNaN(n)) return n;
12835
+ }
12836
+ return 0;
12837
+ };
12838
+ var toVec3 = (v) => {
12839
+ if (Array.isArray(v))
12840
+ return [Number(v[0]) || 0, Number(v[1]) || 0, Number(v[2]) || 0];
12841
+ if (typeof v === "object" && v)
12842
+ return [Number(v.x) || 0, Number(v.y) || 0, Number(v.z) || 0];
12843
+ return [0, 0, 0];
12844
+ };
12845
+ var assertFiniteFeatureTransform = (values) => {
12846
+ if (!values.every(Number.isFinite))
12847
+ throw new Error("JSCAD reference feature transforms must be finite");
12848
+ };
12849
+ var transformFeatureContext = (context, local) => {
12850
+ if (!context.referenceFeatures) return context;
12851
+ const { mat4 } = context.jscad.maths;
12852
+ const matrix = mat4.multiply(mat4.create(), context.matrix, local);
12853
+ assertFiniteFeatureTransform(matrix);
12854
+ return { ...context, matrix };
12855
+ };
12856
+ var validateFeatureName = (name) => {
12857
+ if (name !== void 0 && (typeof name !== "string" || !name.trim()))
12858
+ throw new Error("Named JSCAD features require a nonblank name");
12859
+ };
12860
+ var recordFeature = (context, name, geometry) => {
12861
+ if (!context.referenceFeatures || name === void 0) return;
12862
+ if (Object.hasOwn(context.referenceFeatures, name))
12863
+ throw new Error(`Duplicate JSCAD feature name "${name}"`);
12864
+ const { geometries: geometries9 } = context.jscad;
12865
+ if (!geometries9.geom2.isA(geometry) && !geometries9.path2.isA(geometry) && !geometries9.geom3.isA(geometry))
12866
+ throw new Error(`Named JSCAD feature "${name}" requires native geometry`);
12867
+ assertFiniteFeatureTransform(context.matrix);
12868
+ context.referenceFeatures[name] = {
12869
+ geometry,
12870
+ matrix: [...context.matrix]
12871
+ };
12872
+ };
12873
+ function renderNode(node, colorCtx, renderCtx) {
12874
+ const {
12875
+ jscad: { primitives: primitives9, booleans: booleans5, hulls: hulls2, geometries: geometries9, extrusions: extrusions9, transforms: transforms3 }
12876
+ } = renderCtx;
12877
+ if (node == null || node === false) return [];
12878
+ if (Array.isArray(node))
12879
+ return node.flatMap((n) => renderNode(n, colorCtx, renderCtx));
12880
+ if (!isVNode(node)) return [];
12881
+ const { type, props, children } = node;
12882
+ if (props?.material) {
12883
+ const { material, ...rest } = props;
12884
+ return renderNode({ ...node, props: rest }, colorCtx, renderCtx).map(
12885
+ (entry) => ({
12886
+ ...entry,
12887
+ material: { ...material },
12888
+ geom: { ...entry.geom, material: { ...material } }
12889
+ })
12890
+ );
12891
+ }
12892
+ if (type === Fragment) {
12893
+ return (children ?? []).flatMap((c) => renderNode(c, colorCtx, renderCtx));
12894
+ }
12895
+ if (type === Colorize) {
12896
+ const newColor = props?.color;
12897
+ return (children ?? []).flatMap(
12898
+ (c) => renderNode(c, newColor ?? colorCtx, renderCtx)
12899
+ );
12900
+ }
12901
+ if (type === Translate) {
12902
+ const offset = props?.offset ?? props?.center ?? { x: props?.x, y: props?.y, z: props?.z };
12903
+ if (renderCtx.referenceFeatures)
12904
+ assertFiniteFeatureTransform(
12905
+ (Array.isArray(offset) ? offset.slice(0, 3) : [offset?.x, offset?.y, offset?.z]).map((value) => Number(value ?? 0))
12906
+ );
12907
+ const off = toVec3(offset);
12908
+ const { mat4 } = renderCtx.jscad.maths;
12909
+ const childContext = transformFeatureContext(
12910
+ renderCtx,
12911
+ mat4.fromTranslation(mat4.create(), off)
12912
+ );
12913
+ const geoms = (children ?? []).flatMap(
12914
+ (c) => renderNode(c, colorCtx, childContext)
12915
+ );
12916
+ return geoms.map(({ geom, color, material }) => ({
12917
+ material,
12918
+ geom: transforms3.translate(off, geom),
12919
+ color: color ?? colorCtx
12920
+ }));
12921
+ }
12922
+ if (type === Rotate) {
12923
+ const angles = props?.angles ?? props?.rotation;
12924
+ if (renderCtx.referenceFeatures)
12925
+ assertFiniteFeatureTransform(
12926
+ (Array.isArray(angles) ? angles.slice(0, 3) : [props?.x, props?.y, props?.z]).map(
12927
+ (value) => Number(
12928
+ typeof value === "string" ? value.replace(/\s*deg$/i, "") : value ?? 0
12929
+ )
12930
+ )
12931
+ );
12932
+ const rot = Array.isArray(angles) ? [degToRad(angles[0]), degToRad(angles[1]), degToRad(angles[2])] : [
12933
+ degToRad(props?.x ?? 0),
12934
+ degToRad(props?.y ?? 0),
12935
+ degToRad(props?.z ?? 0)
12936
+ ];
12937
+ const { mat4 } = renderCtx.jscad.maths;
12938
+ const childContext = transformFeatureContext(
12939
+ renderCtx,
12940
+ mat4.fromTaitBryanRotation(mat4.create(), rot[2], rot[1], rot[0])
12941
+ );
12942
+ const geoms = (children ?? []).flatMap(
12943
+ (c) => renderNode(c, colorCtx, childContext)
12944
+ );
12945
+ return geoms.map(({ geom, color, material }) => ({
12946
+ material,
12947
+ geom: transforms3.rotateZ(
12948
+ rot[2],
12949
+ transforms3.rotateY(rot[1], transforms3.rotateX(rot[0], geom))
12950
+ ),
12951
+ color
12952
+ }));
12953
+ }
12954
+ if (type === Union || type === Subtract || type === Hull) {
12955
+ const entries = (children ?? []).flatMap(
12956
+ (c) => renderNode(c, colorCtx, renderCtx)
12957
+ );
12958
+ const geoms = entries.map((g) => g.geom);
12959
+ if (geoms.length === 0) return [];
12960
+ let geom;
12961
+ if (type === Union) geom = booleans5.union(geoms);
12962
+ else if (type === Subtract)
12963
+ geom = booleans5.subtract(geoms[0], geoms.slice(1));
12964
+ else geom = hulls2.hull(geoms);
12965
+ return [
12966
+ {
12967
+ geom,
12968
+ color: colorCtx,
12969
+ material: type === Subtract ? entries[0]?.material : void 0
12970
+ }
12971
+ ];
12972
+ }
12973
+ if (type === Custom) {
12974
+ const { name, reference, geometry } = props;
12975
+ validateFeatureName(name);
12976
+ if (reference && name === void 0)
12977
+ throw new Error("Named JSCAD features require a nonblank name");
12978
+ recordFeature(renderCtx, name, geometry);
12979
+ if (reference) return [];
12980
+ return [{ geom: props.geometry, color: colorCtx }];
12981
+ }
12982
+ if (type === Polygon) {
12983
+ const points = props?.points ?? [];
12984
+ const origin = points[0] ?? [0, 0];
12985
+ const area = points.reduce((sum, point, index) => {
12986
+ const next = points[(index + 1) % points.length];
12987
+ return sum + (point[0] - origin[0]) * (next[1] - origin[1]) - (next[0] - origin[0]) * (point[1] - origin[1]);
12988
+ }, 0);
12989
+ const oriented = area < 0 ? [...points].reverse() : points;
12990
+ const g2 = geometries9.geom2.fromPoints(oriented);
12991
+ return [{ geom: g2, color: colorCtx ?? props?.color }];
12992
+ }
12993
+ if (type === ExtrudeLinear) {
12994
+ const { topOutlineName, bottomOutlineName, twistAngle, twistSteps } = props;
12995
+ const namedOutline = topOutlineName !== void 0 || bottomOutlineName !== void 0;
12996
+ const height10 = props?.height ?? props?.h ?? 1;
12997
+ validateFeatureName(topOutlineName);
12998
+ validateFeatureName(bottomOutlineName);
12999
+ if (namedOutline) {
13000
+ if (!Number.isFinite(height10) || !Number.isFinite(twistAngle ?? 0))
13001
+ throw new Error(
13002
+ "Named extrusion outlines require finite height and twistAngle"
13003
+ );
13004
+ if (twistSteps !== void 0 && (!Number.isInteger(twistSteps) || twistSteps < 1))
13005
+ throw new Error(
13006
+ "Named extrusion outlines require positive integer twistSteps"
13007
+ );
13008
+ }
13009
+ const entries = (children ?? []).flatMap(
13010
+ (c) => renderNode(c, colorCtx, renderCtx)
13011
+ );
13012
+ const geoms2 = entries.map((g) => g.geom);
13013
+ if (geoms2.length === 0) return [];
13014
+ if (namedOutline && geoms2.length !== 1)
13015
+ throw new Error("Named extrusion outlines require exactly one profile");
13016
+ const base2 = geoms2.length > 1 ? booleans5.union(geoms2) : geoms2[0];
13017
+ if (namedOutline && !geometries9.geom2.isA(base2) && !(geometries9.path2.isA(base2) && base2.isClosed))
13018
+ throw new Error(
13019
+ "Named extrusion outlines require a geom2 or closed path2 profile"
13020
+ );
13021
+ if (namedOutline && renderCtx.referenceFeatures) {
13022
+ const { mat4 } = renderCtx.jscad.maths;
13023
+ const topContext = transformFeatureContext(
13024
+ renderCtx,
13025
+ mat4.multiply(
13026
+ mat4.create(),
13027
+ mat4.fromTranslation(mat4.create(), [0, 0, height10]),
13028
+ mat4.fromZRotation(mat4.create(), twistAngle ?? 0)
13029
+ )
13030
+ );
13031
+ recordFeature(topContext, topOutlineName, base2);
13032
+ recordFeature(renderCtx, bottomOutlineName, base2);
13033
+ }
13034
+ const g3 = extrusions9.extrudeLinear(
13035
+ {
13036
+ height: height10,
13037
+ ...twistAngle !== void 0 ? { twistAngle } : {},
13038
+ ...twistSteps !== void 0 ? { twistSteps } : {}
13039
+ },
13040
+ base2
13041
+ );
13042
+ return [
13043
+ {
13044
+ geom: g3,
13045
+ color: colorCtx ?? props?.color,
13046
+ material: entries.length === 1 ? entries[0]?.material : void 0
13047
+ }
13048
+ ];
13049
+ }
13050
+ if (type === Cuboid || type === Cube || type === Cylinder || type === Sphere || type === RoundedCuboid || type === RoundedCylinder) {
13051
+ let g;
13052
+ if (type === Cuboid) {
13053
+ const size = props?.size ?? [1, 1, 1];
13054
+ const offset = props?.offset;
13055
+ const center = props?.center ?? (offset ? [offset[0], offset[1], offset[2]] : [0, 0, 0]);
13056
+ g = primitives9.cuboid({ size, center });
13057
+ } else if (type === Cube) {
13058
+ const size = props?.size ?? 1;
13059
+ const offset = props?.offset;
13060
+ const center = props?.center ?? (offset ? [offset[0], offset[1], offset[2]] : [0, 0, 0]);
13061
+ g = primitives9.cube({ size, center });
13062
+ } else if (type === Cylinder) {
13063
+ const height10 = props?.height ?? 1;
13064
+ const radius = props?.radius ?? 1;
13065
+ const center = props?.center ?? [0, 0, 0];
13066
+ g = primitives9.cylinder({ height: height10, radius, center });
13067
+ } else if (type === Sphere) {
13068
+ const radius = props?.radius ?? 1;
13069
+ const center = props?.center ?? [0, 0, 0];
13070
+ g = primitives9.sphere({ radius, center });
13071
+ } else if (type === RoundedCylinder) {
13072
+ const height10 = props?.height ?? 1;
13073
+ const radius = props?.radius ?? 1;
13074
+ const roundRadius = props?.roundRadius ?? 0.1;
13075
+ const center = props?.center ?? [0, 0, 0];
13076
+ g = primitives9.roundedCylinder({ height: height10, radius, roundRadius, center });
13077
+ } else {
13078
+ const size = props?.size ?? [1, 1, 1];
13079
+ const roundRadius = props?.roundRadius ?? 0.1;
13080
+ const center = props?.center ?? [0, 0, 0];
13081
+ g = primitives9.roundedCuboid({ size, roundRadius, center });
13082
+ }
13083
+ return [{ geom: g, color: colorCtx ?? props?.color }];
13084
+ }
13085
+ if (typeof type === "function") {
13086
+ const out = type(props ?? {});
13087
+ return renderNode(out, colorCtx, renderCtx);
13088
+ }
13089
+ return (children ?? []).flatMap((c) => renderNode(c, colorCtx, renderCtx));
13090
+ }
13091
+ function render(root, jscad22) {
13092
+ jscad22 = withReferences(
13093
+ jscad22
13094
+ );
13095
+ const geometries9 = renderNode(root, void 0, { jscad: jscad22 });
13096
+ return {
13097
+ geometries: geometries9.map(
13098
+ (entry) => entry.material ? { ...entry, geom: { ...entry.geom, material: entry.material } } : entry
13099
+ )
13100
+ };
13101
+ }
13102
+ function renderToJscadModel(root, jscad22) {
13103
+ jscad22 = withReferences(
13104
+ jscad22
13105
+ );
13106
+ const referenceFeatures = /* @__PURE__ */ Object.create(null);
13107
+ const geometries9 = renderNode(root, void 0, {
13108
+ jscad: jscad22,
13109
+ referenceFeatures,
13110
+ matrix: jscad22.maths.mat4.create()
13111
+ });
13112
+ return {
13113
+ geometries: geometries9.map(({ geom, color }) => {
13114
+ if (color === void 0) return geom;
13115
+ const { colors: colors2 } = jscad22;
13116
+ const rgb = typeof color === "string" ? color.startsWith("#") ? colors2.hexToRgb(
13117
+ /^#[\da-f]{3,4}$/i.test(color) ? `#${[...color.slice(1)].map((c) => c + c).join("")}` : color
13118
+ ) : colors2.colorNameToRgb(color) : color;
13119
+ if (!rgb) throw new Error(`Unknown JSCAD color "${color}"`);
13120
+ return colors2.colorize(rgb, geom);
13121
+ }),
13122
+ referenceFeatures
13123
+ };
13124
+ }
13125
+
12386
13126
  // lib/vanilla/primitives.ts
12387
13127
  var Cuboid = /* @__PURE__ */ Symbol("Cuboid");
12388
13128
  var Cube = /* @__PURE__ */ Symbol("Cube");
@@ -12573,11 +13313,11 @@ var ModelRendererRegistry = class {
12573
13313
  };
12574
13314
 
12575
13315
  // lib/models/anglebar/geometry.ts
12576
- import jscad from "@jscad/modeling";
12577
- var { primitives, extrusions, geometries, modifiers, measurements } = jscad;
12578
- var generalize = modifiers.generalize;
12579
- var { rectangle, roundedRectangle, polygon } = primitives;
12580
- var profile = (shape49, height10) => extrusions.extrudeLinear({ height: height10 }, shape49);
13316
+ import jscad3 from "@jscad/modeling";
13317
+ var { primitives: primitives2, extrusions: extrusions2, geometries: geometries2, modifiers: modifiers2, measurements: measurements2 } = jscad3;
13318
+ var generalize = modifiers2.generalize;
13319
+ var { rectangle, roundedRectangle, polygon } = primitives2;
13320
+ var profile = (shape49, height10) => extrusions2.extrudeLinear({ height: height10 }, shape49);
12581
13321
  function filletProfile(points, radii, width10, height10) {
12582
13322
  const outline = [];
12583
13323
  for (let i = 0; i < points.length; i++) {
@@ -12636,7 +13376,7 @@ function createAngleBarMesh(input) {
12636
13376
  { snap: true, triangulate: true },
12637
13377
  createAngleBarGeom(input)
12638
13378
  );
12639
- const epsilon = Math.max(...measurements.measureDimensions(geom)) * 1e-10;
13379
+ const epsilon = Math.max(...measurements2.measureDimensions(geom)) * 1e-10;
12640
13380
  const positions = [];
12641
13381
  const indices = [];
12642
13382
  const lookup = /* @__PURE__ */ new Map();
@@ -12650,7 +13390,7 @@ function createAngleBarMesh(input) {
12650
13390
  }
12651
13391
  return index;
12652
13392
  };
12653
- for (const poly of geometries.geom3.toPolygons(geom)) {
13393
+ for (const poly of geometries2.geom3.toPolygons(geom)) {
12654
13394
  for (let i = 1; i < poly.vertices.length - 1; i++) {
12655
13395
  const a = poly.vertices[0], b = poly.vertices[i], c = poly.vertices[i + 1];
12656
13396
  const u = b.map((x, j) => x - a[j]), v = c.map((x, j) => x - a[j]);
@@ -12683,7 +13423,7 @@ function register55(registry2) {
12683
13423
  }
12684
13424
 
12685
13425
  // lib/mechanical/indexedMeshToGeom3.ts
12686
- import jscad2 from "@jscad/modeling";
13426
+ import jscad4 from "@jscad/modeling";
12687
13427
  function indexedMeshToGeom3(mesh) {
12688
13428
  const polygons = [];
12689
13429
  for (let i = 0; i < mesh.indices.length; i += 3)
@@ -12694,7 +13434,7 @@ function indexedMeshToGeom3(mesh) {
12694
13434
  mesh.positions[index * 3 + 2]
12695
13435
  ])
12696
13436
  );
12697
- return jscad2.geometries.geom3.fromPoints(polygons);
13437
+ return jscad4.geometries.geom3.fromPoints(polygons);
12698
13438
  }
12699
13439
 
12700
13440
  // lib/models/ballbearing/mesh.ts
@@ -12823,11 +13563,11 @@ function createBallBearingMesh(input = {}, options = {}) {
12823
13563
  [ri + 0.15 * (ro - ri), 0.5 * t],
12824
13564
  [ro - 0.15 * (ro - ri), 0.5 * t]
12825
13565
  ];
12826
- const profile6 = sign === -1 ? shape49 : shape49.map(([r, z]) => [r, d.width - z]).reverse();
13566
+ const profile5 = sign === -1 ? shape49 : shape49.map(([r, z]) => [r, d.width - z]).reverse();
12827
13567
  parts.push({
12828
13568
  name: `${face2} ${sign < 0 ? "lower" : "upper"}`,
12829
13569
  color: face2 === "sealed" ? "#252a30" : "#b5bbc3",
12830
- mesh: revolve(profile6, segments)
13570
+ mesh: revolve(profile5, segments)
12831
13571
  });
12832
13572
  }
12833
13573
  return { ...combine(parts), parts };
@@ -12844,21 +13584,21 @@ function checkPrecision(lengths25) {
12844
13584
  "Bearing dimensions exceed the renderer's numerical resolution"
12845
13585
  );
12846
13586
  }
12847
- function revolve(profile6, segments) {
13587
+ function revolve(profile5, segments) {
12848
13588
  const positions = [];
12849
13589
  const indices = [];
12850
- for (const [radius, z] of profile6)
13590
+ for (const [radius, z] of profile5)
12851
13591
  for (let i = 0; i < segments; i++) {
12852
13592
  const angle = i * Math.PI * 2 / segments;
12853
13593
  const r = typeof radius === "number" ? radius : radius(angle);
12854
13594
  positions.push(r * Math.cos(angle), r * Math.sin(angle), z);
12855
13595
  }
12856
- for (let j = 0; j < profile6.length; j++)
13596
+ for (let j = 0; j < profile5.length; j++)
12857
13597
  for (let i = 0; i < segments; i++) {
12858
13598
  const a = j * segments + i;
12859
13599
  const b = j * segments + (i + 1) % segments;
12860
- const c = (j + 1) % profile6.length * segments + (i + 1) % segments;
12861
- const e = (j + 1) % profile6.length * segments + i;
13600
+ const c = (j + 1) % profile5.length * segments + (i + 1) % segments;
13601
+ const e = (j + 1) % profile5.length * segments + i;
12862
13602
  indices.push(a, b, c, a, c, e);
12863
13603
  }
12864
13604
  return { positions, indices };
@@ -12869,7 +13609,7 @@ function annularSector(inner, outer, z0, z1, start, end, segments) {
12869
13609
  Math.ceil((end - start) / (2 * Math.PI) * segments)
12870
13610
  );
12871
13611
  const count = steps + 1;
12872
- const profile6 = [
13612
+ const profile5 = [
12873
13613
  [outer, z0],
12874
13614
  [outer, z1],
12875
13615
  [inner, z1],
@@ -12877,7 +13617,7 @@ function annularSector(inner, outer, z0, z1, start, end, segments) {
12877
13617
  ];
12878
13618
  const positions = [];
12879
13619
  const indices = [];
12880
- for (const [r, z] of profile6)
13620
+ for (const [r, z] of profile5)
12881
13621
  for (let i = 0; i <= steps; i++) {
12882
13622
  const angle = start + (end - start) * i / steps;
12883
13623
  positions.push(r * Math.cos(angle), r * Math.sin(angle), z);
@@ -13068,7 +13808,7 @@ function createBallTransferUnitMesh(input = {}) {
13068
13808
  );
13069
13809
  const segments = 96;
13070
13810
  const latitude = 48;
13071
- const profile6 = [
13811
+ const profile5 = [
13072
13812
  [d.bodyRadius, 0],
13073
13813
  [d.bodyRadius, d.flangeBottomZ],
13074
13814
  [d.flangeRadius, d.flangeBottomZ],
@@ -13081,12 +13821,12 @@ function createBallTransferUnitMesh(input = {}) {
13081
13821
  for (let j = 1; j < latitude; j++) {
13082
13822
  const angle = j * Math.PI / latitude;
13083
13823
  if ((angle - openingAngle) * d.socketRadius > resolution7)
13084
- profile6.push([
13824
+ profile5.push([
13085
13825
  d.socketRadius * Math.sin(angle),
13086
13826
  d.ballCenterZ + d.socketRadius * Math.cos(angle)
13087
13827
  ]);
13088
13828
  }
13089
- profile6.push([0, d.socketBottomZ], [0, 0]);
13829
+ profile5.push([0, d.socketBottomZ], [0, 0]);
13090
13830
  const holes = d.mountingHoles.map(
13091
13831
  ({ x, y, diameter }) => circularProfile(x, y, diameter / 2, segments)
13092
13832
  );
@@ -13094,7 +13834,7 @@ function createBallTransferUnitMesh(input = {}) {
13094
13834
  const housing = joinProfileMeshes([
13095
13835
  // Cap faces are triangulated with all openings, rather than covered by
13096
13836
  // annular triangles and repaired afterward with Boolean subtraction.
13097
- revolve2(profile6, segments, /* @__PURE__ */ new Set([1, 3])),
13837
+ revolve2(profile5, segments, /* @__PURE__ */ new Set([1, 3])),
13098
13838
  cap(
13099
13839
  flangeOutline,
13100
13840
  [circularProfile(0, 0, d.bodyRadius, segments), ...holes],
@@ -13131,10 +13871,10 @@ function createBallTransferUnitMesh(input = {}) {
13131
13871
  ];
13132
13872
  return { positions, indices, parts };
13133
13873
  }
13134
- function revolve2(profile6, segments, omittedEdges = /* @__PURE__ */ new Set()) {
13874
+ function revolve2(profile5, segments, omittedEdges = /* @__PURE__ */ new Set()) {
13135
13875
  const positions = [];
13136
13876
  const indices = [];
13137
- const rings = profile6.map(([radius, z]) => {
13877
+ const rings = profile5.map(([radius, z]) => {
13138
13878
  const start = positions.length / 3;
13139
13879
  const count = radius === 0 ? 1 : segments;
13140
13880
  for (let i = 0; i < count; i++) {
@@ -13416,11 +14156,11 @@ function register59(registry2) {
13416
14156
  }
13417
14157
 
13418
14158
  // lib/models/channelbar/geometry.ts
13419
- import jscad3 from "@jscad/modeling";
13420
- var { primitives: primitives2, extrusions: extrusions2, geometries: geometries2, modifiers: modifiers2, measurements: measurements2 } = jscad3;
13421
- var generalize2 = modifiers2.generalize;
13422
- var { rectangle: rectangle2, roundedRectangle: roundedRectangle2, polygon: polygon2 } = primitives2;
13423
- var profile2 = (shape49, height10) => extrusions2.extrudeLinear({ height: height10 }, shape49);
14159
+ import jscad5 from "@jscad/modeling";
14160
+ var { primitives: primitives3, extrusions: extrusions3, geometries: geometries3, modifiers: modifiers3, measurements: measurements3 } = jscad5;
14161
+ var generalize2 = modifiers3.generalize;
14162
+ var { rectangle: rectangle2, roundedRectangle: roundedRectangle2, polygon: polygon2 } = primitives3;
14163
+ var profile2 = (shape49, height10) => extrusions3.extrudeLinear({ height: height10 }, shape49);
13424
14164
  function filletProfile2(points, radii, width10, height10) {
13425
14165
  const outline = [];
13426
14166
  for (let i = 0; i < points.length; i++) {
@@ -13490,7 +14230,7 @@ function createChannelBarMesh(input) {
13490
14230
  { snap: true, triangulate: true },
13491
14231
  createChannelBarGeom(input)
13492
14232
  );
13493
- const epsilon = Math.max(...measurements2.measureDimensions(geom)) * 1e-10;
14233
+ const epsilon = Math.max(...measurements3.measureDimensions(geom)) * 1e-10;
13494
14234
  const positions = [];
13495
14235
  const indices = [];
13496
14236
  const lookup = /* @__PURE__ */ new Map();
@@ -13504,7 +14244,7 @@ function createChannelBarMesh(input) {
13504
14244
  }
13505
14245
  return index;
13506
14246
  };
13507
- for (const poly of geometries2.geom3.toPolygons(geom)) {
14247
+ for (const poly of geometries3.geom3.toPolygons(geom)) {
13508
14248
  for (let i = 1; i < poly.vertices.length - 1; i++) {
13509
14249
  const a = poly.vertices[0], b = poly.vertices[i], c = poly.vertices[i + 1];
13510
14250
  const u = b.map((x, j) => x - a[j]), v = c.map((x, j) => x - a[j]);
@@ -13537,10 +14277,10 @@ function register60(registry2) {
13537
14277
  }
13538
14278
 
13539
14279
  // lib/models/clampingshaftcollar/mesh.ts
13540
- import jscad5 from "@jscad/modeling";
14280
+ import jscad7 from "@jscad/modeling";
13541
14281
 
13542
14282
  // lib/mechanical/shaft-mount-geometry.ts
13543
- import jscad4 from "@jscad/modeling";
14283
+ import jscad6 from "@jscad/modeling";
13544
14284
  var bodySegments = 64;
13545
14285
  var threadSegments = 24;
13546
14286
  var samplesPerTurn = 12;
@@ -13583,22 +14323,22 @@ function createAnnularSleeve({
13583
14323
  [chamfer, boreARadius, true],
13584
14324
  [0, boreARadius + chamfer, true]
13585
14325
  ];
13586
- const profile6 = raw.filter(
14326
+ const profile5 = raw.filter(
13587
14327
  ([z, r], i) => i === 0 || z !== raw[i - 1][0] || r !== raw[i - 1][1]
13588
14328
  );
13589
14329
  const positions = [];
13590
14330
  const indices = [];
13591
- for (const [z, r, isBore] of profile6)
14331
+ for (const [z, r, isBore] of profile5)
13592
14332
  for (let i = 0; i < bodySegments; i++) {
13593
14333
  const angle = (i + (isBore ? 0.5 : 0)) * Math.PI * 2 / bodySegments;
13594
14334
  const radius = isBore ? r / cosine : r;
13595
14335
  positions.push(radius * Math.cos(angle), radius * Math.sin(angle), z);
13596
14336
  }
13597
- for (let row = 0; row < profile6.length; row++)
14337
+ for (let row = 0; row < profile5.length; row++)
13598
14338
  for (let i = 0; i < bodySegments; i++) {
13599
14339
  const next = (i + 1) % bodySegments;
13600
14340
  const a = row * bodySegments + i, b = row * bodySegments + next;
13601
- const c = (row + 1) % profile6.length * bodySegments + next, d = (row + 1) % profile6.length * bodySegments + i;
14341
+ const c = (row + 1) % profile5.length * bodySegments + next, d = (row + 1) % profile5.length * bodySegments + i;
13602
14342
  indices.push(a, b, c, a, c, d);
13603
14343
  }
13604
14344
  return indexedMeshToGeom3({ positions, indices });
@@ -13656,10 +14396,10 @@ function createMountingHoleCutter(hole) {
13656
14396
  function subtractShaftMountParts(body, ...cutters) {
13657
14397
  const factor = 100;
13658
14398
  const scaled = [body, ...cutters].map(
13659
- (geometry) => jscad4.transforms.scale([factor, factor, factor], geometry)
14399
+ (geometry) => jscad6.transforms.scale([factor, factor, factor], geometry)
13660
14400
  );
13661
- const result = jscad4.booleans.subtract(scaled[0], ...scaled.slice(1));
13662
- return jscad4.transforms.scale([1 / factor, 1 / factor, 1 / factor], result);
14401
+ const result = jscad6.booleans.subtract(scaled[0], ...scaled.slice(1));
14402
+ return jscad6.transforms.scale([1 / factor, 1 / factor, 1 / factor], result);
13663
14403
  }
13664
14404
  function finishShaftMountMesh(geometry) {
13665
14405
  const positions = [];
@@ -13685,7 +14425,7 @@ function finishShaftMountMesh(geometry) {
13685
14425
  vertices.set(key, [...vertices.get(key) ?? [], index]);
13686
14426
  return index;
13687
14427
  };
13688
- const polygons = jscad4.geometries.geom3.toPolygons(geometry).map(
14428
+ const polygons = jscad6.geometries.geom3.toPolygons(geometry).map(
13689
14429
  (polygon4) => polygon4.vertices.map(weld).filter((id, i, ids) => id !== ids[(i + ids.length - 1) % ids.length])
13690
14430
  ).map((ids) => [...new Set(ids)]).filter((ids) => ids.length >= 3).filter((ids) => {
13691
14431
  let longest = 0;
@@ -13708,11 +14448,11 @@ function finishShaftMountMesh(geometry) {
13708
14448
  return Math.hypot(...delta.map((v, axis) => v - t * direction[axis])) >= tolerance;
13709
14449
  });
13710
14450
  });
13711
- const edgeKey = (a, b) => `${Math.min(a, b)},${Math.max(a, b)}`;
14451
+ const edgeKey2 = (a, b) => `${Math.min(a, b)},${Math.max(a, b)}`;
13712
14452
  const edges = /* @__PURE__ */ new Map();
13713
14453
  for (const polygon4 of polygons)
13714
14454
  for (let i = 0; i < polygon4.length; i++) {
13715
- const a = polygon4[i], b = polygon4[(i + 1) % polygon4.length], key = edgeKey(a, b);
14455
+ const a = polygon4[i], b = polygon4[(i + 1) % polygon4.length], key = edgeKey2(a, b);
13716
14456
  const edge = edges.get(key) ?? { a, b, count: 0 };
13717
14457
  edge.count++;
13718
14458
  edges.set(key, edge);
@@ -13797,7 +14537,7 @@ function createClampingShaftCollarMesh(input) {
13797
14537
  });
13798
14538
  const s = dimensions5.split;
13799
14539
  const epsilon = 1e-4;
13800
- const slit = jscad5.primitives.cuboid({
14540
+ const slit = jscad7.primitives.cuboid({
13801
14541
  size: [
13802
14542
  s.xMax - s.xMin + epsilon,
13803
14543
  s.yMax - s.yMin,
@@ -14372,7 +15112,7 @@ function createFlangedBushingMesh(input) {
14372
15112
  const ri = d.innerDiameter / 2;
14373
15113
  const ro = d.outerDiameter / 2;
14374
15114
  const rf = d.flangeDiameter / 2;
14375
- const profile6 = [
15115
+ const profile5 = [
14376
15116
  [rf, 0],
14377
15117
  [rf, d.shoulderZ],
14378
15118
  [ro, d.shoulderZ],
@@ -14383,14 +15123,14 @@ function createFlangedBushingMesh(input) {
14383
15123
  const segments = 96;
14384
15124
  const positions = [];
14385
15125
  const indices = [];
14386
- for (const [radius, z] of profile6)
15126
+ for (const [radius, z] of profile5)
14387
15127
  for (let i = 0; i < segments; i++) {
14388
15128
  const angle = i * Math.PI * 2 / segments;
14389
15129
  positions.push(radius * Math.cos(angle), radius * Math.sin(angle), z);
14390
15130
  }
14391
- for (let ring = 0; ring < profile6.length; ring++) {
15131
+ for (let ring = 0; ring < profile5.length; ring++) {
14392
15132
  const a = ring * segments;
14393
- const b = (ring + 1) % profile6.length * segments;
15133
+ const b = (ring + 1) % profile5.length * segments;
14394
15134
  for (let i = 0; i < segments; i++) {
14395
15135
  const next = (i + 1) % segments;
14396
15136
  indices.push(a + i, a + next, b + next, a + i, b + next, b + i);
@@ -14535,15 +15275,15 @@ function register67(registry2) {
14535
15275
  }
14536
15276
 
14537
15277
  // lib/models/flatcableclip/geometry.ts
14538
- import jscad6 from "@jscad/modeling";
15278
+ import jscad8 from "@jscad/modeling";
14539
15279
  var {
14540
- primitives: primitives3,
14541
- extrusions: extrusions3,
14542
- transforms,
14543
- booleans,
14544
- geometries: geometries3,
14545
- measurements: measurements3
14546
- } = jscad6;
15280
+ primitives: primitives4,
15281
+ extrusions: extrusions4,
15282
+ transforms: transforms2,
15283
+ booleans: booleans2,
15284
+ geometries: geometries4,
15285
+ measurements: measurements4
15286
+ } = jscad8;
14547
15287
  function createFlatCableClipSolid(input) {
14548
15288
  const p = flatCableClipModelPropsSchema.parse(input);
14549
15289
  const legOuter = p.innerWidth / 2 + p.thickness, half = legOuter + p.footLength;
@@ -14561,25 +15301,25 @@ function createFlatCableClipSolid(input) {
14561
15301
  [-legOuter, p.thickness],
14562
15302
  [-half, p.thickness]
14563
15303
  ];
14564
- const bridge = transforms.translate(
15304
+ const bridge = transforms2.translate(
14565
15305
  [0, p.depth / 2, 0],
14566
- transforms.rotateX(
15306
+ transforms2.rotateX(
14567
15307
  Math.PI / 2,
14568
- extrusions3.extrudeLinear(
15308
+ extrusions4.extrudeLinear(
14569
15309
  { height: p.depth },
14570
- primitives3.polygon({ points })
15310
+ primitives4.polygon({ points })
14571
15311
  )
14572
15312
  )
14573
15313
  );
14574
15314
  const bores = [-1, 1].map(
14575
- (sign) => primitives3.cylinder({
15315
+ (sign) => primitives4.cylinder({
14576
15316
  radius: p.holeDiameter / 2,
14577
15317
  height: p.thickness + 2,
14578
15318
  center: [sign * p.holePitch / 2, 0, p.thickness / 2],
14579
15319
  segments: 96
14580
15320
  })
14581
15321
  );
14582
- return booleans.subtract(bridge, ...bores);
15322
+ return booleans2.subtract(bridge, ...bores);
14583
15323
  }
14584
15324
  function createFlatCableClipMesh(input) {
14585
15325
  const p = flatCableClipModelPropsSchema.parse(input);
@@ -14590,8 +15330,8 @@ function createFlatCableClipMesh(input) {
14590
15330
  [0, p.thickness, p.innerHeight, p.innerHeight + p.thickness]
14591
15331
  ];
14592
15332
  const geom = createFlatCableClipSolid(p);
14593
- const tolerance = Math.max(...measurements3.measureDimensions(geom)) * 1e-5;
14594
- const polygons = geometries3.geom3.toPolygons(geom).map(
15333
+ const tolerance = Math.max(...measurements4.measureDimensions(geom)) * 1e-5;
15334
+ const polygons = geometries4.geom3.toPolygons(geom).map(
14595
15335
  (poly) => poly.vertices.map(
14596
15336
  (point) => point.map((value, axis) => {
14597
15337
  const nearest = planes[axis].reduce(
@@ -14601,7 +15341,7 @@ function createFlatCableClipMesh(input) {
14601
15341
  })
14602
15342
  )
14603
15343
  );
14604
- return finishShaftMountMesh(geometries3.geom3.fromPoints(polygons));
15344
+ return finishShaftMountMesh(geometries4.geom3.fromPoints(polygons));
14605
15345
  }
14606
15346
  function createFlatCableClipGeom(input) {
14607
15347
  return indexedMeshToGeom3(createFlatCableClipMesh(input));
@@ -16504,7 +17244,7 @@ function register79(registry2) {
16504
17244
  }
16505
17245
 
16506
17246
  // lib/utils/nemaMotorAssemblyGeometry.ts
16507
- import jscad7 from "@jscad/modeling";
17247
+ import jscad9 from "@jscad/modeling";
16508
17248
  function nema34AssemblyCenters(p) {
16509
17249
  const edge = p.bodyWidth / 2;
16510
17250
  return [-1, 1].flatMap(
@@ -16514,16 +17254,16 @@ function nema34AssemblyCenters(p) {
16514
17254
  );
16515
17255
  }
16516
17256
  function cutNema34FrontRecesses(geometry, p) {
16517
- return jscad7.booleans.subtract(
17257
+ return jscad9.booleans.subtract(
16518
17258
  geometry,
16519
17259
  ...nema34AssemblyCenters(p).flatMap(([x, y]) => [
16520
- jscad7.primitives.cylinder({
17260
+ jscad9.primitives.cylinder({
16521
17261
  radius: 1.6,
16522
17262
  height: p.frontCapLength + 0.2,
16523
17263
  center: [x, y, -p.frontCapLength / 2],
16524
17264
  segments: 32
16525
17265
  }),
16526
- jscad7.primitives.cylinder({
17266
+ jscad9.primitives.cylinder({
16527
17267
  radius: 5,
16528
17268
  height: Math.min(4, p.frontCapLength / 2) + 0.1,
16529
17269
  center: [
@@ -16537,8 +17277,8 @@ function cutNema34FrontRecesses(geometry, p) {
16537
17277
  );
16538
17278
  }
16539
17279
  function createNema34FrontScrews(p) {
16540
- const head = jscad7.booleans.subtract(
16541
- jscad7.primitives.ellipsoid({
17280
+ const head = jscad9.booleans.subtract(
17281
+ jscad9.primitives.ellipsoid({
16542
17282
  radius: [3.2, 3.2, 1.5],
16543
17283
  center: [0, 0, -1.8],
16544
17284
  segments: 32
@@ -16547,22 +17287,22 @@ function createNema34FrontScrews(p) {
16547
17287
  [3.7, 0.8, 1.1],
16548
17288
  [0.8, 3.7, 1.1]
16549
17289
  ].map(
16550
- (size) => jscad7.primitives.cuboid({
17290
+ (size) => jscad9.primitives.cuboid({
16551
17291
  size,
16552
17292
  center: [0, 0, -0.8]
16553
17293
  })
16554
17294
  )
16555
17295
  );
16556
17296
  return nema34AssemblyCenters(p).map(
16557
- ([x, y]) => jscad7.transforms.translate([x, y, 0], head)
17297
+ ([x, y]) => jscad9.transforms.translate([x, y, 0], head)
16558
17298
  );
16559
17299
  }
16560
17300
 
16561
17301
  // lib/NemaMotor.tsx
16562
- import jscad9 from "@jscad/modeling";
17302
+ import jscad11 from "@jscad/modeling";
16563
17303
 
16564
17304
  // lib/utils/nemaMotorWireGeometry.ts
16565
- import jscad8 from "@jscad/modeling";
17305
+ import jscad10 from "@jscad/modeling";
16566
17306
 
16567
17307
  // lib/utils/nemaMotorParameters.ts
16568
17308
  var resolveNemaMotorProps = nemaMotorModelPropsSchema.parse.bind(nemaMotorModelPropsSchema);
@@ -16573,12 +17313,12 @@ function createNemaMotorWireGeometry(input) {
16573
17313
  if (p.noWires) return [];
16574
17314
  const { position } = getNemaMotorReferencePoints(p).wireside;
16575
17315
  const angle = p.wireSideAngle * Math.PI / 180;
16576
- const place = (geometry) => jscad8.transforms.translate(
17316
+ const place = (geometry) => jscad10.transforms.translate(
16577
17317
  [position.x, position.y, position.z],
16578
- jscad8.transforms.rotateZ(angle, geometry)
17318
+ jscad10.transforms.rotateZ(angle, geometry)
16579
17319
  );
16580
17320
  if (p.wireStubs) {
16581
- const colors = [
17321
+ const colors2 = [
16582
17322
  "#d53f3f",
16583
17323
  "#2463af",
16584
17324
  "#3b934b",
@@ -16589,17 +17329,17 @@ function createNemaMotorWireGeometry(input) {
16589
17329
  "#803e91"
16590
17330
  ];
16591
17331
  const wires = Array.from({ length: p.wireCount }, (_, i) => ({
16592
- color: colors[i],
17332
+ color: colors2[i],
16593
17333
  geometry: place(
16594
- jscad8.transforms.translate(
17334
+ jscad10.transforms.translate(
16595
17335
  [
16596
17336
  (p.wireLength - 0.15) / 2,
16597
17337
  (i - (p.wireCount - 1) / 2) * p.wireDiameter * 1.5,
16598
17338
  0
16599
17339
  ],
16600
- jscad8.transforms.rotateY(
17340
+ jscad10.transforms.rotateY(
16601
17341
  Math.PI / 2,
16602
- jscad8.primitives.cylinder({
17342
+ jscad10.primitives.cylinder({
16603
17343
  height: p.wireLength + 0.15,
16604
17344
  radius: p.wireDiameter / 2,
16605
17345
  segments: 24
@@ -16612,7 +17352,7 @@ function createNemaMotorWireGeometry(input) {
16612
17352
  wires.unshift({
16613
17353
  color: "#252830",
16614
17354
  geometry: place(
16615
- jscad8.primitives.roundedCuboid({
17355
+ jscad10.primitives.roundedCuboid({
16616
17356
  size: [3, p.wireCount * p.wireDiameter * 1.5 + 3, 6],
16617
17357
  center: [0.8, 0, 0],
16618
17358
  roundRadius: 1,
@@ -16627,12 +17367,12 @@ function createNemaMotorWireGeometry(input) {
16627
17367
  const wall = pitch === 2 ? 0.6 : 0.3;
16628
17368
  const contactLength = pitch === 2 ? 3.4 : 2.4;
16629
17369
  const contactSize = pitch === 2 ? 0.5 : 0.3;
16630
- const shell = jscad8.booleans.subtract(
16631
- jscad8.primitives.cuboid({
17370
+ const shell = jscad10.booleans.subtract(
17371
+ jscad10.primitives.cuboid({
16632
17372
  size: [matingDepth + 0.1, bodyWidth, bodyHeight],
16633
17373
  center: [(matingDepth - 0.1) / 2, 0, 0]
16634
17374
  }),
16635
- jscad8.primitives.cuboid({
17375
+ jscad10.primitives.cuboid({
16636
17376
  size: [matingDepth - 0.5, bodyWidth - 2 * wall, bodyHeight - 2 * wall],
16637
17377
  center: [matingDepth / 2 + 0.55, 0, 0]
16638
17378
  })
@@ -16642,7 +17382,7 @@ function createNemaMotorWireGeometry(input) {
16642
17382
  ...Array.from({ length: pinCount }, (_, i) => ({
16643
17383
  color: "#b8bec6",
16644
17384
  geometry: place(
16645
- jscad8.primitives.cuboid({
17385
+ jscad10.primitives.cuboid({
16646
17386
  size: [contactLength, contactSize, contactSize],
16647
17387
  center: [contactLength / 2, (i - (pinCount - 1) / 2) * pitch, 0]
16648
17388
  })
@@ -16786,12 +17526,12 @@ function createNemaMotorSections(input) {
16786
17526
  else {
16787
17527
  const cut = r - p.shaftFlatDepth;
16788
17528
  const angle = Math.acos(cut / r);
16789
- const profile6 = Array.from({ length: 97 }, (_, i) => {
17529
+ const profile5 = Array.from({ length: 97 }, (_, i) => {
16790
17530
  const a = angle + (2 * Math.PI - 2 * angle) * i / 96;
16791
17531
  return [r * Math.cos(a), r * Math.sin(a)];
16792
17532
  });
16793
17533
  const rotation = p.shaftFlatAngle * Math.PI / 180;
16794
- const d = profile6.map(([x, y]) => [
17534
+ const d = profile5.map(([x, y]) => [
16795
17535
  x * Math.cos(rotation) - y * Math.sin(rotation),
16796
17536
  x * Math.sin(rotation) + y * Math.cos(rotation)
16797
17537
  ]);
@@ -16802,7 +17542,7 @@ function createNemaMotorSections(input) {
16802
17542
  }
16803
17543
 
16804
17544
  // lib/NemaMotor.tsx
16805
- var generalize3 = jscad9.modifiers.generalize;
17545
+ var generalize3 = jscad11.modifiers.generalize;
16806
17546
  function NemaMotor({
16807
17547
  bodyColor = "#242830",
16808
17548
  capColor = "#aeb5bd",
@@ -16811,7 +17551,7 @@ function NemaMotor({
16811
17551
  ...props
16812
17552
  }) {
16813
17553
  const p = resolveNemaMotorProps(props);
16814
- const screw = p.backFaceScrews ? jscad9.transforms.rotateX(
17554
+ const screw = p.backFaceScrews ? jscad11.transforms.rotateX(
16815
17555
  Math.PI,
16816
17556
  createHexSocketBoltGeom({
16817
17557
  metricSize: p.backFaceScrewSize,
@@ -16823,16 +17563,16 @@ function NemaMotor({
16823
17563
  const halfPitchY = p.backFaceHoleSpacingY / 2;
16824
17564
  return /* @__PURE__ */ jsxs(Fragment2, { children: [
16825
17565
  createNemaMotorSections(p).map((section, index) => {
16826
- const outline = jscad9.geometries.geom2.fromPoints(section.outline);
16827
- const profile6 = section.holes.length ? jscad9.booleans.subtract(
17566
+ const outline = jscad11.geometries.geom2.fromPoints(section.outline);
17567
+ const profile5 = section.holes.length ? jscad11.booleans.subtract(
16828
17568
  outline,
16829
- ...section.holes.map((h2) => jscad9.geometries.geom2.fromPoints(h2))
17569
+ ...section.holes.map((h2) => jscad11.geometries.geom2.fromPoints(h2))
16830
17570
  ) : outline;
16831
- let geometry = jscad9.transforms.translate(
17571
+ let geometry = jscad11.transforms.translate(
16832
17572
  [0, 0, section.zMin],
16833
- jscad9.extrusions.extrudeLinear(
17573
+ jscad11.extrusions.extrudeLinear(
16834
17574
  { height: section.zMax - section.zMin },
16835
- profile6
17575
+ profile5
16836
17576
  )
16837
17577
  );
16838
17578
  if (p.nemaSize === 34 && section.name === "frontCap")
@@ -16874,7 +17614,7 @@ function NemaMotor({
16874
17614
  children: /* @__PURE__ */ jsx(
16875
17615
  Custom,
16876
17616
  {
16877
- geometry: jscad9.transforms.translate(
17617
+ geometry: jscad11.transforms.translate(
16878
17618
  [x, y, -p.bodyLength],
16879
17619
  generalize3({ simplify: true }, screw)
16880
17620
  )
@@ -17364,19 +18104,19 @@ function register83(registry2) {
17364
18104
  }
17365
18105
 
17366
18106
  // lib/models/perforatedsheet/geometry.ts
17367
- import jscad10 from "@jscad/modeling";
18107
+ import jscad12 from "@jscad/modeling";
17368
18108
  var {
17369
- booleans: booleans2,
17370
- primitives: primitives4,
17371
- extrusions: extrusions4,
17372
- geometries: geometries4,
17373
- modifiers: modifiers3,
17374
- measurements: measurements4
17375
- } = jscad10;
17376
- var generalize4 = modifiers3.generalize;
17377
- var { subtract } = booleans2;
17378
- var { rectangle: rectangle3, roundedRectangle: roundedRectangle3, circle: circle2 } = primitives4;
17379
- var profile3 = (shape49, height10) => extrusions4.extrudeLinear({ height: height10 }, shape49);
18109
+ booleans: booleans3,
18110
+ primitives: primitives5,
18111
+ extrusions: extrusions5,
18112
+ geometries: geometries5,
18113
+ modifiers: modifiers4,
18114
+ measurements: measurements5
18115
+ } = jscad12;
18116
+ var generalize4 = modifiers4.generalize;
18117
+ var { subtract } = booleans3;
18118
+ var { rectangle: rectangle3, roundedRectangle: roundedRectangle3, circle: circle2 } = primitives5;
18119
+ var profile3 = (shape49, height10) => extrusions5.extrudeLinear({ height: height10 }, shape49);
17380
18120
  function perforated(p) {
17381
18121
  const holes = [];
17382
18122
  const rows = Math.floor((p.width - 2 * p.edgeY) / p.pitchY + 1 + 1e-10);
@@ -17407,7 +18147,7 @@ function createPerforatedSheetMesh(input) {
17407
18147
  { snap: true, triangulate: true },
17408
18148
  createPerforatedSheetGeom(input)
17409
18149
  );
17410
- const epsilon = Math.max(...measurements4.measureDimensions(geom)) * 1e-10;
18150
+ const epsilon = Math.max(...measurements5.measureDimensions(geom)) * 1e-10;
17411
18151
  const positions = [];
17412
18152
  const indices = [];
17413
18153
  const lookup = /* @__PURE__ */ new Map();
@@ -17421,7 +18161,7 @@ function createPerforatedSheetMesh(input) {
17421
18161
  }
17422
18162
  return index;
17423
18163
  };
17424
- for (const poly of geometries4.geom3.toPolygons(geom)) {
18164
+ for (const poly of geometries5.geom3.toPolygons(geom)) {
17425
18165
  for (let i = 1; i < poly.vertices.length - 1; i++) {
17426
18166
  const a = poly.vertices[0], b = poly.vertices[i], c = poly.vertices[i + 1];
17427
18167
  const u = b.map((x, j) => x - a[j]), v = c.map((x, j) => x - a[j]);
@@ -17463,7 +18203,7 @@ function createPlainBushingMesh(input) {
17463
18203
  const ri = d.innerDiameter / 2;
17464
18204
  const ro = d.outerDiameter / 2;
17465
18205
  const c = props.edgeChamfer;
17466
- const profile6 = c > 0 ? [
18206
+ const profile5 = c > 0 ? [
17467
18207
  [d.endOuterDiameter / 2, 0],
17468
18208
  [ro, c],
17469
18209
  [ro, d.length - c],
@@ -17481,14 +18221,14 @@ function createPlainBushingMesh(input) {
17481
18221
  const segments = 96;
17482
18222
  const positions = [];
17483
18223
  const indices = [];
17484
- for (const [radius, z] of profile6)
18224
+ for (const [radius, z] of profile5)
17485
18225
  for (let i = 0; i < segments; i++) {
17486
18226
  const angle = i * Math.PI * 2 / segments;
17487
18227
  positions.push(radius * Math.cos(angle), radius * Math.sin(angle), z);
17488
18228
  }
17489
- for (let ring = 0; ring < profile6.length; ring++) {
18229
+ for (let ring = 0; ring < profile5.length; ring++) {
17490
18230
  const a = ring * segments;
17491
- const b = (ring + 1) % profile6.length * segments;
18231
+ const b = (ring + 1) % profile5.length * segments;
17492
18232
  for (let i = 0; i < segments; i++) {
17493
18233
  const next = (i + 1) % segments;
17494
18234
  indices.push(a + i, a + next, b + next, a + i, b + next, b + i);
@@ -17520,13 +18260,13 @@ function register85(registry2) {
17520
18260
  }
17521
18261
 
17522
18262
  // lib/models/pushfitplug/geometry.ts
17523
- import jscad11 from "@jscad/modeling";
17524
- var { primitives: primitives5, extrusions: extrusions5, geometries: geometries5, modifiers: modifiers4, measurements: measurements5 } = jscad11;
17525
- var generalize5 = modifiers4.generalize;
17526
- var { rectangle: rectangle4, roundedRectangle: roundedRectangle4, polygon: polygon3 } = primitives5;
18263
+ import jscad13 from "@jscad/modeling";
18264
+ var { primitives: primitives6, extrusions: extrusions6, geometries: geometries6, modifiers: modifiers5, measurements: measurements6 } = jscad13;
18265
+ var generalize5 = modifiers5.generalize;
18266
+ var { rectangle: rectangle4, roundedRectangle: roundedRectangle4, polygon: polygon3 } = primitives6;
17527
18267
  function createPushFitPlugGeom(input) {
17528
18268
  const p = pushFitPlugModelPropsSchema.parse(input);
17529
- return extrusions5.extrudeRotate(
18269
+ return extrusions6.extrudeRotate(
17530
18270
  { segments: 64 },
17531
18271
  polygon3({
17532
18272
  points: [
@@ -17545,7 +18285,7 @@ function createPushFitPlugMesh(input) {
17545
18285
  { snap: true, triangulate: true },
17546
18286
  createPushFitPlugGeom(input)
17547
18287
  );
17548
- const epsilon = Math.max(...measurements5.measureDimensions(geom)) * 1e-10;
18288
+ const epsilon = Math.max(...measurements6.measureDimensions(geom)) * 1e-10;
17549
18289
  const positions = [];
17550
18290
  const indices = [];
17551
18291
  const lookup = /* @__PURE__ */ new Map();
@@ -17559,7 +18299,7 @@ function createPushFitPlugMesh(input) {
17559
18299
  }
17560
18300
  return index;
17561
18301
  };
17562
- for (const poly of geometries5.geom3.toPolygons(geom)) {
18302
+ for (const poly of geometries6.geom3.toPolygons(geom)) {
17563
18303
  for (let i = 1; i < poly.vertices.length - 1; i++) {
17564
18304
  const a = poly.vertices[0], b = poly.vertices[i], c = poly.vertices[i + 1];
17565
18305
  const u = b.map((x, j) => x - a[j]), v = c.map((x, j) => x - a[j]);
@@ -17592,11 +18332,11 @@ function register86(registry2) {
17592
18332
  }
17593
18333
 
17594
18334
  // lib/models/rectangularbar/geometry.ts
17595
- import jscad12 from "@jscad/modeling";
17596
- var { primitives: primitives6, extrusions: extrusions6, geometries: geometries6, modifiers: modifiers5, measurements: measurements6 } = jscad12;
17597
- var generalize6 = modifiers5.generalize;
17598
- var { rectangle: rectangle5, roundedRectangle: roundedRectangle5 } = primitives6;
17599
- var profile4 = (shape49, height10) => extrusions6.extrudeLinear({ height: height10 }, shape49);
18335
+ import jscad14 from "@jscad/modeling";
18336
+ var { primitives: primitives7, extrusions: extrusions7, geometries: geometries7, modifiers: modifiers6, measurements: measurements7 } = jscad14;
18337
+ var generalize6 = modifiers6.generalize;
18338
+ var { rectangle: rectangle5, roundedRectangle: roundedRectangle5 } = primitives7;
18339
+ var profile4 = (shape49, height10) => extrusions7.extrudeLinear({ height: height10 }, shape49);
17600
18340
  var roundedRect = (width10, height10, radius) => radius ? roundedRectangle5({
17601
18341
  size: [width10, height10],
17602
18342
  roundRadius: radius,
@@ -17611,7 +18351,7 @@ function createRectangularBarMesh(input) {
17611
18351
  { snap: true, triangulate: true },
17612
18352
  createRectangularBarGeom(input)
17613
18353
  );
17614
- const epsilon = Math.max(...measurements6.measureDimensions(geom)) * 1e-10;
18354
+ const epsilon = Math.max(...measurements7.measureDimensions(geom)) * 1e-10;
17615
18355
  const positions = [];
17616
18356
  const indices = [];
17617
18357
  const lookup = /* @__PURE__ */ new Map();
@@ -17625,7 +18365,7 @@ function createRectangularBarMesh(input) {
17625
18365
  }
17626
18366
  return index;
17627
18367
  };
17628
- for (const poly of geometries6.geom3.toPolygons(geom)) {
18368
+ for (const poly of geometries7.geom3.toPolygons(geom)) {
17629
18369
  for (let i = 1; i < poly.vertices.length - 1; i++) {
17630
18370
  const a = poly.vertices[0], b = poly.vertices[i], c = poly.vertices[i + 1];
17631
18371
  const u = b.map((x, j) => x - a[j]), v = c.map((x, j) => x - a[j]);
@@ -17769,72 +18509,27 @@ function register88(registry2) {
17769
18509
  registry2.register(model88);
17770
18510
  }
17771
18511
 
17772
- // lib/models/rectangulartube/geometry.ts
17773
- import jscad13 from "@jscad/modeling";
17774
- var {
17775
- booleans: booleans3,
17776
- primitives: primitives7,
17777
- extrusions: extrusions7,
17778
- geometries: geometries7,
17779
- modifiers: modifiers6,
17780
- measurements: measurements7
17781
- } = jscad13;
17782
- var generalize7 = modifiers6.generalize;
17783
- var { subtract: subtract2 } = booleans3;
17784
- var { rectangle: rectangle6, roundedRectangle: roundedRectangle6 } = primitives7;
17785
- var profile5 = (shape49, height10) => extrusions7.extrudeLinear({ height: height10 }, shape49);
17786
- var roundedRect2 = (width10, height10, radius) => radius ? roundedRectangle6({
18512
+ // lib/models/rectangulartube/profiles.ts
18513
+ import jscad15 from "@jscad/modeling";
18514
+ var roundedRectangle6 = (width10, height10, radius) => radius ? jscad15.primitives.roundedRectangle({
17787
18515
  size: [width10, height10],
17788
18516
  roundRadius: radius,
17789
18517
  segments: 64
17790
- }) : rectangle6({ size: [width10, height10] });
17791
- function createRectangularTubeGeom(input) {
18518
+ }) : jscad15.primitives.rectangle({ size: [width10, height10] });
18519
+ function getRectangularTubeProfiles(input) {
17792
18520
  const p = rectangularTubeModelPropsSchema.parse(input);
17793
- return profile5(
17794
- subtract2(
17795
- roundedRect2(p.width, p.height, p.outerRadius),
17796
- roundedRect2(
18521
+ const points = (geometry) => jscad15.geometries.geom2.toPoints(geometry);
18522
+ return {
18523
+ length: p.length,
18524
+ outerPoints: points(roundedRectangle6(p.width, p.height, p.outerRadius)),
18525
+ innerPoints: points(
18526
+ roundedRectangle6(
17797
18527
  p.width - 2 * p.wallThickness,
17798
18528
  p.height - 2 * p.wallThickness,
17799
18529
  p.innerRadius
17800
18530
  )
17801
- ),
17802
- p.length
17803
- );
17804
- }
17805
- function createRectangularTubeMesh(input) {
17806
- const geom = generalize7(
17807
- { snap: true, triangulate: true },
17808
- createRectangularTubeGeom(input)
17809
- );
17810
- const epsilon = Math.max(...measurements7.measureDimensions(geom)) * 1e-10;
17811
- const positions = [];
17812
- const indices = [];
17813
- const lookup = /* @__PURE__ */ new Map();
17814
- const vertex = (v) => {
17815
- const key = v.map((x) => Math.round(x / epsilon)).join(",");
17816
- let index = lookup.get(key);
17817
- if (index === void 0) {
17818
- index = positions.length / 3;
17819
- positions.push(...v);
17820
- lookup.set(key, index);
17821
- }
17822
- return index;
18531
+ )
17823
18532
  };
17824
- for (const poly of geometries7.geom3.toPolygons(geom)) {
17825
- for (let i = 1; i < poly.vertices.length - 1; i++) {
17826
- const a = poly.vertices[0], b = poly.vertices[i], c = poly.vertices[i + 1];
17827
- const u = b.map((x, j) => x - a[j]), v = c.map((x, j) => x - a[j]);
17828
- const area = Math.hypot(
17829
- u[1] * v[2] - u[2] * v[1],
17830
- u[2] * v[0] - u[0] * v[2],
17831
- u[0] * v[1] - u[1] * v[0]
17832
- );
17833
- if (area > epsilon * epsilon)
17834
- indices.push(vertex(a), vertex(b), vertex(c));
17835
- }
17836
- }
17837
- return { positions, indices };
17838
18533
  }
17839
18534
 
17840
18535
  // lib/models/rectangulartube/RectangularTube.tsx
@@ -17842,7 +18537,27 @@ function RectangularTube({
17842
18537
  color = "#929da9",
17843
18538
  ...props
17844
18539
  }) {
17845
- return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsx(Custom, { geometry: createRectangularTubeGeom(props) }) });
18540
+ const { length: length32, outerPoints, innerPoints } = getRectangularTubeProfiles(props);
18541
+ return /* @__PURE__ */ jsx(Colorize, { color, children: /* @__PURE__ */ jsxs(Subtract, { children: [
18542
+ /* @__PURE__ */ jsx(
18543
+ ExtrudeLinear,
18544
+ {
18545
+ height: length32,
18546
+ topOutlineName: "outer_top",
18547
+ bottomOutlineName: "outer_bottom",
18548
+ children: /* @__PURE__ */ jsx(Polygon, { points: outerPoints })
18549
+ }
18550
+ ),
18551
+ /* @__PURE__ */ jsx(
18552
+ ExtrudeLinear,
18553
+ {
18554
+ height: length32,
18555
+ topOutlineName: "inner_top",
18556
+ bottomOutlineName: "inner_bottom",
18557
+ children: /* @__PURE__ */ jsx(Polygon, { points: innerPoints })
18558
+ }
18559
+ )
18560
+ ] }) });
17846
18561
  }
17847
18562
 
17848
18563
  // lib/models/rectangulartube/register.tsx
@@ -18087,7 +18802,7 @@ function holeOutline(hole) {
18087
18802
  function createSheetMetalMesh(input) {
18088
18803
  const props = sheetMetalModelPropsSchema.parse(input);
18089
18804
  const { width: width10, baseLength, flangeHeight, thickness } = props;
18090
- const profile6 = props.channel ? "channel" : props.angle ? "angle" : "plate";
18805
+ const profile5 = props.channel ? "channel" : props.angle ? "angle" : "plate";
18091
18806
  const radius = props.insideBendRadius + thickness / 2;
18092
18807
  const positions = [];
18093
18808
  const indices = [];
@@ -18100,10 +18815,10 @@ function createSheetMetalMesh(input) {
18100
18815
  addTriangle([vertices[0], vertices[1], vertices[2]], reverse);
18101
18816
  addTriangle([vertices[0], vertices[2], vertices[3]], reverse);
18102
18817
  };
18103
- const panels = profile6 === "plate" ? ["base"] : profile6 === "angle" ? ["base", "right"] : ["base", "left", "right"];
18818
+ const panels = profile5 === "plate" ? ["base"] : profile5 === "angle" ? ["base", "right"] : ["base", "left", "right"];
18104
18819
  for (const hole of props.holes) {
18105
18820
  if (!panels.includes(hole.panel))
18106
- throw new Error(`No ${hole.panel} panel on ${profile6}`);
18821
+ throw new Error(`No ${hole.panel} panel on ${profile5}`);
18107
18822
  }
18108
18823
  for (const panel of panels) {
18109
18824
  const length32 = panel === "base" ? baseLength : flangeHeight;
@@ -18154,7 +18869,7 @@ function createSheetMetalMesh(input) {
18154
18869
  for (const [loopIndex, loop] of loops.entries())
18155
18870
  for (let i = 0; i < loop.length; i++) {
18156
18871
  const a = loop[i], b = loop[(i + 1) % loop.length];
18157
- if (loopIndex === 0 && a.u === b.u && (panel === "base" && (a.u > 0 && profile6 !== "plate" || a.u < 0 && profile6 === "channel") || panel !== "base" && a.u < 0))
18872
+ if (loopIndex === 0 && a.u === b.u && (panel === "base" && (a.u > 0 && profile5 !== "plate" || a.u < 0 && profile5 === "channel") || panel !== "base" && a.u < 0))
18158
18873
  continue;
18159
18874
  addQuad(
18160
18875
  [
@@ -18167,7 +18882,7 @@ function createSheetMetalMesh(input) {
18167
18882
  );
18168
18883
  }
18169
18884
  }
18170
- const sides = profile6 === "plate" ? [] : profile6 === "angle" ? [1] : [-1, 1];
18885
+ const sides = profile5 === "plate" ? [] : profile5 === "angle" ? [1] : [-1, 1];
18171
18886
  for (const side of sides) {
18172
18887
  const project = (angle, crossSection) => {
18173
18888
  const r = radius - crossSection.offset;
@@ -18766,7 +19481,7 @@ function register100(registry2) {
18766
19481
  }
18767
19482
 
18768
19483
  // lib/models/tslotcoverstrip/geometry.ts
18769
- import jscad16 from "@jscad/modeling";
19484
+ import jscad18 from "@jscad/modeling";
18770
19485
  var {
18771
19486
  primitives: primitives8,
18772
19487
  extrusions: extrusions8,
@@ -18774,8 +19489,8 @@ var {
18774
19489
  geometries: geometries8,
18775
19490
  modifiers: modifiers7,
18776
19491
  measurements: measurements8
18777
- } = jscad16;
18778
- var generalize8 = modifiers7.generalize;
19492
+ } = jscad18;
19493
+ var generalize7 = modifiers7.generalize;
18779
19494
  function createTSlotCoverStripGeom(input) {
18780
19495
  const p = tSlotCoverStripModelPropsSchema.parse(input);
18781
19496
  const w = p.width / 2;
@@ -18802,7 +19517,7 @@ function createTSlotCoverStripGeom(input) {
18802
19517
  return extrusions8.extrudeLinear({ height: p.length }, outline);
18803
19518
  }
18804
19519
  function createTSlotCoverStripMesh(input) {
18805
- const geom = generalize8(
19520
+ const geom = generalize7(
18806
19521
  { snap: false, triangulate: true },
18807
19522
  createTSlotCoverStripGeom(input)
18808
19523
  );
@@ -19056,10 +19771,10 @@ function register104(registry2) {
19056
19771
  }
19057
19772
 
19058
19773
  // lib/models/ufl/geometry.ts
19059
- import jscad17 from "@jscad/modeling";
19774
+ import jscad19 from "@jscad/modeling";
19060
19775
  function createUflGeometries(input = {}) {
19061
19776
  const d = getUflDimensions(input);
19062
- const { booleans: booleans5, primitives: primitives9 } = jscad17;
19777
+ const { booleans: booleans5, primitives: primitives9 } = jscad19;
19063
19778
  const silver = "#bcbfc3";
19064
19779
  const dielectric = "#eee9d5";
19065
19780
  const gold = "#d9b45b";
@@ -19216,17 +19931,17 @@ var createWormGearMesh = (input) => {
19216
19931
  fractions.push(fraction);
19217
19932
  }
19218
19933
  }
19219
- const profile6 = [];
19934
+ const profile5 = [];
19220
19935
  for (let start = 0; start < props.starts; start++) {
19221
19936
  for (const fraction of fractions) {
19222
19937
  const distance2 = Math.min(fraction, 1 - fraction) * axialPitch;
19223
- profile6.push({
19938
+ profile5.push({
19224
19939
  angle: (start + fraction) * Math.PI * 2 / props.starts,
19225
19940
  radius: distance2 <= tipHalfWidth ? outsideRadius : distance2 >= rootHalfWidth ? rootRadius : pitchRadius + (toothThickness / 2 - distance2) / pressureTangent
19226
19941
  });
19227
19942
  }
19228
19943
  }
19229
- const count = profile6.length;
19944
+ const count = profile5.length;
19230
19945
  const positions = [];
19231
19946
  const indices = [];
19232
19947
  const phase = props.phase % 360 * Math.PI / 180;
@@ -19234,7 +19949,7 @@ var createWormGearMesh = (input) => {
19234
19949
  const ring = (z) => {
19235
19950
  const first = positions.length / 3;
19236
19951
  const rotation = phase + direction * (z / lead) * Math.PI * 2;
19237
- for (const sample of profile6) {
19952
+ for (const sample of profile5) {
19238
19953
  const angle = sample.angle + rotation;
19239
19954
  positions.push(
19240
19955
  sample.radius * Math.cos(angle),
@@ -19714,53 +20429,199 @@ function createDualRowGullWing(p) {
19714
20429
  leadThickness / 2 + (midZ - leadThickness / 2) * t * t * (3 - 2 * t)
19715
20430
  ]);
19716
20431
  }
19717
- points.push([root, midZ]);
19718
- const section = ([x, z]) => /* @__PURE__ */ jsx(Translate, { offset: { x: side * x, y, z }, children: /* @__PURE__ */ jsx(Cuboid, { size: [slice, leadWidth, leadThickness] }) });
19719
- return /* @__PURE__ */ jsx(Union, { children: points.slice(1).map((point, i) => /* @__PURE__ */ jsxs(Hull, { children: [
19720
- section(points[i]),
19721
- section(point)
19722
- ] }, i)) });
19723
- };
20432
+ points.push([root, midZ]);
20433
+ const section = ([x, z]) => /* @__PURE__ */ jsx(Translate, { offset: { x: side * x, y, z }, children: /* @__PURE__ */ jsx(Cuboid, { size: [slice, leadWidth, leadThickness] }) });
20434
+ return /* @__PURE__ */ jsx(Union, { children: points.slice(1).map((point, i) => /* @__PURE__ */ jsxs(Hull, { children: [
20435
+ section(points[i]),
20436
+ section(point)
20437
+ ] }, i)) });
20438
+ };
20439
+ return /* @__PURE__ */ jsxs(Fragment2, { children: [
20440
+ /* @__PURE__ */ jsx(Colorize, { color: "#353535", children: /* @__PURE__ */ jsxs(Subtract, { children: [
20441
+ body,
20442
+ /* @__PURE__ */ jsx(
20443
+ Translate,
20444
+ {
20445
+ offset: {
20446
+ x: -bodyWidth / 2 + taperInset + dimpleRadius * 2,
20447
+ y: bodyLength10 / 2 - taperInset - dimpleRadius * 2,
20448
+ z: bodyHeight
20449
+ },
20450
+ children: /* @__PURE__ */ jsx(Cylinder, { radius: dimpleRadius, height: dimpleDepth * 2 })
20451
+ }
20452
+ )
20453
+ ] }) }),
20454
+ /* @__PURE__ */ jsx(Colorize, { color: "#bfc1c4", children: Array.from(
20455
+ { length: pinCount },
20456
+ (_, i) => lead(
20457
+ i < pinCount / 2 ? -1 : 1,
20458
+ ((pinCount / 2 - 1) / 2 - i % (pinCount / 2)) * pitch
20459
+ )
20460
+ ) }),
20461
+ exposedPadWidth > 0 && /* @__PURE__ */ jsx(Colorize, { color: "#bfc1c4", children: /* @__PURE__ */ jsx(Translate, { z: (standoff + leadThickness) / 2, children: /* @__PURE__ */ jsx(
20462
+ Cuboid,
20463
+ {
20464
+ size: [
20465
+ exposedPadWidth,
20466
+ exposedPadLength,
20467
+ standoff + leadThickness
20468
+ ]
20469
+ }
20470
+ ) }) })
20471
+ ] });
20472
+ }
20473
+
20474
+ // lib/SSOP.tsx
20475
+ var SSOP = (props) => createDualRowGullWing(props);
20476
+
20477
+ // lib/utils/FlatLeadDiode.tsx
20478
+ function createFlatLeadDiode(p) {
20479
+ const dimensions5 = [
20480
+ "bodyLength",
20481
+ "bodyWidth",
20482
+ "bodyHeight",
20483
+ "leadSpan",
20484
+ "cathodeLength",
20485
+ "cathodeWidth",
20486
+ "anodeLength",
20487
+ "anodeWidth",
20488
+ "terminalThickness",
20489
+ "standoff",
20490
+ "taperInset",
20491
+ "markingWidth"
20492
+ ];
20493
+ for (const name of dimensions5) {
20494
+ const value = p[name];
20495
+ const allowZero = ["standoff", "taperInset", "markingWidth"].includes(name);
20496
+ if (!Number.isFinite(value) || (allowZero ? value < 0 : value <= 0))
20497
+ throw new Error(`Invalid diode dimension: ${name}`);
20498
+ }
20499
+ const overhang = (p.leadSpan - p.bodyLength) / 2;
20500
+ if (overhang < 0 || p.cathodeLength <= overhang || p.anodeLength <= overhang || p.cathodeLength + p.anodeLength >= p.leadSpan || p.cathodeWidth > p.bodyWidth || p.anodeWidth > p.bodyWidth || p.standoff >= p.terminalThickness || p.terminalThickness >= p.bodyHeight || p.taperInset * 2 >= Math.min(p.bodyLength, p.bodyWidth) || p.markingWidth * 2 >= p.bodyLength - p.taperInset * 2)
20501
+ throw new Error(
20502
+ "Diode dimensions leave disconnected terminals or an invalid mold"
20503
+ );
20504
+ const slice = Math.min(p.bodyHeight - p.standoff, p.bodyWidth) / 100;
20505
+ const body = /* @__PURE__ */ jsxs(Hull, { children: [
20506
+ /* @__PURE__ */ jsx(
20507
+ Cuboid,
20508
+ {
20509
+ size: [p.bodyLength, p.bodyWidth, slice],
20510
+ center: [0, 0, p.standoff + slice / 2]
20511
+ }
20512
+ ),
20513
+ /* @__PURE__ */ jsx(
20514
+ Cuboid,
20515
+ {
20516
+ size: [
20517
+ p.bodyLength - p.taperInset * 2,
20518
+ p.bodyWidth - p.taperInset * 2,
20519
+ slice
20520
+ ],
20521
+ center: [0, 0, p.bodyHeight - slice / 2]
20522
+ }
20523
+ )
20524
+ ] });
20525
+ const stripe = /* @__PURE__ */ jsx(
20526
+ Cuboid,
20527
+ {
20528
+ size: [p.markingWidth, (p.bodyWidth - p.taperInset * 2) * 0.9, slice],
20529
+ center: [
20530
+ -p.bodyLength / 2 + p.taperInset + p.markingWidth,
20531
+ 0,
20532
+ p.bodyHeight - slice / 2
20533
+ ]
20534
+ }
20535
+ );
19724
20536
  return /* @__PURE__ */ jsxs(Fragment2, { children: [
19725
- /* @__PURE__ */ jsx(Colorize, { color: "#353535", children: /* @__PURE__ */ jsxs(Subtract, { children: [
20537
+ /* @__PURE__ */ jsx(Colorize, { color: "#25272a", children: p.markingWidth > 0 ? /* @__PURE__ */ jsxs(Subtract, { children: [
19726
20538
  body,
20539
+ stripe
20540
+ ] }) : body }),
20541
+ /* @__PURE__ */ jsxs(Colorize, { color: "#c7c9cd", children: [
19727
20542
  /* @__PURE__ */ jsx(
19728
- Translate,
20543
+ Cuboid,
19729
20544
  {
19730
- offset: {
19731
- x: -bodyWidth / 2 + taperInset + dimpleRadius * 2,
19732
- y: bodyLength10 / 2 - taperInset - dimpleRadius * 2,
19733
- z: bodyHeight
19734
- },
19735
- children: /* @__PURE__ */ jsx(Cylinder, { radius: dimpleRadius, height: dimpleDepth * 2 })
20545
+ size: [p.cathodeLength, p.cathodeWidth, p.terminalThickness],
20546
+ center: [
20547
+ -p.leadSpan / 2 + p.cathodeLength / 2,
20548
+ 0,
20549
+ p.terminalThickness / 2
20550
+ ]
20551
+ }
20552
+ ),
20553
+ /* @__PURE__ */ jsx(
20554
+ Cuboid,
20555
+ {
20556
+ size: [p.anodeLength, p.anodeWidth, p.terminalThickness],
20557
+ center: [
20558
+ p.leadSpan / 2 - p.anodeLength / 2,
20559
+ 0,
20560
+ p.terminalThickness / 2
20561
+ ]
19736
20562
  }
19737
20563
  )
19738
- ] }) }),
19739
- /* @__PURE__ */ jsx(Colorize, { color: "#bfc1c4", children: Array.from(
19740
- { length: pinCount },
19741
- (_, i) => lead(
19742
- i < pinCount / 2 ? -1 : 1,
19743
- ((pinCount / 2 - 1) / 2 - i % (pinCount / 2)) * pitch
19744
- )
19745
- ) }),
19746
- exposedPadWidth > 0 && /* @__PURE__ */ jsx(Colorize, { color: "#bfc1c4", children: /* @__PURE__ */ jsx(Translate, { z: (standoff + leadThickness) / 2, children: /* @__PURE__ */ jsx(
19747
- Cuboid,
19748
- {
19749
- size: [
19750
- exposedPadWidth,
19751
- exposedPadLength,
19752
- standoff + leadThickness
19753
- ]
19754
- }
19755
- ) }) })
20564
+ ] }),
20565
+ p.markingWidth > 0 && /* @__PURE__ */ jsx(Colorize, { color: "#aaaaa8", children: stripe })
19756
20566
  ] });
19757
20567
  }
19758
20568
 
19759
- // lib/SSOP.tsx
19760
- var SSOP = (props) => createDualRowGullWing(props);
20569
+ // lib/DO219AD.tsx
20570
+ var DO219AD = (props) => createFlatLeadDiode({
20571
+ bodyLength: 2.2,
20572
+ bodyWidth: 1.3,
20573
+ bodyHeight: 0.68,
20574
+ leadSpan: 2.5,
20575
+ cathodeLength: 1.3,
20576
+ cathodeWidth: 0.88,
20577
+ anodeLength: 0.65,
20578
+ anodeWidth: 0.65,
20579
+ terminalThickness: 0.195,
20580
+ standoff: 0.11,
20581
+ taperInset: 0.05,
20582
+ markingWidth: 0.23,
20583
+ ...props
20584
+ });
20585
+
20586
+ // lib/SOD323HE.tsx
20587
+ var SOD323HE = (props) => createFlatLeadDiode({
20588
+ bodyLength: 2,
20589
+ bodyWidth: 1.4,
20590
+ bodyHeight: 0.6,
20591
+ leadSpan: 2.5,
20592
+ cathodeLength: 0.55,
20593
+ cathodeWidth: 0.8,
20594
+ anodeLength: 0.55,
20595
+ anodeWidth: 0.8,
20596
+ terminalThickness: 0.17,
20597
+ standoff: 0.05,
20598
+ taperInset: 0.15,
20599
+ markingWidth: 0.2,
20600
+ ...props
20601
+ });
19761
20602
 
19762
20603
  // lib/utils/FootprinterBodyModels.tsx
19763
20604
  function renderFootprinterBodyModel(p) {
20605
+ if (p.fn === "do219ad" || p.fn === "sod323he") {
20606
+ const Diode = p.fn === "do219ad" ? DO219AD : SOD323HE;
20607
+ return /* @__PURE__ */ jsx(
20608
+ Diode,
20609
+ {
20610
+ bodyLength: p.bodylength,
20611
+ bodyWidth: p.bodywidth,
20612
+ bodyHeight: p.bodyheight,
20613
+ leadSpan: p.leadspan,
20614
+ cathodeLength: p.cathodelength,
20615
+ cathodeWidth: p.cathodewidth,
20616
+ anodeLength: p.anodelength,
20617
+ anodeWidth: p.anodewidth,
20618
+ terminalThickness: p.terminalthickness,
20619
+ standoff: p.standoff,
20620
+ taperInset: p.taperinset,
20621
+ markingWidth: p.markingwidth
20622
+ }
20623
+ );
20624
+ }
19764
20625
  if (p.bodywidth === void 0 && p.bodyheight === void 0 && p.bodythickness === void 0)
19765
20626
  return null;
19766
20627
  if (p.fn === "ssop") {
@@ -27189,8 +28050,8 @@ var Footprinter3d = ({ footprint }) => {
27189
28050
  DFN,
27190
28051
  {
27191
28052
  num_pins: fpJson.num_pins,
27192
- bodyWidth: fpJson.w,
27193
- bodyLength: fpJson.h,
28053
+ bodyWidth: fpJson.bodywidth ?? fpJson.w,
28054
+ bodyLength: fpJson.bodylength ?? fpJson.h,
27194
28055
  pitch: fpJson.p,
27195
28056
  padLength: fpJson.pl,
27196
28057
  padWidth: fpJson.pw,
@@ -27737,185 +28598,6 @@ var Footprinter3d = ({ footprint }) => {
27737
28598
  return null;
27738
28599
  };
27739
28600
 
27740
- // lib/vanilla/render.ts
27741
- var isVNode = (n) => n && typeof n === "object" && "type" in n;
27742
- var degToRad = (v) => {
27743
- if (typeof v === "number") return v;
27744
- if (typeof v === "string") {
27745
- const m = /^(-?\d+(?:\.\d+)?)\s*deg$/i.exec(v);
27746
- if (m) return parseFloat(m[1]) * Math.PI / 180;
27747
- const n = Number(v);
27748
- if (!Number.isNaN(n)) return n;
27749
- }
27750
- return 0;
27751
- };
27752
- var toVec3 = (v) => {
27753
- if (Array.isArray(v))
27754
- return [Number(v[0]) || 0, Number(v[1]) || 0, Number(v[2]) || 0];
27755
- if (typeof v === "object" && v)
27756
- return [Number(v.x) || 0, Number(v.y) || 0, Number(v.z) || 0];
27757
- return [0, 0, 0];
27758
- };
27759
- function renderNode(node, colorCtx, renderCtx) {
27760
- const {
27761
- jscad: { primitives: primitives9, booleans: booleans5, hulls, geometries: geometries9, extrusions: extrusions9, transforms: transforms2 }
27762
- } = renderCtx;
27763
- if (node == null || node === false) return [];
27764
- if (Array.isArray(node))
27765
- return node.flatMap((n) => renderNode(n, colorCtx, renderCtx));
27766
- if (!isVNode(node)) return [];
27767
- const { type, props, children } = node;
27768
- if (props?.material) {
27769
- const { material, ...rest } = props;
27770
- return renderNode({ ...node, props: rest }, colorCtx, renderCtx).map(
27771
- (entry) => ({
27772
- ...entry,
27773
- material: { ...material },
27774
- geom: { ...entry.geom, material: { ...material } }
27775
- })
27776
- );
27777
- }
27778
- if (type === Fragment) {
27779
- return (children ?? []).flatMap((c) => renderNode(c, colorCtx, renderCtx));
27780
- }
27781
- if (type === Colorize) {
27782
- const newColor = props?.color;
27783
- return (children ?? []).flatMap(
27784
- (c) => renderNode(c, newColor ?? colorCtx, renderCtx)
27785
- );
27786
- }
27787
- if (type === Translate) {
27788
- const off = toVec3(
27789
- props?.offset ?? props?.center ?? { x: props?.x, y: props?.y, z: props?.z }
27790
- );
27791
- const geoms = (children ?? []).flatMap(
27792
- (c) => renderNode(c, colorCtx, renderCtx)
27793
- );
27794
- return geoms.map(({ geom, color, material }) => ({
27795
- material,
27796
- geom: transforms2.translate(off, geom),
27797
- color: color ?? colorCtx
27798
- }));
27799
- }
27800
- if (type === Rotate) {
27801
- const angles = props?.angles ?? props?.rotation;
27802
- const rot = Array.isArray(angles) ? [degToRad(angles[0]), degToRad(angles[1]), degToRad(angles[2])] : [
27803
- degToRad(props?.x ?? 0),
27804
- degToRad(props?.y ?? 0),
27805
- degToRad(props?.z ?? 0)
27806
- ];
27807
- const geoms = (children ?? []).flatMap(
27808
- (c) => renderNode(c, colorCtx, renderCtx)
27809
- );
27810
- return geoms.map(({ geom, color, material }) => ({
27811
- material,
27812
- geom: transforms2.rotateZ(
27813
- rot[2],
27814
- transforms2.rotateY(rot[1], transforms2.rotateX(rot[0], geom))
27815
- ),
27816
- color
27817
- }));
27818
- }
27819
- if (type === Union || type === Subtract || type === Hull) {
27820
- const entries = (children ?? []).flatMap(
27821
- (c) => renderNode(c, colorCtx, renderCtx)
27822
- );
27823
- const geoms = entries.map((g) => g.geom);
27824
- if (geoms.length === 0) return [];
27825
- let geom;
27826
- if (type === Union) geom = booleans5.union(geoms);
27827
- else if (type === Subtract)
27828
- geom = booleans5.subtract(geoms[0], geoms.slice(1));
27829
- else geom = hulls.hull(geoms);
27830
- return [
27831
- {
27832
- geom,
27833
- color: colorCtx,
27834
- material: type === Subtract ? entries[0]?.material : void 0
27835
- }
27836
- ];
27837
- }
27838
- if (type === Custom) {
27839
- return [{ geom: props.geometry, color: colorCtx }];
27840
- }
27841
- if (type === Polygon) {
27842
- const points = props?.points ?? [];
27843
- const g2 = geometries9.geom2.fromPoints(points);
27844
- return [{ geom: g2, color: colorCtx ?? props?.color }];
27845
- }
27846
- if (type === ExtrudeLinear) {
27847
- const entries = (children ?? []).flatMap(
27848
- (c) => renderNode(c, colorCtx, renderCtx)
27849
- );
27850
- const geoms2 = entries.map((g) => g.geom);
27851
- if (geoms2.length === 0) return [];
27852
- const base2 = geoms2.length > 1 ? booleans5.union(geoms2) : geoms2[0];
27853
- const height10 = props?.height ?? props?.h ?? 1;
27854
- let g3 = extrusions9.extrudeLinear({ height: height10 }, base2);
27855
- if (g3.polygons) {
27856
- for (const poly of g3.polygons) {
27857
- if (!poly.plane || !poly.vertices || poly.vertices.length < 3) continue;
27858
- poly.vertices.reverse();
27859
- }
27860
- }
27861
- return [
27862
- {
27863
- geom: g3,
27864
- color: colorCtx ?? props?.color,
27865
- material: entries.length === 1 ? entries[0]?.material : void 0
27866
- }
27867
- ];
27868
- }
27869
- if (type === Cuboid || type === Cube || type === Cylinder || type === Sphere || type === RoundedCuboid || type === RoundedCylinder) {
27870
- let g;
27871
- if (type === Cuboid) {
27872
- const size = props?.size ?? [1, 1, 1];
27873
- const offset = props?.offset;
27874
- const center = props?.center ?? (offset ? [offset[0], offset[1], offset[2]] : [0, 0, 0]);
27875
- g = primitives9.cuboid({ size, center });
27876
- } else if (type === Cube) {
27877
- const size = props?.size ?? 1;
27878
- const offset = props?.offset;
27879
- const center = props?.center ?? (offset ? [offset[0], offset[1], offset[2]] : [0, 0, 0]);
27880
- g = primitives9.cube({ size, center });
27881
- } else if (type === Cylinder) {
27882
- const height10 = props?.height ?? 1;
27883
- const radius = props?.radius ?? 1;
27884
- const center = props?.center ?? [0, 0, 0];
27885
- g = primitives9.cylinder({ height: height10, radius, center });
27886
- } else if (type === Sphere) {
27887
- const radius = props?.radius ?? 1;
27888
- const center = props?.center ?? [0, 0, 0];
27889
- g = primitives9.sphere({ radius, center });
27890
- } else if (type === RoundedCylinder) {
27891
- const height10 = props?.height ?? 1;
27892
- const radius = props?.radius ?? 1;
27893
- const roundRadius = props?.roundRadius ?? 0.1;
27894
- const center = props?.center ?? [0, 0, 0];
27895
- g = primitives9.roundedCylinder({ height: height10, radius, roundRadius, center });
27896
- } else {
27897
- const size = props?.size ?? [1, 1, 1];
27898
- const roundRadius = props?.roundRadius ?? 0.1;
27899
- const center = props?.center ?? [0, 0, 0];
27900
- g = primitives9.roundedCuboid({ size, roundRadius, center });
27901
- }
27902
- return [{ geom: g, color: colorCtx ?? props?.color }];
27903
- }
27904
- if (typeof type === "function") {
27905
- const out = type(props ?? {});
27906
- return renderNode(out, colorCtx, renderCtx);
27907
- }
27908
- return (children ?? []).flatMap((c) => renderNode(c, colorCtx, renderCtx));
27909
- }
27910
- function render(root, jscad18) {
27911
- const geometries9 = renderNode(root, void 0, { jscad: jscad18 });
27912
- return {
27913
- geometries: geometries9.map(
27914
- (entry) => entry.material ? { ...entry, geom: { ...entry.geom, material: entry.material } } : entry
27915
- )
27916
- };
27917
- }
27918
-
27919
28601
  // lib/vanilla/convertCSGToThreeGeom.ts
27920
28602
  import {
27921
28603
  BufferAttribute,
@@ -27926,16 +28608,16 @@ function convertCSGToThreeGeom(csg) {
27926
28608
  if (csg.polygons) {
27927
28609
  const vertices = [];
27928
28610
  const indices = [];
27929
- const colors = [];
28611
+ const colors2 = [];
27930
28612
  let idx = 0;
27931
28613
  for (const polygon4 of csg.polygons) {
27932
28614
  for (const vertex of polygon4.vertices) {
27933
28615
  vertex.index = idx;
27934
28616
  vertices.push(vertex[0], vertex[1], vertex[2]);
27935
28617
  if (csg.color && csg.color.length >= 3) {
27936
- colors.push(csg.color[0], csg.color[1], csg.color[2]);
28618
+ colors2.push(csg.color[0], csg.color[1], csg.color[2]);
27937
28619
  } else {
27938
- colors.push(1, 1, 1);
28620
+ colors2.push(1, 1, 1);
27939
28621
  }
27940
28622
  idx++;
27941
28623
  }
@@ -27952,29 +28634,29 @@ function convertCSGToThreeGeom(csg) {
27952
28634
  new BufferAttribute(new Float32Array(vertices), 3)
27953
28635
  );
27954
28636
  geo.setIndex(indices);
27955
- if (colors.length > 0) {
28637
+ if (colors2.length > 0) {
27956
28638
  geo.setAttribute(
27957
28639
  "color",
27958
- new BufferAttribute(new Float32Array(colors), 3)
28640
+ new BufferAttribute(new Float32Array(colors2), 3)
27959
28641
  );
27960
28642
  }
27961
28643
  if (csg.transforms) {
27962
- const transforms2 = new Matrix4();
27963
- transforms2.fromArray(csg.transforms);
27964
- geo.applyMatrix4(transforms2);
28644
+ const transforms3 = new Matrix4();
28645
+ transforms3.fromArray(csg.transforms);
28646
+ geo.applyMatrix4(transforms3);
27965
28647
  }
27966
28648
  geo.computeVertexNormals();
27967
28649
  return geo;
27968
28650
  }
27969
28651
  if (csg.sides) {
27970
28652
  const vertices = [];
27971
- const colors = [];
28653
+ const colors2 = [];
27972
28654
  for (const side of csg.sides) {
27973
28655
  vertices.push(side[0][0], side[0][1], 0);
27974
28656
  if (csg.color && csg.color.length >= 3) {
27975
- colors.push(csg.color[0], csg.color[1], csg.color[2]);
28657
+ colors2.push(csg.color[0], csg.color[1], csg.color[2]);
27976
28658
  } else {
27977
- colors.push(1, 1, 1);
28659
+ colors2.push(1, 1, 1);
27978
28660
  }
27979
28661
  }
27980
28662
  const geo = new BufferGeometry();
@@ -27982,16 +28664,16 @@ function convertCSGToThreeGeom(csg) {
27982
28664
  "position",
27983
28665
  new BufferAttribute(new Float32Array(vertices), 3)
27984
28666
  );
27985
- if (colors.length > 0) {
28667
+ if (colors2.length > 0) {
27986
28668
  geo.setAttribute(
27987
28669
  "color",
27988
- new BufferAttribute(new Float32Array(colors), 3)
28670
+ new BufferAttribute(new Float32Array(colors2), 3)
27989
28671
  );
27990
28672
  }
27991
28673
  if (csg.transforms) {
27992
- const transforms2 = new Matrix4();
27993
- transforms2.fromArray(csg.transforms);
27994
- geo.applyMatrix4(transforms2);
28674
+ const transforms3 = new Matrix4();
28675
+ transforms3.fromArray(csg.transforms);
28676
+ geo.applyMatrix4(transforms3);
27995
28677
  }
27996
28678
  return geo;
27997
28679
  }
@@ -27999,25 +28681,104 @@ function convertCSGToThreeGeom(csg) {
27999
28681
  return new BufferGeometry();
28000
28682
  }
28001
28683
 
28684
+ // lib/named-edges.ts
28685
+ import jscad20 from "@jscad/modeling";
28686
+ function listJscadNamedEdges(model108) {
28687
+ return listJscadReferenceFeatures(model108).filter((name) => {
28688
+ const { geometry } = model108.referenceFeatures[name];
28689
+ return jscad20.geometries.geom2.isA(geometry) || jscad20.geometries.path2.isA(geometry);
28690
+ });
28691
+ }
28692
+ function listJscadReferenceFeatures(model108) {
28693
+ return Object.keys(model108.referenceFeatures);
28694
+ }
28695
+ function readJscadReferenceFeature(model108, name) {
28696
+ if (!Object.hasOwn(model108.referenceFeatures, name))
28697
+ throw new Error(`JSCAD model does not define named feature "${name}"`);
28698
+ return model108.referenceFeatures[name];
28699
+ }
28700
+ function readJscadNamedEdge(model108, name) {
28701
+ const { geometry: feature, matrix } = readJscadReferenceFeature(model108, name);
28702
+ if (matrix.length !== 16 || !matrix.every(Number.isFinite))
28703
+ throw new Error(
28704
+ `Named JSCAD feature "${name}" requires a finite 4x4 matrix`
28705
+ );
28706
+ let points;
28707
+ let closed;
28708
+ if (jscad20.geometries.path2.isA(feature)) {
28709
+ const path = jscad20.geometries.path2.clone(feature);
28710
+ points = jscad20.geometries.path2.toPoints(path);
28711
+ closed = path.isClosed;
28712
+ } else if (jscad20.geometries.geom2.isA(feature)) {
28713
+ const outlines = jscad20.geometries.geom2.toOutlines(
28714
+ jscad20.geometries.geom2.clone(feature)
28715
+ );
28716
+ if (outlines.length !== 1)
28717
+ throw new Error(
28718
+ `Named JSCAD edge "${name}" must identify one contour; name its boundaries separately`
28719
+ );
28720
+ points = outlines[0];
28721
+ closed = true;
28722
+ } else {
28723
+ throw new Error(
28724
+ `Named JSCAD edge "${name}" is not a geom2 or path2 feature`
28725
+ );
28726
+ }
28727
+ if (points.length < 2)
28728
+ throw new Error(`Named JSCAD edge "${name}" has no measurable path`);
28729
+ return {
28730
+ points: points.map(([x, y]) => {
28731
+ const point = jscad20.maths.vec3.transform(
28732
+ jscad20.maths.vec3.create(),
28733
+ [x, y, 0],
28734
+ matrix
28735
+ );
28736
+ return { x: point[0], y: point[1], z: point[2] };
28737
+ }),
28738
+ closed
28739
+ };
28740
+ }
28741
+
28742
+ // lib/models/rectangulartube/model.tsx
28743
+ import jscad21 from "@jscad/modeling";
28744
+ function createRectangularTubeModel(input) {
28745
+ const model108 = renderToJscadModel(
28746
+ /* @__PURE__ */ jsx(RectangularTube, { ...input }),
28747
+ jscad21
28748
+ );
28749
+ if (model108.geometries.length !== 1 || !jscad21.geometries.geom3.isA(model108.geometries[0]))
28750
+ throw new Error("RectangularTube must render exactly one native solid");
28751
+ return model108;
28752
+ }
28753
+
28754
+ // lib/models/rectangulartube/geometry.ts
28755
+ function createRectangularTubeGeom(input) {
28756
+ const model108 = createRectangularTubeModel(input);
28757
+ return model108.geometries[0];
28758
+ }
28759
+ function createRectangularTubeMesh(input) {
28760
+ return geom3ToIndexedMesh(createRectangularTubeGeom(input));
28761
+ }
28762
+
28002
28763
  // lib/vanilla/index.ts
28003
- function getJscadModelForFootprint(footprint, jscad18) {
28764
+ function getJscadModelForFootprint(footprint, jscad22) {
28004
28765
  const vnode = h(Footprinter3d, { footprint });
28005
- return render(vnode, jscad18);
28766
+ return render(vnode, jscad22);
28006
28767
  }
28007
- function getJscadModelForFootprintWithPads(footprint, jscad18) {
28768
+ function getJscadModelForFootprintWithPads(footprint, jscad22) {
28008
28769
  const vnode = h(
28009
28770
  Fragment,
28010
28771
  {},
28011
28772
  h(Footprinter3d, { footprint }),
28012
28773
  h(ExtrudedPads, { footprint })
28013
28774
  );
28014
- return render(vnode, jscad18);
28775
+ return render(vnode, jscad22);
28015
28776
  }
28016
- function createJSCADRenderer(jscad18) {
28777
+ function createJSCADRenderer(jscad22) {
28017
28778
  function createJSCADRoot(container) {
28018
28779
  return {
28019
28780
  render(element) {
28020
- const { geometries: geometries9 } = render(element, jscad18);
28781
+ const { geometries: geometries9 } = render(element, jscad22);
28021
28782
  container.splice(0, container.length, ...geometries9);
28022
28783
  }
28023
28784
  };
@@ -28152,6 +28913,7 @@ export {
28152
28913
  createRectangularGasketMesh,
28153
28914
  createRectangularTubeGeom,
28154
28915
  createRectangularTubeMesh,
28916
+ createRectangularTubeModel,
28155
28917
  createRigidCouplerGeom,
28156
28918
  createRigidCouplerMesh,
28157
28919
  createSetScrewGeom,
@@ -28187,8 +28949,14 @@ export {
28187
28949
  createWormGearMesh,
28188
28950
  createZeeBarGeom,
28189
28951
  createZeeBarMesh,
28952
+ geom3ToIndexedMesh,
28190
28953
  getJscadModelForFootprint,
28191
28954
  getJscadModelForFootprintWithPads,
28192
- h
28955
+ h,
28956
+ listJscadNamedEdges,
28957
+ listJscadReferenceFeatures,
28958
+ readJscadNamedEdge,
28959
+ readJscadReferenceFeature,
28960
+ renderToJscadModel
28193
28961
  };
28194
28962
  //# sourceMappingURL=vanilla.js.map