@tscircuit/3d-viewer 0.0.611 → 0.0.612

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.
Files changed (2) hide show
  1. package/dist/index.js +2322 -1332
  2. package/package.json +7 -4
package/dist/index.js CHANGED
@@ -284,29 +284,29 @@ var require_fromRotation = __commonJS({
284
284
  var { sin, cos } = require_trigonometry();
285
285
  var identity = require_identity();
286
286
  var fromRotation = (out, rad, axis) => {
287
- let [x, y, z42] = axis;
288
- const lengthSquared = x * x + y * y + z42 * z42;
287
+ let [x, y, z27] = axis;
288
+ const lengthSquared = x * x + y * y + z27 * z27;
289
289
  if (Math.abs(lengthSquared) < EPS3) {
290
290
  return identity(out);
291
291
  }
292
292
  const len = 1 / Math.sqrt(lengthSquared);
293
293
  x *= len;
294
294
  y *= len;
295
- z42 *= len;
295
+ z27 *= len;
296
296
  const s = sin(rad);
297
297
  const c = cos(rad);
298
298
  const t = 1 - c;
299
299
  out[0] = x * x * t + c;
300
- out[1] = y * x * t + z42 * s;
301
- out[2] = z42 * x * t - y * s;
300
+ out[1] = y * x * t + z27 * s;
301
+ out[2] = z27 * x * t - y * s;
302
302
  out[3] = 0;
303
- out[4] = x * y * t - z42 * s;
303
+ out[4] = x * y * t - z27 * s;
304
304
  out[5] = y * y * t + c;
305
- out[6] = z42 * y * t + x * s;
305
+ out[6] = z27 * y * t + x * s;
306
306
  out[7] = 0;
307
- out[8] = x * z42 * t + y * s;
308
- out[9] = y * z42 * t - x * s;
309
- out[10] = z42 * z42 * t + c;
307
+ out[8] = x * z27 * t + y * s;
308
+ out[9] = y * z27 * t - x * s;
309
+ out[10] = z27 * z27 * t + c;
310
310
  out[11] = 0;
311
311
  out[12] = 0;
312
312
  out[13] = 0;
@@ -560,8 +560,8 @@ var require_distance = __commonJS({
560
560
  var distance6 = (a, b) => {
561
561
  const x = b[0] - a[0];
562
562
  const y = b[1] - a[1];
563
- const z42 = b[2] - a[2];
564
- return Math.sqrt(x * x + y * y + z42 * z42);
563
+ const z27 = b[2] - a[2];
564
+ return Math.sqrt(x * x + y * y + z27 * z27);
565
565
  };
566
566
  module.exports = distance6;
567
567
  }
@@ -609,11 +609,11 @@ var require_fromValues2 = __commonJS({
609
609
  "node_modules/@jscad/modeling/src/maths/vec3/fromValues.js"(exports, module) {
610
610
  "use strict";
611
611
  var create = require_create2();
612
- var fromValues = (x, y, z42) => {
612
+ var fromValues = (x, y, z27) => {
613
613
  const out = create();
614
614
  out[0] = x;
615
615
  out[1] = y;
616
- out[2] = z42;
616
+ out[2] = z27;
617
617
  return out;
618
618
  };
619
619
  module.exports = fromValues;
@@ -624,10 +624,10 @@ var require_fromValues2 = __commonJS({
624
624
  var require_fromVec2 = __commonJS({
625
625
  "node_modules/@jscad/modeling/src/maths/vec3/fromVec2.js"(exports, module) {
626
626
  "use strict";
627
- var fromVector2 = (out, vector, z42 = 0) => {
627
+ var fromVector2 = (out, vector, z27 = 0) => {
628
628
  out[0] = vector[0];
629
629
  out[1] = vector[1];
630
- out[2] = z42;
630
+ out[2] = z27;
631
631
  return out;
632
632
  };
633
633
  module.exports = fromVector2;
@@ -641,8 +641,8 @@ var require_length = __commonJS({
641
641
  var length83 = (vector) => {
642
642
  const x = vector[0];
643
643
  const y = vector[1];
644
- const z42 = vector[2];
645
- return Math.sqrt(x * x + y * y + z42 * z42);
644
+ const z27 = vector[2];
645
+ return Math.sqrt(x * x + y * y + z27 * z27);
646
646
  };
647
647
  module.exports = length83;
648
648
  }
@@ -725,14 +725,14 @@ var require_normalize = __commonJS({
725
725
  var normalize = (out, vector) => {
726
726
  const x = vector[0];
727
727
  const y = vector[1];
728
- const z42 = vector[2];
729
- let len = x * x + y * y + z42 * z42;
728
+ const z27 = vector[2];
729
+ let len = x * x + y * y + z27 * z27;
730
730
  if (len > 0) {
731
731
  len = 1 / Math.sqrt(len);
732
732
  }
733
733
  out[0] = x * len;
734
734
  out[1] = y * len;
735
- out[2] = z42 * len;
735
+ out[2] = z27 * len;
736
736
  return out;
737
737
  };
738
738
  module.exports = normalize;
@@ -856,8 +856,8 @@ var require_squaredDistance = __commonJS({
856
856
  var squaredDistance = (a, b) => {
857
857
  const x = b[0] - a[0];
858
858
  const y = b[1] - a[1];
859
- const z42 = b[2] - a[2];
860
- return x * x + y * y + z42 * z42;
859
+ const z27 = b[2] - a[2];
860
+ return x * x + y * y + z27 * z27;
861
861
  };
862
862
  module.exports = squaredDistance;
863
863
  }
@@ -870,8 +870,8 @@ var require_squaredLength = __commonJS({
870
870
  var squaredLength = (vector) => {
871
871
  const x = vector[0];
872
872
  const y = vector[1];
873
- const z42 = vector[2];
874
- return x * x + y * y + z42 * z42;
873
+ const z27 = vector[2];
874
+ return x * x + y * y + z27 * z27;
875
875
  };
876
876
  module.exports = squaredLength;
877
877
  }
@@ -907,12 +907,12 @@ var require_transform = __commonJS({
907
907
  var transform = (out, vector, matrix) => {
908
908
  const x = vector[0];
909
909
  const y = vector[1];
910
- const z42 = vector[2];
911
- let w = matrix[3] * x + matrix[7] * y + matrix[11] * z42 + matrix[15];
910
+ const z27 = vector[2];
911
+ let w = matrix[3] * x + matrix[7] * y + matrix[11] * z27 + matrix[15];
912
912
  w = w || 1;
913
- out[0] = (matrix[0] * x + matrix[4] * y + matrix[8] * z42 + matrix[12]) / w;
914
- out[1] = (matrix[1] * x + matrix[5] * y + matrix[9] * z42 + matrix[13]) / w;
915
- out[2] = (matrix[2] * x + matrix[6] * y + matrix[10] * z42 + matrix[14]) / w;
913
+ out[0] = (matrix[0] * x + matrix[4] * y + matrix[8] * z27 + matrix[12]) / w;
914
+ out[1] = (matrix[1] * x + matrix[5] * y + matrix[9] * z27 + matrix[13]) / w;
915
+ out[2] = (matrix[2] * x + matrix[6] * y + matrix[10] * z27 + matrix[14]) / w;
916
916
  return out;
917
917
  };
918
918
  module.exports = transform;
@@ -1114,8 +1114,8 @@ var require_isMirroring = __commonJS({
1114
1114
  var isMirroring = (matrix) => {
1115
1115
  const x = matrix[4] * matrix[9] - matrix[8] * matrix[5];
1116
1116
  const y = matrix[8] * matrix[1] - matrix[0] * matrix[9];
1117
- const z42 = matrix[0] * matrix[5] - matrix[4] * matrix[1];
1118
- const d = x * matrix[2] + y * matrix[6] + z42 * matrix[10];
1117
+ const z27 = matrix[0] * matrix[5] - matrix[4] * matrix[1];
1118
+ const d = x * matrix[2] + y * matrix[6] + z27 * matrix[10];
1119
1119
  return d < 0;
1120
1120
  };
1121
1121
  module.exports = isMirroring;
@@ -1217,15 +1217,15 @@ var require_rotate = __commonJS({
1217
1217
  var { sin, cos } = require_trigonometry();
1218
1218
  var copy = require_copy();
1219
1219
  var rotate2 = (out, matrix, radians, axis) => {
1220
- let [x, y, z42] = axis;
1221
- const lengthSquared = x * x + y * y + z42 * z42;
1220
+ let [x, y, z27] = axis;
1221
+ const lengthSquared = x * x + y * y + z27 * z27;
1222
1222
  if (Math.abs(lengthSquared) < EPS3) {
1223
1223
  return copy(out, matrix);
1224
1224
  }
1225
1225
  const len = 1 / Math.sqrt(lengthSquared);
1226
1226
  x *= len;
1227
1227
  y *= len;
1228
- z42 *= len;
1228
+ z27 *= len;
1229
1229
  const s = sin(radians);
1230
1230
  const c = cos(radians);
1231
1231
  const t = 1 - c;
@@ -1242,14 +1242,14 @@ var require_rotate = __commonJS({
1242
1242
  const a22 = matrix[10];
1243
1243
  const a23 = matrix[11];
1244
1244
  const b00 = x * x * t + c;
1245
- const b01 = y * x * t + z42 * s;
1246
- const b02 = z42 * x * t - y * s;
1247
- const b10 = x * y * t - z42 * s;
1245
+ const b01 = y * x * t + z27 * s;
1246
+ const b02 = z27 * x * t - y * s;
1247
+ const b10 = x * y * t - z27 * s;
1248
1248
  const b11 = y * y * t + c;
1249
- const b12 = z42 * y * t + x * s;
1250
- const b20 = x * z42 * t + y * s;
1251
- const b21 = y * z42 * t - x * s;
1252
- const b22 = z42 * z42 * t + c;
1249
+ const b12 = z27 * y * t + x * s;
1250
+ const b20 = x * z27 * t + y * s;
1251
+ const b21 = y * z27 * t - x * s;
1252
+ const b22 = z27 * z27 * t + c;
1253
1253
  out[0] = a00 * b00 + a10 * b01 + a20 * b02;
1254
1254
  out[1] = a01 * b00 + a11 * b01 + a21 * b02;
1255
1255
  out[2] = a02 * b00 + a12 * b01 + a22 * b02;
@@ -1401,7 +1401,7 @@ var require_scale2 = __commonJS({
1401
1401
  var scale2 = (out, matrix, dimensions) => {
1402
1402
  const x = dimensions[0];
1403
1403
  const y = dimensions[1];
1404
- const z42 = dimensions[2];
1404
+ const z27 = dimensions[2];
1405
1405
  out[0] = matrix[0] * x;
1406
1406
  out[1] = matrix[1] * x;
1407
1407
  out[2] = matrix[2] * x;
@@ -1410,10 +1410,10 @@ var require_scale2 = __commonJS({
1410
1410
  out[5] = matrix[5] * y;
1411
1411
  out[6] = matrix[6] * y;
1412
1412
  out[7] = matrix[7] * y;
1413
- out[8] = matrix[8] * z42;
1414
- out[9] = matrix[9] * z42;
1415
- out[10] = matrix[10] * z42;
1416
- out[11] = matrix[11] * z42;
1413
+ out[8] = matrix[8] * z27;
1414
+ out[9] = matrix[9] * z27;
1415
+ out[10] = matrix[10] * z27;
1416
+ out[11] = matrix[11] * z27;
1417
1417
  out[12] = matrix[12];
1418
1418
  out[13] = matrix[13];
1419
1419
  out[14] = matrix[14];
@@ -1467,7 +1467,7 @@ var require_translate = __commonJS({
1467
1467
  var translate6 = (out, matrix, offsets) => {
1468
1468
  const x = offsets[0];
1469
1469
  const y = offsets[1];
1470
- const z42 = offsets[2];
1470
+ const z27 = offsets[2];
1471
1471
  let a00;
1472
1472
  let a01;
1473
1473
  let a02;
@@ -1481,10 +1481,10 @@ var require_translate = __commonJS({
1481
1481
  let a22;
1482
1482
  let a23;
1483
1483
  if (matrix === out) {
1484
- out[12] = matrix[0] * x + matrix[4] * y + matrix[8] * z42 + matrix[12];
1485
- out[13] = matrix[1] * x + matrix[5] * y + matrix[9] * z42 + matrix[13];
1486
- out[14] = matrix[2] * x + matrix[6] * y + matrix[10] * z42 + matrix[14];
1487
- out[15] = matrix[3] * x + matrix[7] * y + matrix[11] * z42 + matrix[15];
1484
+ out[12] = matrix[0] * x + matrix[4] * y + matrix[8] * z27 + matrix[12];
1485
+ out[13] = matrix[1] * x + matrix[5] * y + matrix[9] * z27 + matrix[13];
1486
+ out[14] = matrix[2] * x + matrix[6] * y + matrix[10] * z27 + matrix[14];
1487
+ out[15] = matrix[3] * x + matrix[7] * y + matrix[11] * z27 + matrix[15];
1488
1488
  } else {
1489
1489
  a00 = matrix[0];
1490
1490
  a01 = matrix[1];
@@ -1510,10 +1510,10 @@ var require_translate = __commonJS({
1510
1510
  out[9] = a21;
1511
1511
  out[10] = a22;
1512
1512
  out[11] = a23;
1513
- out[12] = a00 * x + a10 * y + a20 * z42 + matrix[12];
1514
- out[13] = a01 * x + a11 * y + a21 * z42 + matrix[13];
1515
- out[14] = a02 * x + a12 * y + a22 * z42 + matrix[14];
1516
- out[15] = a03 * x + a13 * y + a23 * z42 + matrix[15];
1513
+ out[12] = a00 * x + a10 * y + a20 * z27 + matrix[12];
1514
+ out[13] = a01 * x + a11 * y + a21 * z27 + matrix[13];
1515
+ out[14] = a02 * x + a12 * y + a22 * z27 + matrix[14];
1516
+ out[15] = a03 * x + a13 * y + a23 * z27 + matrix[15];
1517
1517
  }
1518
1518
  return out;
1519
1519
  };
@@ -2351,7 +2351,7 @@ var require_validate = __commonJS({
2351
2351
  var vec2 = require_vec2();
2352
2352
  var isA = require_isA();
2353
2353
  var toOutlines = require_toOutlines();
2354
- var validate = (object) => {
2354
+ var validate2 = (object) => {
2355
2355
  if (!isA(object)) {
2356
2356
  throw new Error("invalid geom2 structure");
2357
2357
  }
@@ -2365,7 +2365,7 @@ var require_validate = __commonJS({
2365
2365
  throw new Error(`geom2 invalid transforms ${object.transforms}`);
2366
2366
  }
2367
2367
  };
2368
- module.exports = validate;
2368
+ module.exports = validate2;
2369
2369
  }
2370
2370
  });
2371
2371
 
@@ -2616,9 +2616,9 @@ var require_HalfEdge = __commonJS({
2616
2616
  var distance6 = require_distance();
2617
2617
  var squaredDistance = require_squaredDistance();
2618
2618
  var HalfEdge = class {
2619
- constructor(vertex, face) {
2619
+ constructor(vertex, face2) {
2620
2620
  this.vertex = vertex;
2621
- this.face = face;
2621
+ this.face = face2;
2622
2622
  this.next = null;
2623
2623
  this.prev = null;
2624
2624
  this.opposite = null;
@@ -2844,16 +2844,16 @@ var require_Face = __commonJS({
2844
2844
  return indices;
2845
2845
  }
2846
2846
  static createTriangle(v0, v1, v2, minArea = 0) {
2847
- const face = new _Face();
2848
- const e0 = new HalfEdge(v0, face);
2849
- const e1 = new HalfEdge(v1, face);
2850
- const e2 = new HalfEdge(v2, face);
2847
+ const face2 = new _Face();
2848
+ const e0 = new HalfEdge(v0, face2);
2849
+ const e1 = new HalfEdge(v1, face2);
2850
+ const e2 = new HalfEdge(v2, face2);
2851
2851
  e0.next = e2.prev = e1;
2852
2852
  e1.next = e0.prev = e2;
2853
2853
  e2.next = e1.prev = e0;
2854
- face.edge = e0;
2855
- face.computeNormalAndCentroid(minArea);
2856
- return face;
2854
+ face2.edge = e0;
2855
+ face2.computeNormalAndCentroid(minArea);
2856
+ return face2;
2857
2857
  }
2858
2858
  };
2859
2859
  module.exports = {
@@ -2899,14 +2899,14 @@ var require_QuickHull = __commonJS({
2899
2899
  this.discardedFaces = [];
2900
2900
  this.vertexPointIndices = [];
2901
2901
  }
2902
- addVertexToFace(vertex, face) {
2903
- vertex.face = face;
2904
- if (!face.outside) {
2902
+ addVertexToFace(vertex, face2) {
2903
+ vertex.face = face2;
2904
+ if (!face2.outside) {
2905
2905
  this.claimed.add(vertex);
2906
2906
  } else {
2907
- this.claimed.insertBefore(face.outside, vertex);
2907
+ this.claimed.insertBefore(face2.outside, vertex);
2908
2908
  }
2909
- face.outside = vertex;
2909
+ face2.outside = vertex;
2910
2910
  }
2911
2911
  /**
2912
2912
  * Removes `vertex` for the `claimed` list of vertices, it also makes sure
@@ -2916,12 +2916,12 @@ var require_QuickHull = __commonJS({
2916
2916
  * @param {Vertex} vertex
2917
2917
  * @param {Face} face
2918
2918
  */
2919
- removeVertexFromFace(vertex, face) {
2920
- if (vertex === face.outside) {
2921
- if (vertex.next && vertex.next.face === face) {
2922
- face.outside = vertex.next;
2919
+ removeVertexFromFace(vertex, face2) {
2920
+ if (vertex === face2.outside) {
2921
+ if (vertex.next && vertex.next.face === face2) {
2922
+ face2.outside = vertex.next;
2923
2923
  } else {
2924
- face.outside = null;
2924
+ face2.outside = null;
2925
2925
  }
2926
2926
  }
2927
2927
  this.claimed.remove(vertex);
@@ -2934,15 +2934,15 @@ var require_QuickHull = __commonJS({
2934
2934
  * @return {Vertex|undefined} If face had visible vertices returns
2935
2935
  * `face.outside`, otherwise undefined
2936
2936
  */
2937
- removeAllVerticesFromFace(face) {
2938
- if (face.outside) {
2939
- let end = face.outside;
2940
- while (end.next && end.next.face === face) {
2937
+ removeAllVerticesFromFace(face2) {
2938
+ if (face2.outside) {
2939
+ let end = face2.outside;
2940
+ while (end.next && end.next.face === face2) {
2941
2941
  end = end.next;
2942
2942
  }
2943
- this.claimed.removeChain(face.outside, end);
2943
+ this.claimed.removeChain(face2.outside, end);
2944
2944
  end.next = null;
2945
- return face.outside;
2945
+ return face2.outside;
2946
2946
  }
2947
2947
  }
2948
2948
  /**
@@ -2959,8 +2959,8 @@ var require_QuickHull = __commonJS({
2959
2959
  * @param {Face} face
2960
2960
  * @param {Face} [absorbingFace]
2961
2961
  */
2962
- deleteFaceVertices(face, absorbingFace) {
2963
- const faceVertices = this.removeAllVerticesFromFace(face);
2962
+ deleteFaceVertices(face2, absorbingFace) {
2963
+ const faceVertices = this.removeAllVerticesFromFace(face2);
2964
2964
  if (faceVertices) {
2965
2965
  if (!absorbingFace) {
2966
2966
  this.unclaimed.addAll(faceVertices);
@@ -2991,12 +2991,12 @@ var require_QuickHull = __commonJS({
2991
2991
  let maxDistance = this.tolerance;
2992
2992
  let maxFace;
2993
2993
  for (let i = 0; i < newFaces.length; i += 1) {
2994
- const face = newFaces[i];
2995
- if (face.mark === VISIBLE) {
2996
- const dist = face.distanceToPlane(vertex.point);
2994
+ const face2 = newFaces[i];
2995
+ if (face2.mark === VISIBLE) {
2996
+ const dist = face2.distanceToPlane(vertex.point);
2997
2997
  if (dist > maxDistance) {
2998
2998
  maxDistance = dist;
2999
- maxFace = face;
2999
+ maxFace = face2;
3000
3000
  }
3001
3001
  if (maxDistance > 1e3 * this.tolerance) {
3002
3002
  break;
@@ -3142,9 +3142,9 @@ var require_QuickHull = __commonJS({
3142
3142
  reindexFaceAndVertices() {
3143
3143
  const activeFaces = [];
3144
3144
  for (let i = 0; i < this.faces.length; i += 1) {
3145
- const face = this.faces[i];
3146
- if (face.mark === VISIBLE) {
3147
- activeFaces.push(face);
3145
+ const face2 = this.faces[i];
3146
+ if (face2.mark === VISIBLE) {
3147
+ activeFaces.push(face2);
3148
3148
  }
3149
3149
  }
3150
3150
  this.faces = activeFaces;
@@ -3205,12 +3205,12 @@ var require_QuickHull = __commonJS({
3205
3205
  * @param {HalfEdge[]} horizon - The edges that form part of the horizon in
3206
3206
  * ccw order
3207
3207
  */
3208
- computeHorizon(eyePoint, crossEdge, face, horizon) {
3209
- this.deleteFaceVertices(face);
3210
- face.mark = DELETED;
3208
+ computeHorizon(eyePoint, crossEdge, face2, horizon) {
3209
+ this.deleteFaceVertices(face2);
3210
+ face2.mark = DELETED;
3211
3211
  let edge;
3212
3212
  if (!crossEdge) {
3213
- edge = crossEdge = face.getEdge(0);
3213
+ edge = crossEdge = face2.getEdge(0);
3214
3214
  } else {
3215
3215
  edge = crossEdge.next;
3216
3216
  }
@@ -3236,14 +3236,14 @@ var require_QuickHull = __commonJS({
3236
3236
  * @return {HalfEdge} The half edge whose vertex is the eyeVertex
3237
3237
  */
3238
3238
  addAdjoiningFace(eyeVertex, horizonEdge) {
3239
- const face = Face.createTriangle(
3239
+ const face2 = Face.createTriangle(
3240
3240
  eyeVertex,
3241
3241
  horizonEdge.tail(),
3242
3242
  horizonEdge.head()
3243
3243
  );
3244
- this.faces.push(face);
3245
- face.getEdge(-1).setOpposite(horizonEdge.opposite);
3246
- return face.getEdge(0);
3244
+ this.faces.push(face2);
3245
+ face2.getEdge(-1).setOpposite(horizonEdge.opposite);
3246
+ return face2.getEdge(0);
3247
3247
  }
3248
3248
  /**
3249
3249
  * Adds horizon.length faces to the hull, each face will be 'linked' with the
@@ -3318,12 +3318,12 @@ var require_QuickHull = __commonJS({
3318
3318
  * @param {number} mergeType - Either MERGE_NON_CONVEX_WRT_LARGER_FACE or
3319
3319
  * MERGE_NON_CONVEX
3320
3320
  */
3321
- doAdjacentMerge(face, mergeType) {
3322
- let edge = face.edge;
3321
+ doAdjacentMerge(face2, mergeType) {
3322
+ let edge = face2.edge;
3323
3323
  let convex = true;
3324
3324
  let it = 0;
3325
3325
  do {
3326
- if (it >= face.nVertices) {
3326
+ if (it >= face2.nVertices) {
3327
3327
  throw Error("merge recursion limit exceeded");
3328
3328
  }
3329
3329
  const oppositeFace = edge.opposite.face;
@@ -3333,7 +3333,7 @@ var require_QuickHull = __commonJS({
3333
3333
  merge = true;
3334
3334
  }
3335
3335
  } else {
3336
- if (face.area > oppositeFace.area) {
3336
+ if (face2.area > oppositeFace.area) {
3337
3337
  if (this.oppositeFaceDistance(edge) > -this.tolerance) {
3338
3338
  merge = true;
3339
3339
  } else if (this.oppositeFaceDistance(edge.opposite) > -this.tolerance) {
@@ -3348,17 +3348,17 @@ var require_QuickHull = __commonJS({
3348
3348
  }
3349
3349
  }
3350
3350
  if (merge) {
3351
- const discardedFaces = face.mergeAdjacentFaces(edge, []);
3351
+ const discardedFaces = face2.mergeAdjacentFaces(edge, []);
3352
3352
  for (let i = 0; i < discardedFaces.length; i += 1) {
3353
- this.deleteFaceVertices(discardedFaces[i], face);
3353
+ this.deleteFaceVertices(discardedFaces[i], face2);
3354
3354
  }
3355
3355
  return true;
3356
3356
  }
3357
3357
  edge = edge.next;
3358
3358
  it += 1;
3359
- } while (edge !== face.edge);
3359
+ } while (edge !== face2.edge);
3360
3360
  if (!convex) {
3361
- face.mark = NON_CONVEX;
3361
+ face2.mark = NON_CONVEX;
3362
3362
  }
3363
3363
  return false;
3364
3364
  }
@@ -3387,17 +3387,17 @@ var require_QuickHull = __commonJS({
3387
3387
  this.computeHorizon(eyeVertex.point, null, eyeVertex.face, horizon);
3388
3388
  this.addNewFaces(eyeVertex, horizon);
3389
3389
  for (let i = 0; i < this.newFaces.length; i += 1) {
3390
- const face = this.newFaces[i];
3391
- if (face.mark === VISIBLE) {
3392
- while (this.doAdjacentMerge(face, MERGE_NON_CONVEX_WRT_LARGER_FACE)) {
3390
+ const face2 = this.newFaces[i];
3391
+ if (face2.mark === VISIBLE) {
3392
+ while (this.doAdjacentMerge(face2, MERGE_NON_CONVEX_WRT_LARGER_FACE)) {
3393
3393
  }
3394
3394
  }
3395
3395
  }
3396
3396
  for (let i = 0; i < this.newFaces.length; i += 1) {
3397
- const face = this.newFaces[i];
3398
- if (face.mark === NON_CONVEX) {
3399
- face.mark = VISIBLE;
3400
- while (this.doAdjacentMerge(face, MERGE_NON_CONVEX)) {
3397
+ const face2 = this.newFaces[i];
3398
+ if (face2.mark === NON_CONVEX) {
3399
+ face2.mark = VISIBLE;
3400
+ while (this.doAdjacentMerge(face2, MERGE_NON_CONVEX)) {
3401
3401
  }
3402
3402
  }
3403
3403
  }
@@ -3583,11 +3583,11 @@ var require_fromValues4 = __commonJS({
3583
3583
  "node_modules/@jscad/modeling/src/maths/vec4/fromValues.js"(exports, module) {
3584
3584
  "use strict";
3585
3585
  var create = require_create7();
3586
- var fromValues = (x, y, z42, w) => {
3586
+ var fromValues = (x, y, z27, w) => {
3587
3587
  const out = create();
3588
3588
  out[0] = x;
3589
3589
  out[1] = y;
3590
- out[2] = z42;
3590
+ out[2] = z27;
3591
3591
  out[3] = w;
3592
3592
  return out;
3593
3593
  };
@@ -3745,8 +3745,8 @@ var require_projectionOfPoint = __commonJS({
3745
3745
  const a = point[0] * plane[0] + point[1] * plane[1] + point[2] * plane[2] - plane[3];
3746
3746
  const x = point[0] - a * plane[0];
3747
3747
  const y = point[1] - a * plane[1];
3748
- const z42 = point[2] - a * plane[2];
3749
- return vec3.fromValues(x, y, z42);
3748
+ const z27 = point[2] - a * plane[2];
3749
+ return vec3.fromValues(x, y, z27);
3750
3750
  };
3751
3751
  module.exports = projectionOfPoint;
3752
3752
  }
@@ -4050,11 +4050,11 @@ var require_transform5 = __commonJS({
4050
4050
  "node_modules/@jscad/modeling/src/maths/vec4/transform.js"(exports, module) {
4051
4051
  "use strict";
4052
4052
  var transform = (out, vector, matrix) => {
4053
- const [x, y, z42, w] = vector;
4054
- out[0] = matrix[0] * x + matrix[4] * y + matrix[8] * z42 + matrix[12] * w;
4055
- out[1] = matrix[1] * x + matrix[5] * y + matrix[9] * z42 + matrix[13] * w;
4056
- out[2] = matrix[2] * x + matrix[6] * y + matrix[10] * z42 + matrix[14] * w;
4057
- out[3] = matrix[3] * x + matrix[7] * y + matrix[11] * z42 + matrix[15] * w;
4053
+ const [x, y, z27, w] = vector;
4054
+ out[0] = matrix[0] * x + matrix[4] * y + matrix[8] * z27 + matrix[12] * w;
4055
+ out[1] = matrix[1] * x + matrix[5] * y + matrix[9] * z27 + matrix[13] * w;
4056
+ out[2] = matrix[2] * x + matrix[6] * y + matrix[10] * z27 + matrix[14] * w;
4057
+ out[3] = matrix[3] * x + matrix[7] * y + matrix[11] * z27 + matrix[15] * w;
4058
4058
  return out;
4059
4059
  };
4060
4060
  module.exports = transform;
@@ -4116,8 +4116,8 @@ var require_measureBoundingSphere = __commonJS({
4116
4116
  out[2] = (minz[2] + maxz[2]) * 0.5;
4117
4117
  const x = out[0] - maxx[0];
4118
4118
  const y = out[1] - maxy[1];
4119
- const z42 = out[2] - maxz[2];
4120
- out[3] = Math.sqrt(x * x + y * y + z42 * z42);
4119
+ const z27 = out[2] - maxz[2];
4120
+ out[3] = Math.sqrt(x * x + y * y + z27 * z27);
4121
4121
  cache.set(polygon2, out);
4122
4122
  return out;
4123
4123
  };
@@ -4200,7 +4200,7 @@ var require_validate2 = __commonJS({
4200
4200
  var isConvex = require_isConvex();
4201
4201
  var measureArea = require_measureArea();
4202
4202
  var plane = require_plane2();
4203
- var validate = (object) => {
4203
+ var validate2 = (object) => {
4204
4204
  if (!isA(object)) {
4205
4205
  throw new Error("invalid poly3 structure");
4206
4206
  }
@@ -4233,7 +4233,7 @@ var require_validate2 = __commonJS({
4233
4233
  });
4234
4234
  }
4235
4235
  };
4236
- module.exports = validate;
4236
+ module.exports = validate2;
4237
4237
  }
4238
4238
  });
4239
4239
 
@@ -4274,8 +4274,8 @@ var require_fromPointsConvex = __commonJS({
4274
4274
  throw new Error("the given points must be an array");
4275
4275
  }
4276
4276
  const faces = quickhull(uniquePoints, { skipTriangulation: true });
4277
- const polygons = faces.map((face) => {
4278
- const vertices = face.map((index2) => uniquePoints[index2]);
4277
+ const polygons = faces.map((face2) => {
4278
+ const vertices = face2.map((index2) => uniquePoints[index2]);
4279
4279
  return poly3.create(vertices);
4280
4280
  });
4281
4281
  return create(polygons);
@@ -4552,7 +4552,7 @@ var require_validate3 = __commonJS({
4552
4552
  "use strict";
4553
4553
  var poly3 = require_poly3();
4554
4554
  var isA = require_isA3();
4555
- var validate = (object) => {
4555
+ var validate2 = (object) => {
4556
4556
  if (!isA(object)) {
4557
4557
  throw new Error("invalid geom3 structure");
4558
4558
  }
@@ -4586,7 +4586,7 @@ var require_validate3 = __commonJS({
4586
4586
  ${nonManifold.join("\n")}`);
4587
4587
  }
4588
4588
  };
4589
- module.exports = validate;
4589
+ module.exports = validate2;
4590
4590
  }
4591
4591
  });
4592
4592
 
@@ -5146,7 +5146,7 @@ var require_validate4 = __commonJS({
5146
5146
  "use strict";
5147
5147
  var vec2 = require_vec2();
5148
5148
  var isA = require_isA4();
5149
- var validate = (object) => {
5149
+ var validate2 = (object) => {
5150
5150
  if (!isA(object)) {
5151
5151
  throw new Error("invalid path2 structure");
5152
5152
  }
@@ -5166,7 +5166,7 @@ var require_validate4 = __commonJS({
5166
5166
  throw new Error(`path2 invalid transforms ${object.transforms}`);
5167
5167
  }
5168
5168
  };
5169
- module.exports = validate;
5169
+ module.exports = validate2;
5170
5170
  }
5171
5171
  });
5172
5172
 
@@ -5816,17 +5816,17 @@ var require_lengths = __commonJS({
5816
5816
  "node_modules/@jscad/modeling/src/curves/bezier/lengths.js"(exports, module) {
5817
5817
  "use strict";
5818
5818
  var valueAt = require_valueAt();
5819
- var lengths = (segments, bezier) => {
5819
+ var lengths3 = (segments, bezier) => {
5820
5820
  let sum = 0;
5821
- const lengths2 = [0];
5821
+ const lengths4 = [0];
5822
5822
  let previous = valueAt(0, bezier);
5823
5823
  for (let index2 = 1; index2 <= segments; index2++) {
5824
5824
  const current = valueAt(index2 / segments, bezier);
5825
5825
  sum += distanceBetween(current, previous);
5826
- lengths2.push(sum);
5826
+ lengths4.push(sum);
5827
5827
  previous = current;
5828
5828
  }
5829
- return lengths2;
5829
+ return lengths4;
5830
5830
  };
5831
5831
  var distanceBetween = (a, b) => {
5832
5832
  if (Number.isFinite(a) && Number.isFinite(b)) {
@@ -5844,7 +5844,7 @@ var require_lengths = __commonJS({
5844
5844
  throw new Error("The operands must be of the same type, either number or array.");
5845
5845
  }
5846
5846
  };
5847
- module.exports = lengths;
5847
+ module.exports = lengths3;
5848
5848
  }
5849
5849
  });
5850
5850
 
@@ -5852,8 +5852,8 @@ var require_lengths = __commonJS({
5852
5852
  var require_length3 = __commonJS({
5853
5853
  "node_modules/@jscad/modeling/src/curves/bezier/length.js"(exports, module) {
5854
5854
  "use strict";
5855
- var lengths = require_lengths();
5856
- var length83 = (segments, bezier) => lengths(segments, bezier)[segments];
5855
+ var lengths3 = require_lengths();
5856
+ var length83 = (segments, bezier) => lengths3(segments, bezier)[segments];
5857
5857
  module.exports = length83;
5858
5858
  }
5859
5859
  });
@@ -5862,14 +5862,14 @@ var require_length3 = __commonJS({
5862
5862
  var require_arcLengthToT = __commonJS({
5863
5863
  "node_modules/@jscad/modeling/src/curves/bezier/arcLengthToT.js"(exports, module) {
5864
5864
  "use strict";
5865
- var lengths = require_lengths();
5865
+ var lengths3 = require_lengths();
5866
5866
  var arcLengthToT = (options, bezier) => {
5867
5867
  const defaults2 = {
5868
5868
  distance: 0,
5869
5869
  segments: 100
5870
5870
  };
5871
5871
  const { distance: distance6, segments } = Object.assign({}, defaults2, options);
5872
- const arcLengths = lengths(segments, bezier);
5872
+ const arcLengths = lengths3(segments, bezier);
5873
5873
  let startIndex = 0;
5874
5874
  let endIndex = segments;
5875
5875
  while (startIndex <= endIndex) {
@@ -7354,7 +7354,7 @@ var require_circle = __commonJS({
7354
7354
  var { TAU } = require_constants();
7355
7355
  var ellipse3 = require_ellipse();
7356
7356
  var { isGTE } = require_commonChecks();
7357
- var circle = (options) => {
7357
+ var circle2 = (options) => {
7358
7358
  const defaults2 = {
7359
7359
  center: [0, 0],
7360
7360
  radius: 1,
@@ -7367,7 +7367,7 @@ var require_circle = __commonJS({
7367
7367
  radius = [radius, radius];
7368
7368
  return ellipse3({ center, radius, startAngle, endAngle, segments });
7369
7369
  };
7370
- module.exports = circle;
7370
+ module.exports = circle2;
7371
7371
  }
7372
7372
  });
7373
7373
 
@@ -7682,15 +7682,15 @@ var require_polyhedron = __commonJS({
7682
7682
  points.forEach((point, i) => {
7683
7683
  if (!isNumberArray(point, 3)) throw new Error(`point ${i} must be an array of X, Y, Z values`);
7684
7684
  });
7685
- faces.forEach((face, i) => {
7686
- if (face.length < 3) throw new Error(`face ${i} must contain 3 or more indexes`);
7687
- if (!isNumberArray(face, face.length)) throw new Error(`face ${i} must be an array of numbers`);
7685
+ faces.forEach((face2, i) => {
7686
+ if (face2.length < 3) throw new Error(`face ${i} must contain 3 or more indexes`);
7687
+ if (!isNumberArray(face2, face2.length)) throw new Error(`face ${i} must be an array of numbers`);
7688
7688
  });
7689
7689
  if (orientation2 !== "outward") {
7690
- faces.forEach((face) => face.reverse());
7690
+ faces.forEach((face2) => face2.reverse());
7691
7691
  }
7692
- const polygons = faces.map((face, findex) => {
7693
- const polygon2 = poly3.create(face.map((pindex) => points[pindex]));
7692
+ const polygons = faces.map((face2, findex) => {
7693
+ const polygon2 = poly3.create(face2.map((pindex) => points[pindex]));
7694
7694
  if (colors2 && colors2[findex]) polygon2.color = colors2[findex];
7695
7695
  return polygon2;
7696
7696
  });
@@ -9594,7 +9594,7 @@ var require_torus = __commonJS({
9594
9594
  var extrudeRotate = require_extrudeRotate();
9595
9595
  var { rotate: rotate2 } = require_rotate3();
9596
9596
  var { translate: translate6 } = require_translate2();
9597
- var circle = require_circle();
9597
+ var circle2 = require_circle();
9598
9598
  var { isGT, isGTE } = require_commonChecks();
9599
9599
  var torus = (options) => {
9600
9600
  const defaults2 = {
@@ -9614,7 +9614,7 @@ var require_torus = __commonJS({
9614
9614
  if (!isGTE(startAngle, 0)) throw new Error("startAngle must be positive");
9615
9615
  if (!isGT(outerRotation, 0)) throw new Error("outerRotation must be greater than zero");
9616
9616
  if (innerRadius >= outerRadius) throw new Error("inner circle is too large to rotate about the outer circle");
9617
- let innerCircle = circle({ radius: innerRadius, segments: innerSegments });
9617
+ let innerCircle = circle2({ radius: innerRadius, segments: innerSegments });
9618
9618
  if (innerRotation !== 0) {
9619
9619
  innerCircle = rotate2([0, 0, innerRotation], innerCircle);
9620
9620
  }
@@ -9694,10 +9694,10 @@ var require_triangle2 = __commonJS({
9694
9694
  const b = c / Math.sin(C) * Math.sin(B);
9695
9695
  return createTriangle(A, B, C, a, b, c);
9696
9696
  };
9697
- var solveSSS = (lengths) => {
9698
- const a = lengths[1];
9699
- const b = lengths[2];
9700
- const c = lengths[0];
9697
+ var solveSSS = (lengths3) => {
9698
+ const a = lengths3[1];
9699
+ const b = lengths3[2];
9700
+ const c = lengths3[0];
9701
9701
  if (a + b <= c || b + c <= a || c + a <= b) {
9702
9702
  throw new Error("SSS triangle is incorrect, as the longest side is longer than the sum of the other sides");
9703
9703
  }
@@ -10056,11 +10056,11 @@ var require_areAllShapesTheSameType = __commonJS({
10056
10056
  var path2 = require_path2();
10057
10057
  var areAllShapesTheSameType = (shapes) => {
10058
10058
  let previousType;
10059
- for (const shape of shapes) {
10059
+ for (const shape2 of shapes) {
10060
10060
  let currentType = 0;
10061
- if (geom2.isA(shape)) currentType = 1;
10062
- if (geom3.isA(shape)) currentType = 2;
10063
- if (path2.isA(shape)) currentType = 3;
10061
+ if (geom2.isA(shape2)) currentType = 1;
10062
+ if (geom3.isA(shape2)) currentType = 2;
10063
+ if (path2.isA(shape2)) currentType = 3;
10064
10064
  if (previousType && currentType !== previousType) return false;
10065
10065
  previousType = currentType;
10066
10066
  }
@@ -11309,8 +11309,8 @@ var require_hullPoints3 = __commonJS({
11309
11309
  var quickhull = require_quickhull();
11310
11310
  var hullPoints3 = (uniquePoints) => {
11311
11311
  const faces = quickhull(uniquePoints, { skipTriangulation: true });
11312
- const polygons = faces.map((face) => {
11313
- const vertices = face.map((index2) => uniquePoints[index2]);
11312
+ const polygons = faces.map((face2) => {
11313
+ const vertices = face2.map((index2) => uniquePoints[index2]);
11314
11314
  return poly3.create(vertices);
11315
11315
  });
11316
11316
  return polygons;
@@ -13770,10 +13770,10 @@ var require_dist = __commonJS({
13770
13770
  })
13771
13771
  },
13772
13772
  colors: {
13773
- colorize: (color, shape) => ({
13773
+ colorize: (color, shape2) => ({
13774
13774
  type: "colorize",
13775
13775
  color,
13776
- shape
13776
+ shape: shape2
13777
13777
  })
13778
13778
  },
13779
13779
  primitives: {
@@ -13803,32 +13803,32 @@ var require_dist = __commonJS({
13803
13803
  })
13804
13804
  },
13805
13805
  transforms: {
13806
- rotate: (angles, shape) => ({
13806
+ rotate: (angles, shape2) => ({
13807
13807
  type: "rotate",
13808
13808
  angles,
13809
- shape
13809
+ shape: shape2
13810
13810
  }),
13811
- scale: (factors, shape) => ({
13811
+ scale: (factors, shape2) => ({
13812
13812
  type: "scale",
13813
13813
  factors,
13814
- shape
13814
+ shape: shape2
13815
13815
  }),
13816
- translate: (vector, shape) => ({
13816
+ translate: (vector, shape2) => ({
13817
13817
  type: "translate",
13818
13818
  vector,
13819
- shape
13819
+ shape: shape2
13820
13820
  })
13821
13821
  },
13822
13822
  extrusions: {
13823
- extrudeLinear: (options, shape) => ({
13823
+ extrudeLinear: (options, shape2) => ({
13824
13824
  type: "extrudeLinear",
13825
13825
  options,
13826
- shape
13826
+ shape: shape2
13827
13827
  }),
13828
- extrudeRotate: (options, shape) => ({
13828
+ extrudeRotate: (options, shape2) => ({
13829
13829
  type: "extrudeRotate",
13830
13830
  options,
13831
- shape
13831
+ shape: shape2
13832
13832
  })
13833
13833
  },
13834
13834
  maths: {
@@ -13837,8 +13837,8 @@ var require_dist = __commonJS({
13837
13837
  fromValues: (x, y) => [x, y]
13838
13838
  },
13839
13839
  vec3: {
13840
- create: (x, y, z42) => [x, y, z42],
13841
- fromValues: (x, y, z42) => [x, y, z42]
13840
+ create: (x, y, z27) => [x, y, z27],
13841
+ fromValues: (x, y, z27) => [x, y, z27]
13842
13842
  }
13843
13843
  },
13844
13844
  geometries: {
@@ -13862,17 +13862,17 @@ var require_dist = __commonJS({
13862
13862
  }
13863
13863
  },
13864
13864
  measurements: {
13865
- measureBoundingBox: (shape) => ({
13865
+ measureBoundingBox: (shape2) => ({
13866
13866
  type: "measureBoundingBox",
13867
- shape
13867
+ shape: shape2
13868
13868
  }),
13869
- measureArea: (shape) => ({
13869
+ measureArea: (shape2) => ({
13870
13870
  type: "measureArea",
13871
- shape
13871
+ shape: shape2
13872
13872
  }),
13873
- measureVolume: (shape) => ({
13873
+ measureVolume: (shape2) => ({
13874
13874
  type: "measureVolume",
13875
- shape
13875
+ shape: shape2
13876
13876
  })
13877
13877
  },
13878
13878
  utils: {
@@ -13880,77 +13880,77 @@ var require_dist = __commonJS({
13880
13880
  radToDeg: (radians) => radians * 180 / Math.PI
13881
13881
  }
13882
13882
  };
13883
- var executeJscadOperations3 = (jscad3, operation) => {
13883
+ var executeJscadOperations3 = (jscad5, operation) => {
13884
13884
  if (Array.isArray(operation) && operation.length === 1) {
13885
- return executeJscadOperations3(jscad3, operation[0]);
13885
+ return executeJscadOperations3(jscad5, operation[0]);
13886
13886
  }
13887
13887
  if (Array.isArray(operation)) {
13888
13888
  throw new Error(
13889
13889
  `executeJscadOperations currently doesn't support Array<JscadOperation>, try adding a root union or or executing each element individually`
13890
13890
  );
13891
13891
  }
13892
- const recurse = (op) => executeJscadOperations3(jscad3, op);
13892
+ const recurse = (op) => executeJscadOperations3(jscad5, op);
13893
13893
  const { type, ...params } = operation;
13894
13894
  switch (type) {
13895
13895
  case "intersect":
13896
- return jscad3.booleans.intersect(...operation.shapes.map(recurse));
13896
+ return jscad5.booleans.intersect(...operation.shapes.map(recurse));
13897
13897
  case "subtract":
13898
- return jscad3.booleans.subtract(...operation.shapes.map(recurse));
13898
+ return jscad5.booleans.subtract(...operation.shapes.map(recurse));
13899
13899
  case "union":
13900
- return jscad3.booleans.union(...operation.shapes.map(recurse));
13900
+ return jscad5.booleans.union(...operation.shapes.map(recurse));
13901
13901
  case "hull":
13902
- return jscad3.hulls.hull(...operation.shapes.map(recurse));
13902
+ return jscad5.hulls.hull(...operation.shapes.map(recurse));
13903
13903
  case "hullChain":
13904
- return jscad3.hulls.hullChain(...operation.shapes.map(recurse));
13904
+ return jscad5.hulls.hullChain(...operation.shapes.map(recurse));
13905
13905
  case "colorize":
13906
- return jscad3.colors.colorize(operation.color, recurse(operation.shape));
13906
+ return jscad5.colors.colorize(operation.color, recurse(operation.shape));
13907
13907
  case "cube":
13908
- return jscad3.primitives.cube(params);
13908
+ return jscad5.primitives.cube(params);
13909
13909
  case "sphere":
13910
- return jscad3.primitives.sphere(params);
13910
+ return jscad5.primitives.sphere(params);
13911
13911
  case "cylinder":
13912
- return jscad3.primitives.cylinder(params);
13912
+ return jscad5.primitives.cylinder(params);
13913
13913
  case "polygon":
13914
- return jscad3.primitives.polygon(params);
13914
+ return jscad5.primitives.polygon(params);
13915
13915
  case "cuboid":
13916
- return jscad3.primitives.cuboid(params);
13916
+ return jscad5.primitives.cuboid(params);
13917
13917
  case "roundedCuboid":
13918
- return jscad3.primitives.roundedCuboid(params);
13918
+ return jscad5.primitives.roundedCuboid(params);
13919
13919
  case "rotate":
13920
- return jscad3.transforms.rotate(operation.angles, recurse(operation.shape));
13920
+ return jscad5.transforms.rotate(operation.angles, recurse(operation.shape));
13921
13921
  case "scale":
13922
- return jscad3.transforms.scale(operation.factors, recurse(operation.shape));
13922
+ return jscad5.transforms.scale(operation.factors, recurse(operation.shape));
13923
13923
  case "translate":
13924
- return jscad3.transforms.translate(
13924
+ return jscad5.transforms.translate(
13925
13925
  operation.vector,
13926
13926
  recurse(operation.shape)
13927
13927
  );
13928
13928
  case "extrudeLinear":
13929
- return jscad3.extrusions.extrudeLinear(
13929
+ return jscad5.extrusions.extrudeLinear(
13930
13930
  operation.options,
13931
13931
  recurse(operation.shape)
13932
13932
  );
13933
13933
  case "extrudeRotate":
13934
- return jscad3.extrusions.extrudeRotate(
13934
+ return jscad5.extrusions.extrudeRotate(
13935
13935
  operation.options,
13936
13936
  recurse(operation.shape)
13937
13937
  );
13938
13938
  case "createGeom2":
13939
- return jscad3.geometries.geom2.create(operation.points);
13939
+ return jscad5.geometries.geom2.create(operation.points);
13940
13940
  case "createGeom3":
13941
- return jscad3.geometries.geom3.create(operation.polygons);
13941
+ return jscad5.geometries.geom3.create(operation.polygons);
13942
13942
  case "createPath2":
13943
- return jscad3.geometries.path2.create(operation.points);
13943
+ return jscad5.geometries.path2.create(operation.points);
13944
13944
  case "measureBoundingBox":
13945
- return jscad3.measurements.measureBoundingBox(recurse(operation.shape));
13945
+ return jscad5.measurements.measureBoundingBox(recurse(operation.shape));
13946
13946
  case "measureArea":
13947
- return jscad3.measurements.measureArea(recurse(operation.shape));
13947
+ return jscad5.measurements.measureArea(recurse(operation.shape));
13948
13948
  case "measureVolume":
13949
- return jscad3.measurements.measureVolume(recurse(operation.shape));
13949
+ return jscad5.measurements.measureVolume(recurse(operation.shape));
13950
13950
  case "degToRad":
13951
- return jscad3.utils.degToRad(operation.degrees);
13951
+ return jscad5.utils.degToRad(operation.degrees);
13952
13952
  case "radToDeg":
13953
- return jscad3.utils.radToDeg(operation.radians);
13953
+ return jscad5.utils.radToDeg(operation.radians);
13954
13954
  default:
13955
13955
  if (operation.type === void 0) {
13956
13956
  throw new Error(
@@ -14789,15 +14789,8 @@ var Html = ({ children, position, style }) => {
14789
14789
  return portal;
14790
14790
  };
14791
14791
 
14792
- // node_modules/@tscircuit/footprinter/dist/index.js
14793
- import {
14794
- length as length82
14795
- } from "circuit-json";
14796
- import { length } from "circuit-json";
14797
- import { z as z3 } from "zod";
14792
+ // node_modules/@tscircuit/modelprinter/index.js
14798
14793
  import { z as z2 } from "zod";
14799
- import { z } from "zod";
14800
- import { z as z4 } from "zod";
14801
14794
 
14802
14795
  // node_modules/@tscircuit/mm/dist/index.js
14803
14796
  var unitToMm = {
@@ -14810,6 +14803,11 @@ var unitToMm = {
14810
14803
  ft: 304.8,
14811
14804
  feet: 304.8
14812
14805
  };
14806
+ var mmNumberFormatter = new Intl.NumberFormat("en-US", {
14807
+ useGrouping: false,
14808
+ notation: "standard",
14809
+ maximumFractionDigits: 12
14810
+ });
14813
14811
  var mm = (n) => {
14814
14812
  let unit = typeof n === "number" ? "mm" : n.replace(/^[^a-zA-Z]+/g, "").toLowerCase();
14815
14813
  if (!unit)
@@ -14820,15 +14818,958 @@ var mm = (n) => {
14820
14818
  }
14821
14819
  throw new Error(`Unsupported unit: ${unit}`);
14822
14820
  };
14823
- var mm_default = mm;
14821
+
14822
+ // node_modules/@tscircuit/modelprinter/index.js
14823
+ import { z } from "zod";
14824
+ import { z as z3 } from "zod";
14825
+ import { z as z5 } from "zod";
14826
+ import { z as z4 } from "zod";
14827
+ var modelLengthSchema = z.union([z.number(), z.string()]).transform((value, context) => {
14828
+ try {
14829
+ const parsed = mm(value);
14830
+ if (!Number.isFinite(parsed)) throw new Error("Length is not finite");
14831
+ return parsed;
14832
+ } catch {
14833
+ context.addIssue({
14834
+ code: "custom",
14835
+ message: `Invalid model length: ${String(value)}`
14836
+ });
14837
+ return z.NEVER;
14838
+ }
14839
+ });
14840
+ var positiveModelLengthSchema = modelLengthSchema.refine(
14841
+ (value) => value > 0,
14842
+ "Length must be greater than zero"
14843
+ );
14844
+ var nonnegativeModelLengthSchema = modelLengthSchema.refine(
14845
+ (value) => value >= 0,
14846
+ "Length cannot be negative"
14847
+ );
14848
+ var nemaSizeSchema = z2.union([
14849
+ z2.literal(8),
14850
+ z2.literal(17),
14851
+ z2.literal(23)
14852
+ ]);
14853
+ var nemaMotorDimensions = {
14854
+ 8: {
14855
+ bodyWidth: 20.3,
14856
+ bodyLength: 33,
14857
+ mountingHoleSpacing: 16,
14858
+ mountingHoleDiameter: 2,
14859
+ mountingHoleDepth: 2,
14860
+ mountingHoleThrough: false,
14861
+ pilotDiameter: 15,
14862
+ pilotLength: 1.5,
14863
+ shaftDiameter: 4,
14864
+ shaftLength: 15,
14865
+ shaftShape: "round",
14866
+ shaftFlatDepth: 0.5,
14867
+ shaftFlatLength: 10,
14868
+ shaftFlatAngle: 0,
14869
+ frontCapLength: 3.5,
14870
+ rearCapLength: 3.5,
14871
+ faceCornerChamfer: 0.5,
14872
+ bodyCornerChamfer: 3
14873
+ },
14874
+ 17: {
14875
+ bodyWidth: 42.3,
14876
+ bodyLength: 38,
14877
+ mountingHoleSpacing: 31,
14878
+ mountingHoleDiameter: 3,
14879
+ mountingHoleDepth: 4.5,
14880
+ mountingHoleThrough: false,
14881
+ pilotDiameter: 22,
14882
+ pilotLength: 2,
14883
+ shaftDiameter: 5,
14884
+ shaftLength: 24,
14885
+ shaftShape: "d",
14886
+ shaftFlatDepth: 0.5,
14887
+ shaftFlatLength: 15,
14888
+ shaftFlatAngle: 0,
14889
+ frontCapLength: 5,
14890
+ rearCapLength: 5,
14891
+ faceCornerChamfer: 3,
14892
+ bodyCornerChamfer: 6
14893
+ },
14894
+ 23: {
14895
+ bodyWidth: 56.4,
14896
+ bodyLength: 51,
14897
+ mountingHoleSpacing: 47.14,
14898
+ mountingHoleDiameter: 5,
14899
+ mountingHoleDepth: 5,
14900
+ mountingHoleThrough: true,
14901
+ pilotDiameter: 38.1,
14902
+ pilotLength: 1.6,
14903
+ shaftDiameter: 6.35,
14904
+ shaftLength: 20.6,
14905
+ shaftShape: "d",
14906
+ shaftFlatDepth: 0.5,
14907
+ shaftFlatLength: 15,
14908
+ shaftFlatAngle: 0,
14909
+ frontCapLength: 5,
14910
+ rearCapLength: 5,
14911
+ faceCornerChamfer: 2,
14912
+ bodyCornerChamfer: 15
14913
+ }
14914
+ };
14915
+ var shape = {
14916
+ nemaSize: nemaSizeSchema,
14917
+ bodyWidth: positiveModelLengthSchema.optional(),
14918
+ bodyLength: positiveModelLengthSchema.optional(),
14919
+ mountingHoleSpacing: positiveModelLengthSchema.optional(),
14920
+ mountingHoleDiameter: positiveModelLengthSchema.optional(),
14921
+ mountingHoleDepth: positiveModelLengthSchema.optional(),
14922
+ mountingHoleThrough: z2.boolean().optional(),
14923
+ pilotDiameter: positiveModelLengthSchema.optional(),
14924
+ pilotLength: positiveModelLengthSchema.optional(),
14925
+ /** Distance from mounting face Z=0 to shaft tip, including pilot height. */
14926
+ shaftLength: positiveModelLengthSchema.optional(),
14927
+ shaftDiameter: positiveModelLengthSchema.optional(),
14928
+ shaftShape: z2.enum(["round", "d"]).optional(),
14929
+ /** Radial material removed from the +X side before rotation. */
14930
+ shaftFlatDepth: nonnegativeModelLengthSchema.optional(),
14931
+ /** Flat extends back from the tip; leaves a round shoulder above the pilot. */
14932
+ shaftFlatLength: nonnegativeModelLengthSchema.optional(),
14933
+ /** Degrees around +Z, counterclockwise; zero puts the flat on +X. */
14934
+ shaftFlatAngle: z2.number().finite().optional(),
14935
+ frontCapLength: positiveModelLengthSchema.optional(),
14936
+ rearCapLength: positiveModelLengthSchema.optional(),
14937
+ faceCornerChamfer: nonnegativeModelLengthSchema.optional(),
14938
+ bodyCornerChamfer: nonnegativeModelLengthSchema.optional()
14939
+ };
14940
+ var resolve = (p) => {
14941
+ const d = nemaMotorDimensions[p.nemaSize];
14942
+ return {
14943
+ nemaSize: p.nemaSize,
14944
+ bodyWidth: p.bodyWidth ?? d.bodyWidth,
14945
+ bodyLength: p.bodyLength ?? d.bodyLength,
14946
+ mountingHoleSpacing: p.mountingHoleSpacing ?? d.mountingHoleSpacing,
14947
+ mountingHoleDiameter: p.mountingHoleDiameter ?? d.mountingHoleDiameter,
14948
+ mountingHoleDepth: p.mountingHoleDepth ?? d.mountingHoleDepth,
14949
+ mountingHoleThrough: p.mountingHoleThrough ?? d.mountingHoleThrough,
14950
+ pilotDiameter: p.pilotDiameter ?? d.pilotDiameter,
14951
+ pilotLength: p.pilotLength ?? d.pilotLength,
14952
+ shaftDiameter: p.shaftDiameter ?? d.shaftDiameter,
14953
+ shaftLength: p.shaftLength ?? d.shaftLength,
14954
+ shaftShape: p.shaftShape ?? d.shaftShape,
14955
+ shaftFlatDepth: p.shaftFlatDepth ?? d.shaftFlatDepth,
14956
+ shaftFlatLength: p.shaftFlatLength ?? d.shaftFlatLength,
14957
+ shaftFlatAngle: p.shaftFlatAngle ?? d.shaftFlatAngle,
14958
+ frontCapLength: p.frontCapLength ?? d.frontCapLength,
14959
+ rearCapLength: p.rearCapLength ?? d.rearCapLength,
14960
+ faceCornerChamfer: p.faceCornerChamfer ?? d.faceCornerChamfer,
14961
+ bodyCornerChamfer: p.bodyCornerChamfer ?? d.bodyCornerChamfer
14962
+ };
14963
+ };
14964
+ var validate = (p, ctx) => {
14965
+ const issue = (message) => ctx.addIssue({ code: "custom", message });
14966
+ const r = p.mountingHoleDiameter / 2;
14967
+ if (p.frontCapLength + p.rearCapLength >= p.bodyLength)
14968
+ issue("End caps must leave a positive body length");
14969
+ if (p.faceCornerChamfer >= p.bodyWidth / 2 || p.bodyCornerChamfer >= p.bodyWidth / 2)
14970
+ issue("Chamfer must be smaller than half the body width");
14971
+ if (p.mountingHoleSpacing + 2 * r >= p.bodyWidth || p.bodyWidth - p.faceCornerChamfer - p.mountingHoleSpacing <= r * Math.SQRT2)
14972
+ issue("Mounting holes must fit entirely inside the front face");
14973
+ if (p.pilotDiameter >= p.bodyWidth || p.pilotDiameter <= p.shaftDiameter)
14974
+ issue(
14975
+ "Pilot diameter must exceed the shaft diameter and fit inside the face"
14976
+ );
14977
+ if (p.mountingHoleSpacing / Math.SQRT2 <= p.pilotDiameter / 2 + r)
14978
+ issue("Mounting holes must clear the pilot");
14979
+ if (!p.mountingHoleThrough && p.mountingHoleDepth >= p.frontCapLength)
14980
+ issue("Blind mounting hole depth must be less than the front cap length");
14981
+ if (p.mountingHoleThrough && p.bodyWidth - p.bodyCornerChamfer - p.mountingHoleSpacing >= -r * Math.SQRT2)
14982
+ issue("Body and rear cap must clear through mounting holes");
14983
+ if (p.shaftLength <= p.pilotLength)
14984
+ issue("Shaft tip must extend beyond the pilot");
14985
+ if (p.shaftShape === "d" && (p.shaftFlatDepth <= 0 || p.shaftFlatDepth >= p.shaftDiameter / 2 || p.shaftFlatLength <= 0 || p.shaftFlatLength > p.shaftLength - p.pilotLength))
14986
+ issue(
14987
+ "D flat must have positive depth less than the shaft radius and fit above the pilot"
14988
+ );
14989
+ };
14990
+ var nemaMotorModelPropsSchema = z2.object(shape).strict().transform(resolve).superRefine(validate);
14991
+ var nemaMotorModelDefinitionSchema = z2.object({ fn: z2.literal("nema"), ...shape }).strict().transform(({ fn, ...props }) => ({ fn, ...resolve(props) })).superRefine(validate);
14992
+ var holePosition = {
14993
+ panel: z3.enum(["base", "left", "right"]),
14994
+ /** Panel-local mm, centered on its straight section: u along its length,
14995
+ * v along the sheet width. Side-panel u increases upward. */
14996
+ u: modelLengthSchema,
14997
+ v: modelLengthSchema
14998
+ };
14999
+ var sheetMetalHoleSchema = z3.discriminatedUnion("shape", [
15000
+ z3.object({
15001
+ ...holePosition,
15002
+ shape: z3.literal("round"),
15003
+ diameter: positiveModelLengthSchema
15004
+ }).strict(),
15005
+ z3.object({
15006
+ ...holePosition,
15007
+ shape: z3.literal("slot"),
15008
+ length: positiveModelLengthSchema,
15009
+ width: positiveModelLengthSchema,
15010
+ axis: z3.enum(["u", "v"]).default("v")
15011
+ }).strict()
15012
+ ]);
15013
+ var sheetMetalShape = {
15014
+ profile: z3.enum(["plate", "angle", "channel"]).default("plate"),
15015
+ width: positiveModelLengthSchema,
15016
+ /** Straight base length between bend tangencies, not overall width. */
15017
+ baseLength: positiveModelLengthSchema,
15018
+ /** Straight flange length above the bend tangent. */
15019
+ flangeHeight: positiveModelLengthSchema.default(12),
15020
+ thickness: positiveModelLengthSchema.default(1),
15021
+ insideBendRadius: positiveModelLengthSchema.default(1),
15022
+ holes: z3.array(sheetMetalHoleSchema).max(100).default([])
15023
+ };
15024
+ var sheetMetalModelPropsSchema = z3.object(sheetMetalShape).strict();
15025
+ var sheetMetalModelDefinitionSchema = z3.object({ fn: z3.literal("sheetmetal"), ...sheetMetalShape }).strict();
15026
+ var hexSocketBoltDimensions = {
15027
+ M2: {
15028
+ diameter: 2,
15029
+ threadPitch: 0.4,
15030
+ headDiameter: 3.8,
15031
+ headHeight: 2,
15032
+ socketWidth: 1.5,
15033
+ socketDepth: 1
15034
+ },
15035
+ "M2.5": {
15036
+ diameter: 2.5,
15037
+ threadPitch: 0.45,
15038
+ headDiameter: 4.5,
15039
+ headHeight: 2.5,
15040
+ socketWidth: 2,
15041
+ socketDepth: 1.1
15042
+ },
15043
+ M3: {
15044
+ diameter: 3,
15045
+ threadPitch: 0.5,
15046
+ headDiameter: 5.5,
15047
+ headHeight: 3,
15048
+ socketWidth: 2.5,
15049
+ socketDepth: 1.3
15050
+ },
15051
+ M4: {
15052
+ diameter: 4,
15053
+ threadPitch: 0.7,
15054
+ headDiameter: 7,
15055
+ headHeight: 4,
15056
+ socketWidth: 3,
15057
+ socketDepth: 2
15058
+ },
15059
+ M5: {
15060
+ diameter: 5,
15061
+ threadPitch: 0.8,
15062
+ headDiameter: 8.5,
15063
+ headHeight: 5,
15064
+ socketWidth: 4,
15065
+ socketDepth: 2.5
15066
+ },
15067
+ M6: {
15068
+ diameter: 6,
15069
+ threadPitch: 1,
15070
+ headDiameter: 10,
15071
+ headHeight: 6,
15072
+ socketWidth: 5,
15073
+ socketDepth: 3
15074
+ },
15075
+ M8: {
15076
+ diameter: 8,
15077
+ threadPitch: 1.25,
15078
+ headDiameter: 13,
15079
+ headHeight: 8,
15080
+ socketWidth: 6,
15081
+ socketDepth: 4
15082
+ },
15083
+ M10: {
15084
+ diameter: 10,
15085
+ threadPitch: 1.5,
15086
+ headDiameter: 16,
15087
+ headHeight: 10,
15088
+ socketWidth: 8,
15089
+ socketDepth: 5
15090
+ },
15091
+ M12: {
15092
+ diameter: 12,
15093
+ threadPitch: 1.75,
15094
+ headDiameter: 18,
15095
+ headHeight: 12,
15096
+ socketWidth: 10,
15097
+ socketDepth: 6
15098
+ }
15099
+ };
15100
+ var metricBoltSizeSchema = z4.enum([
15101
+ "M2",
15102
+ "M2.5",
15103
+ "M3",
15104
+ "M4",
15105
+ "M5",
15106
+ "M6",
15107
+ "M8",
15108
+ "M10",
15109
+ "M12"
15110
+ ]);
15111
+ var hexSocketBoltModelPropsShape = {
15112
+ metricSize: metricBoltSizeSchema,
15113
+ /** Length under the head, excluding the head itself. */
15114
+ length: positiveModelLengthSchema,
15115
+ showThreads: z4.boolean().default(true)
15116
+ };
15117
+ var hexSocketBoltModelPropsSchema = z4.object(hexSocketBoltModelPropsShape).strict();
15118
+ var hexSocketBoltModelDefinitionSchema = z4.object({
15119
+ fn: z4.literal("hexsocketbolt"),
15120
+ ...hexSocketBoltModelPropsShape
15121
+ }).strict();
15122
+ var flexScreenOrientationSchema = z5.enum([
15123
+ "sitsFlat",
15124
+ "sitsFlatBelowBoard",
15125
+ "foldedToFaceAboveBoard",
15126
+ "foldedToFaceBelowBoard",
15127
+ "foldedToRightAngleAboveBoard",
15128
+ "foldedToRightAngleBelowBoard"
15129
+ ]);
15130
+ var positiveFiniteNumberSchema = z5.number().finite().positive();
15131
+ var aspectRatioStringSchema = z5.string().refine((value) => {
15132
+ const parts = value.split(":");
15133
+ if (parts.length !== 2) return false;
15134
+ const width10 = Number(parts[0]);
15135
+ const height10 = Number(parts[1]);
15136
+ return Number.isFinite(width10) && Number.isFinite(height10) && width10 > 0 && height10 > 0;
15137
+ }, 'Aspect ratio must look like "16:9"').transform((value) => value);
15138
+ var flexScreenAspectRatioSchema = z5.union([
15139
+ positiveFiniteNumberSchema,
15140
+ aspectRatioStringSchema,
15141
+ z5.tuple([positiveFiniteNumberSchema, positiveFiniteNumberSchema])
15142
+ ]);
15143
+ var modelPointSchema = z5.object({
15144
+ x: modelLengthSchema.optional(),
15145
+ y: modelLengthSchema.optional(),
15146
+ z: modelLengthSchema.optional()
15147
+ }).strict();
15148
+ var rotationValueSchema = z5.union([z5.number().finite(), z5.string().min(1)]);
15149
+ var modelRotationSchema = z5.tuple([
15150
+ rotationValueSchema,
15151
+ rotationValueSchema,
15152
+ rotationValueSchema
15153
+ ]);
15154
+ var orientationShortcutKeys = [
15155
+ "sitsFlat",
15156
+ "sitsFlatBelowBoard",
15157
+ "foldedToFaceAboveBoard",
15158
+ "foldedToFaceBelowBoard",
15159
+ "foldsAboveBoard",
15160
+ "foldsBelowBoard",
15161
+ "foldedToRightAngleAboveBoard",
15162
+ "foldedToRightAngleBelowBoard"
15163
+ ];
15164
+ var flexScreenModelPropsShape = {
15165
+ width: positiveModelLengthSchema.optional(),
15166
+ height: positiveModelLengthSchema.optional(),
15167
+ diagonal: positiveModelLengthSchema.optional(),
15168
+ aspectRatio: flexScreenAspectRatioSchema.optional(),
15169
+ ratio: flexScreenAspectRatioSchema.optional(),
15170
+ defaultDiagonal: positiveModelLengthSchema.optional(),
15171
+ orientation: flexScreenOrientationSchema.optional(),
15172
+ sitsFlat: z5.boolean().optional(),
15173
+ sitsFlatBelowBoard: z5.boolean().optional(),
15174
+ foldedToFaceAboveBoard: z5.boolean().optional(),
15175
+ foldedToFaceBelowBoard: z5.boolean().optional(),
15176
+ foldsAboveBoard: z5.boolean().optional(),
15177
+ foldsBelowBoard: z5.boolean().optional(),
15178
+ foldedToRightAngleAboveBoard: z5.boolean().optional(),
15179
+ foldedToRightAngleBelowBoard: z5.boolean().optional(),
15180
+ screenThickness: positiveModelLengthSchema.optional(),
15181
+ bezelInset: nonnegativeModelLengthSchema.optional(),
15182
+ bezelDepth: positiveModelLengthSchema.optional(),
15183
+ activeAreaWidth: positiveModelLengthSchema.optional(),
15184
+ activeAreaHeight: positiveModelLengthSchema.optional(),
15185
+ screenColor: z5.string().min(1).optional(),
15186
+ bezelColor: z5.string().min(1).optional(),
15187
+ showScreen: z5.boolean().optional(),
15188
+ flexCableLength: positiveModelLengthSchema.optional(),
15189
+ flexCableWidth: positiveModelLengthSchema.optional(),
15190
+ flexCableThickness: positiveModelLengthSchema.optional(),
15191
+ flexCableColor: z5.string().min(1).optional(),
15192
+ conductorCount: z5.number().int().positive().optional(),
15193
+ conductorPitch: positiveModelLengthSchema.optional(),
15194
+ conductorWidth: positiveModelLengthSchema.optional(),
15195
+ conductorThickness: positiveModelLengthSchema.optional(),
15196
+ conductorColor: z5.string().min(1).optional(),
15197
+ cableEdgeMargin: nonnegativeModelLengthSchema.optional(),
15198
+ exposedContactLength: nonnegativeModelLengthSchema.optional(),
15199
+ showConductors: z5.boolean().optional(),
15200
+ showFlexCable: z5.boolean().optional(),
15201
+ showStiffeners: z5.boolean().optional(),
15202
+ stiffenerLength: nonnegativeModelLengthSchema.optional(),
15203
+ stiffenerThickness: positiveModelLengthSchema.optional(),
15204
+ stiffenerColor: z5.string().min(1).optional(),
15205
+ bendRadius: positiveModelLengthSchema.optional(),
15206
+ bendSegments: z5.number().int().min(2).optional(),
15207
+ rightAngleVerticalLead: nonnegativeModelLengthSchema.optional(),
15208
+ distanceAboveBoard: nonnegativeModelLengthSchema.optional(),
15209
+ distanceBelowBoard: nonnegativeModelLengthSchema.optional(),
15210
+ foldDistanceFromConnector: nonnegativeModelLengthSchema.optional(),
15211
+ foldOutset: positiveModelLengthSchema.optional(),
15212
+ foldSegments: z5.number().int().min(4).optional(),
15213
+ screenGap: nonnegativeModelLengthSchema.optional(),
15214
+ boardTopZ: modelLengthSchema.optional(),
15215
+ boardThickness: positiveModelLengthSchema.optional(),
15216
+ boardClearance: nonnegativeModelLengthSchema.optional(),
15217
+ cableStartX: modelLengthSchema.optional(),
15218
+ cableStartY: modelLengthSchema.optional(),
15219
+ cableStartZ: modelLengthSchema.optional(),
15220
+ cableLateralOffset: modelLengthSchema.optional(),
15221
+ screenOffset: modelPointSchema.optional(),
15222
+ screenRotation: modelRotationSchema.optional(),
15223
+ rotation: modelRotationSchema.optional(),
15224
+ offset: modelPointSchema.optional()
15225
+ };
15226
+ var addOrientationShortcutIssue = (props, addIssue) => {
15227
+ const selectedShortcuts = orientationShortcutKeys.filter(
15228
+ (key) => props[key] === true
15229
+ );
15230
+ if (selectedShortcuts.length > 1) addIssue(selectedShortcuts[1]);
15231
+ };
15232
+ var flexScreenModelPropsSchema = z5.object(flexScreenModelPropsShape).strict().superRefine((props, context) => {
15233
+ addOrientationShortcutIssue(props, (path) => {
15234
+ context.addIssue({
15235
+ code: "custom",
15236
+ message: "Only one FlexScreen orientation shortcut can be true",
15237
+ path: [path]
15238
+ });
15239
+ });
15240
+ });
15241
+ var flexScreenModelDefinitionSchema = z5.object({
15242
+ fn: z5.literal("flexscreen"),
15243
+ ...flexScreenModelPropsShape
15244
+ }).strict().superRefine((model, context) => {
15245
+ addOrientationShortcutIssue(model, (path) => {
15246
+ context.addIssue({
15247
+ code: "custom",
15248
+ message: "Only one FlexScreen orientation shortcut can be true",
15249
+ path: [path]
15250
+ });
15251
+ });
15252
+ });
15253
+ var modelDefinitionSchema = z5.union([
15254
+ nemaMotorModelDefinitionSchema,
15255
+ sheetMetalModelDefinitionSchema,
15256
+ flexScreenModelDefinitionSchema,
15257
+ hexSocketBoltModelDefinitionSchema
15258
+ ]);
15259
+ function splitModelStringTokens(value) {
15260
+ const tokens = [];
15261
+ let depth = 0;
15262
+ let start = 0;
15263
+ for (let index2 = 0; index2 < value.length; index2++) {
15264
+ const character = value[index2];
15265
+ if (character === "(") depth++;
15266
+ if (character === ")") depth--;
15267
+ if (depth < 0 || depth > 1) throw new Error("Invalid feature parentheses");
15268
+ if (character === "_" && depth === 0) {
15269
+ tokens.push(value.slice(start, index2));
15270
+ start = index2 + 1;
15271
+ }
15272
+ }
15273
+ if (depth !== 0) throw new Error("Unclosed feature parentheses");
15274
+ tokens.push(value.slice(start));
15275
+ if (tokens.some((token) => !token))
15276
+ throw new Error("Model strings cannot contain empty tokens");
15277
+ return tokens;
15278
+ }
15279
+ var parsePart = (part) => {
15280
+ const match = part.match(/^([a-zA-Z]+)([\(\d\.\+\-].*)?$/);
15281
+ if (!match?.[1]) return void 0;
15282
+ return {
15283
+ fn: match[1].toLowerCase(),
15284
+ value: match[2]
15285
+ };
15286
+ };
15287
+ var parseModelStringParams = (definition) => {
15288
+ const normalizedDefinition = definition.trim();
15289
+ if (!normalizedDefinition) throw new Error("Model string cannot be empty");
15290
+ const parts = splitModelStringTokens(normalizedDefinition);
15291
+ const firstPart = parts[0];
15292
+ const first = parsePart(firstPart);
15293
+ const params = {};
15294
+ const fn = first?.fn ?? firstPart.toLowerCase();
15295
+ params[fn] = true;
15296
+ params.fn = fn;
15297
+ if (first?.value) {
15298
+ const numericValue = Number.parseFloat(first.value);
15299
+ if (Number.isFinite(numericValue)) params.num_pins = numericValue;
15300
+ }
15301
+ for (const part of parts.slice(1)) {
15302
+ if (!part) throw new Error("Model strings cannot contain empty tokens");
15303
+ const parsed = parsePart(part);
15304
+ if (!parsed) throw new Error(`Invalid model string token "${part}"`);
15305
+ params[parsed.fn] = parsed.value ?? true;
15306
+ }
15307
+ params.string = normalizedDefinition;
15308
+ return params;
15309
+ };
15310
+ var lengths = {
15311
+ l: "bodyLength",
15312
+ length: "bodyLength",
15313
+ bodylength: "bodyLength",
15314
+ bodywidth: "bodyWidth",
15315
+ shaftlength: "shaftLength",
15316
+ shaftdiameter: "shaftDiameter",
15317
+ flatdepth: "shaftFlatDepth",
15318
+ flatlength: "shaftFlatLength",
15319
+ holespacing: "mountingHoleSpacing",
15320
+ holediameter: "mountingHoleDiameter",
15321
+ holedepth: "mountingHoleDepth",
15322
+ pilotdiameter: "pilotDiameter",
15323
+ pilotlength: "pilotLength",
15324
+ frontcap: "frontCapLength",
15325
+ rearcap: "rearCapLength",
15326
+ facechamfer: "faceCornerChamfer",
15327
+ bodychamfer: "bodyCornerChamfer"
15328
+ };
15329
+ function parseNemaMotorModelParams(raw) {
15330
+ const tokens = raw.string.split("_");
15331
+ const match = tokens[0]?.match(/^nema(8|17|23)$/i);
15332
+ if (!match) throw new Error("Expected nema8, nema17 or nema23");
15333
+ const props = {
15334
+ fn: "nema",
15335
+ nemaSize: Number(match[1])
15336
+ };
15337
+ for (const token of tokens.slice(1)) {
15338
+ const match2 = token.match(/^([a-z]+)(.*)$/i);
15339
+ if (!match2) throw new Error(`Invalid NEMA token "${token}"`);
15340
+ const name = match2[1].toLowerCase(), value = match2[2];
15341
+ let property, parsed;
15342
+ if (name in lengths) {
15343
+ property = lengths[name];
15344
+ parsed = value;
15345
+ } else if (name === "flatangle") {
15346
+ property = "shaftFlatAngle";
15347
+ if (!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:deg)?$/i.test(value))
15348
+ throw new Error("flatangle requires a numeric angle in degrees");
15349
+ parsed = Number(value.replace(/deg$/i, ""));
15350
+ } else if (["round", "dshaft", "throughholes", "blindholes"].includes(name)) {
15351
+ if (value) throw new Error(`NEMA flag "${name}" does not accept a value`);
15352
+ property = name === "round" || name === "dshaft" ? "shaftShape" : "mountingHoleThrough";
15353
+ parsed = name === "round" ? "round" : name === "dshaft" ? "d" : name === "throughholes";
15354
+ } else throw new Error(`Unknown NEMA motor token "${token}"`);
15355
+ if (property in props)
15356
+ throw new Error(`NEMA property "${property}" is set more than once`);
15357
+ props[property] = parsed;
15358
+ }
15359
+ return nemaMotorModelDefinitionSchema.parse(props);
15360
+ }
15361
+ function parseSheetMetalFeature(feature, profile) {
15362
+ const match = feature.match(/^(hole|slot)[1-9]\d*\(([^()]+)\)$/);
15363
+ if (!match) throw new Error(`Invalid sheet metal feature "${feature}"`);
15364
+ const kind = match[1];
15365
+ const values = {};
15366
+ for (const token of match[2].split("_")) {
15367
+ const parameter = token.match(
15368
+ /^(leftofcenter|rightofcenter|abovecenter|belowcenter|r|d|l|w)([0-9.].*)$/
15369
+ );
15370
+ const key = parameter?.[1] ?? token;
15371
+ if (key in values) throw new Error(`Duplicate ${key} in ${feature}`);
15372
+ values[key] = parameter?.[2] ?? "";
15373
+ }
15374
+ const allowed = /* @__PURE__ */ new Set([
15375
+ "bottomface",
15376
+ "angledface",
15377
+ "leftface",
15378
+ "rightface",
15379
+ "leftofcenter",
15380
+ "rightofcenter",
15381
+ "abovecenter",
15382
+ "belowcenter",
15383
+ ...kind === "hole" ? ["r", "d"] : ["l", "w", "horizontal", "vertical"]
15384
+ ]);
15385
+ for (const key of Object.keys(values)) {
15386
+ if (!allowed.has(key)) throw new Error(`Unknown ${key} in ${feature}`);
15387
+ }
15388
+ const faces = ["bottomface", "angledface", "leftface", "rightface"].filter(
15389
+ (face22) => face22 in values
15390
+ );
15391
+ if (faces.length !== 1)
15392
+ throw new Error(`Specify exactly one face in ${feature}`);
15393
+ const face2 = faces[0];
15394
+ if (face2 === "angledface" && profile !== "angle" || ["leftface", "rightface"].includes(face2) && profile !== "channel")
15395
+ throw new Error(`No ${face2} on ${profile}`);
15396
+ for (const [a, b] of [
15397
+ ["leftofcenter", "rightofcenter"],
15398
+ ["abovecenter", "belowcenter"],
15399
+ ["horizontal", "vertical"],
15400
+ ["r", "d"]
15401
+ ]) {
15402
+ if (a in values && b in values)
15403
+ throw new Error(`Conflicting ${a} and ${b} in ${feature}`);
15404
+ }
15405
+ const distance6 = (key) => key in values ? positiveModelLengthSchema.parse(values[key]) : 0;
15406
+ const horizontal = distance6("rightofcenter") - distance6("leftofcenter");
15407
+ const vertical = distance6("abovecenter") - distance6("belowcenter");
15408
+ const panel = face2 === "bottomface" ? "base" : face2 === "leftface" ? "left" : "right";
15409
+ const position = {
15410
+ panel,
15411
+ u: panel === "base" ? horizontal : vertical,
15412
+ v: panel === "base" ? vertical : horizontal * (panel === "left" ? -1 : 1)
15413
+ };
15414
+ if (kind === "hole") {
15415
+ if (!("r" in values) && !("d" in values))
15416
+ throw new Error(`Hole requires r or d in ${feature}`);
15417
+ return sheetMetalHoleSchema.parse({
15418
+ ...position,
15419
+ shape: "round",
15420
+ diameter: "r" in values ? 2 * distance6("r") : distance6("d")
15421
+ });
15422
+ }
15423
+ if (!("l" in values) || !("w" in values))
15424
+ throw new Error(`Slot requires l and w in ${feature}`);
15425
+ const length83 = distance6("l"), width10 = distance6("w");
15426
+ if (length83 < width10) throw new Error("Slot length must be at least its width");
15427
+ return sheetMetalHoleSchema.parse({
15428
+ ...position,
15429
+ shape: "slot",
15430
+ length: length83,
15431
+ width: width10,
15432
+ axis: panel === "base" === !("vertical" in values) ? "u" : "v"
15433
+ });
15434
+ }
15435
+ var lengths2 = {
15436
+ w: "width",
15437
+ l: "baseLength",
15438
+ h: "flangeHeight",
15439
+ t: "thickness",
15440
+ r: "insideBendRadius"
15441
+ };
15442
+ function parseSheetMetalModelParams(raw) {
15443
+ const props = {};
15444
+ const tokens = splitModelStringTokens(raw.string);
15445
+ if (tokens[0] !== "sheetmetal") throw new Error("Expected sheetmetal");
15446
+ const features = [];
15447
+ const featureNames = /* @__PURE__ */ new Set();
15448
+ for (const token of tokens.slice(1)) {
15449
+ if (/^(hole|slot)[1-9]\d*\(/.test(token)) {
15450
+ const name = token.slice(0, token.indexOf("("));
15451
+ if (featureNames.has(name)) throw new Error(`Duplicate feature "${name}"`);
15452
+ featureNames.add(name);
15453
+ features.push(token);
15454
+ continue;
15455
+ }
15456
+ if (["plate", "angle", "channel"].includes(token)) {
15457
+ if (props.profile) throw new Error("Duplicate sheet metal profile");
15458
+ props.profile = token;
15459
+ continue;
15460
+ }
15461
+ const key = lengths2[token[0]];
15462
+ if (!key || token.length < 2)
15463
+ throw new Error(`Unknown sheet metal token "${token}"`);
15464
+ if (key in props) throw new Error(`Duplicate sheet metal property "${key}"`);
15465
+ props[key] = token.slice(1);
15466
+ }
15467
+ const definition = sheetMetalModelDefinitionSchema.parse({
15468
+ fn: "sheetmetal",
15469
+ ...props
15470
+ });
15471
+ definition.holes = features.map(
15472
+ (feature) => parseSheetMetalFeature(feature, definition.profile)
15473
+ );
15474
+ return definition;
15475
+ }
15476
+ var parseHexSocketBoltModelParams = (raw) => {
15477
+ if (raw.fn !== "hexsocketbolt") {
15478
+ throw new Error(`Expected hexsocketbolt params, got "${raw.fn}"`);
15479
+ }
15480
+ const tokens = raw.string.split("_");
15481
+ if (tokens[0]?.toLowerCase() !== "hexsocketbolt") {
15482
+ throw new Error(
15483
+ "The hexsocketbolt function does not accept an inline value"
15484
+ );
15485
+ }
15486
+ const seen = /* @__PURE__ */ new Set();
15487
+ for (const token of tokens.slice(1)) {
15488
+ const name = token.match(/^[a-z]+/i)?.[0]?.toLowerCase();
15489
+ if (name && seen.has(name))
15490
+ throw new Error(`Duplicate bolt token "${name}"`);
15491
+ if (name) seen.add(name);
15492
+ }
15493
+ const props = {};
15494
+ for (const [token, value] of Object.entries(raw)) {
15495
+ if (["fn", "string", "hexsocketbolt"].includes(token)) continue;
15496
+ let property;
15497
+ let parsed = value;
15498
+ if (token === "m") {
15499
+ property = "metricSize";
15500
+ parsed = `M${String(value)}`;
15501
+ } else if (token === "l" || token === "length") {
15502
+ property = "length";
15503
+ } else if (token === "threads" || token === "nothreads") {
15504
+ if (value !== true)
15505
+ throw new Error(`Bolt token "${token}" does not accept a value`);
15506
+ property = "showThreads";
15507
+ parsed = token === "threads";
15508
+ } else {
15509
+ throw new Error(
15510
+ `Unknown hex socket bolt model token "${token}${String(value)}"`
15511
+ );
15512
+ }
15513
+ if (property in props)
15514
+ throw new Error(`Bolt property "${property}" is set more than once`);
15515
+ props[property] = parsed;
15516
+ }
15517
+ return hexSocketBoltModelDefinitionSchema.parse({
15518
+ fn: "hexsocketbolt",
15519
+ ...props
15520
+ });
15521
+ };
15522
+ var orientationTokens = {
15523
+ sitsflat: "sitsFlat",
15524
+ sitsflatbelow: "sitsFlatBelowBoard",
15525
+ sitsflatbelowboard: "sitsFlatBelowBoard",
15526
+ foldsabove: "foldedToFaceAboveBoard",
15527
+ foldsaboveboard: "foldedToFaceAboveBoard",
15528
+ foldedtofaceaboveboard: "foldedToFaceAboveBoard",
15529
+ foldsbelow: "foldedToFaceBelowBoard",
15530
+ foldsbelowboard: "foldedToFaceBelowBoard",
15531
+ foldedtofacebelowboard: "foldedToFaceBelowBoard",
15532
+ rightangleabove: "foldedToRightAngleAboveBoard",
15533
+ rightangleaboveboard: "foldedToRightAngleAboveBoard",
15534
+ foldedtorightangleaboveboard: "foldedToRightAngleAboveBoard",
15535
+ rightanglebelow: "foldedToRightAngleBelowBoard",
15536
+ rightanglebelowboard: "foldedToRightAngleBelowBoard",
15537
+ foldedtorightanglebelowboard: "foldedToRightAngleBelowBoard"
15538
+ };
15539
+ var lengthProperties = {
15540
+ width: ["width", "w"],
15541
+ height: ["height", "h"],
15542
+ diagonal: ["diagonal", "diag", "d"],
15543
+ defaultDiagonal: ["defaultdiagonal", "defaultdiag"],
15544
+ screenThickness: ["screenthickness"],
15545
+ bezelInset: ["bezelinset"],
15546
+ bezelDepth: ["bezeldepth"],
15547
+ activeAreaWidth: ["activeareawidth", "activew"],
15548
+ activeAreaHeight: ["activeareaheight", "activeh"],
15549
+ flexCableLength: ["flexcablelength", "flexlength", "flex"],
15550
+ flexCableWidth: ["flexcablewidth", "flexwidth"],
15551
+ flexCableThickness: ["flexcablethickness", "flexthickness"],
15552
+ conductorPitch: ["conductorpitch"],
15553
+ conductorWidth: ["conductorwidth"],
15554
+ conductorThickness: ["conductorthickness"],
15555
+ cableEdgeMargin: ["cableedgemargin", "edgemargin"],
15556
+ exposedContactLength: ["exposedcontactlength", "contactlength"],
15557
+ stiffenerLength: ["stiffenerlength"],
15558
+ stiffenerThickness: ["stiffenerthickness"],
15559
+ bendRadius: ["bendradius"],
15560
+ rightAngleVerticalLead: ["rightangleverticallead", "verticallead"],
15561
+ distanceAboveBoard: ["distanceaboveboard", "distanceabove"],
15562
+ distanceBelowBoard: ["distancebelowboard", "distancebelow"],
15563
+ foldDistanceFromConnector: [
15564
+ "folddistancefromconnector",
15565
+ "folddistance",
15566
+ "foldstart"
15567
+ ],
15568
+ foldOutset: ["foldoutset", "outset"],
15569
+ screenGap: ["screengap"],
15570
+ boardTopZ: ["boardtopz"],
15571
+ boardThickness: ["boardthickness"],
15572
+ boardClearance: ["boardclearance"],
15573
+ cableStartX: ["cablestartx"],
15574
+ cableStartY: ["cablestarty"],
15575
+ cableStartZ: ["cablestartz"],
15576
+ cableLateralOffset: ["cablelateraloffset", "lateraloffset"]
15577
+ };
15578
+ var lengthTokenToProperty = Object.fromEntries(
15579
+ Object.entries(lengthProperties).flatMap(
15580
+ ([property, tokens]) => tokens.map((token) => [token, property])
15581
+ )
15582
+ );
15583
+ var integerTokenToProperty = {
15584
+ conductorcount: "conductorCount",
15585
+ conductors: "conductorCount",
15586
+ bendsegments: "bendSegments",
15587
+ foldsegments: "foldSegments"
15588
+ };
15589
+ var booleanTokens = {
15590
+ showscreen: ["showScreen", true],
15591
+ hidescreen: ["showScreen", false],
15592
+ showflex: ["showFlexCable", true],
15593
+ hideflex: ["showFlexCable", false],
15594
+ showconductors: ["showConductors", true],
15595
+ hideconductors: ["showConductors", false],
15596
+ showstiffeners: ["showStiffeners", true],
15597
+ hidestiffeners: ["showStiffeners", false]
15598
+ };
15599
+ var colorProperties = {
15600
+ screencolor: "screenColor",
15601
+ bezelcolor: "bezelColor",
15602
+ flexcolor: "flexCableColor",
15603
+ conductorcolor: "conductorColor",
15604
+ stiffenercolor: "stiffenerColor"
15605
+ };
15606
+ var parseAspectRatio = (value) => {
15607
+ const normalized = String(value).toLowerCase().replace("x", ":");
15608
+ if (normalized.includes(":")) {
15609
+ const [width10, height10, extra] = normalized.split(":");
15610
+ const numericWidth = Number(width10);
15611
+ const numericHeight = Number(height10);
15612
+ if (extra !== void 0 || !Number.isFinite(numericWidth) || !Number.isFinite(numericHeight) || numericWidth <= 0 || numericHeight <= 0) {
15613
+ throw new Error(`Invalid FlexScreen aspect ratio "${String(value)}"`);
15614
+ }
15615
+ return `${numericWidth}:${numericHeight}`;
15616
+ }
15617
+ const numeric = Number(normalized);
15618
+ if (!Number.isFinite(numeric) || numeric <= 0) {
15619
+ throw new Error(`Invalid FlexScreen aspect ratio "${String(value)}"`);
15620
+ }
15621
+ return numeric;
15622
+ };
15623
+ var unwrapFunctionValue = (value, token) => {
15624
+ if (typeof value !== "string" || !/^\(.+\)$/.test(value)) {
15625
+ throw new Error(`FlexScreen token "${token}" requires a value in (...)`);
15626
+ }
15627
+ return value.slice(1, -1);
15628
+ };
15629
+ var assertBareToken = (value, token) => {
15630
+ if (value !== true) {
15631
+ throw new Error(`FlexScreen token "${token}" does not accept a value`);
15632
+ }
15633
+ };
15634
+ var parseFlexScreenModelParams = (rawParams) => {
15635
+ if (rawParams.fn !== "flexscreen") {
15636
+ throw new Error(`Expected FlexScreen params, got "${rawParams.fn}"`);
15637
+ }
15638
+ const props = {};
15639
+ let orientation2;
15640
+ let relativeDistance;
15641
+ for (const [token, value] of Object.entries(rawParams)) {
15642
+ if (token === "fn" || token === "string" || token === "flexscreen") {
15643
+ continue;
15644
+ }
15645
+ const tokenOrientation = orientationTokens[token];
15646
+ if (tokenOrientation) {
15647
+ assertBareToken(value, token);
15648
+ if (orientation2 && orientation2 !== tokenOrientation) {
15649
+ throw new Error(
15650
+ "A FlexScreen model string can only set one orientation"
15651
+ );
15652
+ }
15653
+ orientation2 = tokenOrientation;
15654
+ props.orientation = tokenOrientation;
15655
+ continue;
15656
+ }
15657
+ if (token in booleanTokens) {
15658
+ assertBareToken(value, token);
15659
+ const [property, enabled] = booleanTokens[token];
15660
+ props[property] = enabled;
15661
+ continue;
15662
+ }
15663
+ const colorProperty = colorProperties[token];
15664
+ if (colorProperty) {
15665
+ props[colorProperty] = unwrapFunctionValue(value, token);
15666
+ continue;
15667
+ }
15668
+ if (token === "ratio") {
15669
+ props.aspectRatio = parseAspectRatio(value);
15670
+ continue;
15671
+ }
15672
+ const lengthProperty = lengthTokenToProperty[token];
15673
+ if (lengthProperty) {
15674
+ props[lengthProperty] = value;
15675
+ continue;
15676
+ }
15677
+ if (token === "distance") {
15678
+ relativeDistance = value;
15679
+ continue;
15680
+ }
15681
+ const integerProperty = integerTokenToProperty[token];
15682
+ if (integerProperty) {
15683
+ const parsed = Number(value);
15684
+ if (!Number.isInteger(parsed) || parsed < 1) {
15685
+ throw new Error(
15686
+ `Invalid positive integer in FlexScreen token "${token}${String(value)}"`
15687
+ );
15688
+ }
15689
+ props[integerProperty] = parsed;
15690
+ continue;
15691
+ }
15692
+ throw new Error(`Unknown FlexScreen model token "${token}${String(value)}"`);
15693
+ }
15694
+ if (relativeDistance !== void 0) {
15695
+ if (orientation2 === "foldedToFaceAboveBoard") {
15696
+ props.distanceAboveBoard = relativeDistance;
15697
+ } else if (orientation2 === "foldedToFaceBelowBoard") {
15698
+ props.distanceBelowBoard = relativeDistance;
15699
+ } else {
15700
+ throw new Error(
15701
+ 'The "distance" token requires foldsabove or foldsbelow; use distanceabove or distancebelow for an explicit side'
15702
+ );
15703
+ }
15704
+ }
15705
+ return flexScreenModelDefinitionSchema.parse({ fn: "flexscreen", ...props });
15706
+ };
15707
+ var modelFunctions = {
15708
+ nema: parseNemaMotorModelParams,
15709
+ sheetmetal: parseSheetMetalModelParams,
15710
+ flexscreen: parseFlexScreenModelParams,
15711
+ hexsocketbolt: parseHexSocketBoltModelParams
15712
+ };
15713
+ var modelParamsToJson = (params) => {
15714
+ const modelFunction = modelFunctions[params.fn];
15715
+ if (modelFunction) {
15716
+ return modelFunction(params);
15717
+ }
15718
+ throw new Error(`Unsupported modelprinter function "${params.fn}"`);
15719
+ };
15720
+ var string = (value) => {
15721
+ const params = parseModelStringParams(value);
15722
+ return {
15723
+ params: () => params,
15724
+ json: () => modelParamsToJson(params)
15725
+ };
15726
+ };
15727
+ var modelprinter = {
15728
+ string,
15729
+ getModelNames: () => Object.keys(modelFunctions)
15730
+ };
15731
+ var mp = modelprinter;
15732
+
15733
+ // node_modules/@tscircuit/footprinter/dist/index.js
15734
+ import {
15735
+ length as length82
15736
+ } from "circuit-json";
15737
+ import { length } from "circuit-json";
15738
+ import { z as z32 } from "zod";
15739
+ import { z as z22 } from "zod";
15740
+ import { z as z6 } from "zod";
15741
+ import { z as z42 } from "zod";
15742
+
15743
+ // node_modules/@tscircuit/footprinter/node_modules/@tscircuit/mm/dist/index.js
15744
+ var unitToMm2 = {
15745
+ in: 25.4,
15746
+ inch: 25.4,
15747
+ mil: 0.0254,
15748
+ mm: 1,
15749
+ m: 1e3,
15750
+ cm: 10,
15751
+ ft: 304.8,
15752
+ feet: 304.8
15753
+ };
15754
+ var mm2 = (n) => {
15755
+ let unit = typeof n === "number" ? "mm" : n.replace(/^[^a-zA-Z]+/g, "").toLowerCase();
15756
+ if (!unit)
15757
+ unit = "mm";
15758
+ const val = typeof n === "number" ? n : Number.parseFloat(n.split(unit)[0]);
15759
+ if (unit in unitToMm2) {
15760
+ return val * unitToMm2[unit];
15761
+ }
15762
+ throw new Error(`Unsupported unit: ${unit}`);
15763
+ };
15764
+ var mm_default = mm2;
14824
15765
 
14825
15766
  // node_modules/@tscircuit/footprinter/dist/index.js
14826
15767
  import {
14827
15768
  length as length2
14828
15769
  } from "circuit-json";
14829
- import { z as z5 } from "zod";
15770
+ import { z as z52 } from "zod";
14830
15771
  import { distance, length as length3 } from "circuit-json";
14831
- import { z as z6 } from "zod";
15772
+ import { z as z62 } from "zod";
14832
15773
  import {
14833
15774
  length as length4
14834
15775
  } from "circuit-json";
@@ -14871,7 +15812,7 @@ import {
14871
15812
  } from "circuit-json";
14872
15813
  import { z as z21 } from "zod";
14873
15814
  import { length as length19 } from "circuit-json";
14874
- import { z as z22 } from "zod";
15815
+ import { z as z222 } from "zod";
14875
15816
  import { length as length20 } from "circuit-json";
14876
15817
  import { z as z23 } from "zod";
14877
15818
  import { z as z24 } from "zod";
@@ -14892,7 +15833,7 @@ import {
14892
15833
  length as length26
14893
15834
  } from "circuit-json";
14894
15835
  import { z as z31 } from "zod";
14895
- import { z as z32 } from "zod";
15836
+ import { z as z322 } from "zod";
14896
15837
  import { length as length27 } from "circuit-json";
14897
15838
  import {
14898
15839
  length as length28
@@ -14947,7 +15888,7 @@ import { z as z50 } from "zod";
14947
15888
  import { length as length44 } from "circuit-json";
14948
15889
  import { z as z51 } from "zod";
14949
15890
  import { length as length45 } from "circuit-json";
14950
- import { z as z52 } from "zod";
15891
+ import { z as z522 } from "zod";
14951
15892
  import { length as length46 } from "circuit-json";
14952
15893
  import { z as z53 } from "zod";
14953
15894
  import { length as length47 } from "circuit-json";
@@ -14968,7 +15909,7 @@ import { z as z60 } from "zod";
14968
15909
  import { length as length53 } from "circuit-json";
14969
15910
  import { z as z61 } from "zod";
14970
15911
  import { length as length54 } from "circuit-json";
14971
- import { z as z62 } from "zod";
15912
+ import { z as z622 } from "zod";
14972
15913
  import { length as length55 } from "circuit-json";
14973
15914
  import { z as z63 } from "zod";
14974
15915
  import { length as length56 } from "circuit-json";
@@ -15172,7 +16113,7 @@ var silkscreenRef = (x, y, font_size) => {
15172
16113
  anchor_alignment: "center"
15173
16114
  };
15174
16115
  };
15175
- var function_call = z.string().or(z.array(z.any())).transform((a) => {
16116
+ var function_call = z6.string().or(z6.array(z6.any())).transform((a) => {
15176
16117
  if (Array.isArray(a)) return a;
15177
16118
  if (a.startsWith("(") && a.endsWith(")")) {
15178
16119
  a = a.slice(1, -1);
@@ -15181,32 +16122,32 @@ var function_call = z.string().or(z.array(z.any())).transform((a) => {
15181
16122
  const numVal = Number(v);
15182
16123
  return isNaN(numVal) ? v : numVal;
15183
16124
  });
15184
- }).pipe(z.array(z.string().or(z.number())));
15185
- var horizontalSide = z2.enum(["leftside", "rightside"]);
15186
- var verticalSide = z2.enum(["topside", "bottomside"]);
15187
- var horizontalAlignment = z2.enum(["left", "right"]);
15188
- var verticalAlignment = z2.enum(["top", "bottom"]);
16125
+ }).pipe(z6.array(z6.string().or(z6.number())));
16126
+ var horizontalSide = z22.enum(["leftside", "rightside"]);
16127
+ var verticalSide = z22.enum(["topside", "bottomside"]);
16128
+ var horizontalAlignment = z22.enum(["left", "right"]);
16129
+ var verticalAlignment = z22.enum(["top", "bottom"]);
15189
16130
  var pin1_location = function_call.pipe(
15190
- z2.union([
15191
- z2.tuple([horizontalSide, verticalAlignment]),
15192
- z2.tuple([verticalSide, horizontalAlignment])
16131
+ z22.union([
16132
+ z22.tuple([horizontalSide, verticalAlignment]),
16133
+ z22.tuple([verticalSide, horizontalAlignment])
15193
16134
  ])
15194
16135
  );
15195
- var base_def = z3.object({
15196
- norefdes: z3.boolean().optional().describe("disable reference designator label"),
15197
- invert: z3.boolean().optional().describe(
16136
+ var base_def = z32.object({
16137
+ norefdes: z32.boolean().optional().describe("disable reference designator label"),
16138
+ invert: z32.boolean().optional().describe(
15198
16139
  "install the part backwards: for a pin header, the LONG pins pass through the board instead of the short ones. It does not change which side of the board the part is on \u2014 that is the component's `layer`"
15199
16140
  ),
15200
- faceup: z3.boolean().optional().describe(
16141
+ faceup: z32.boolean().optional().describe(
15201
16142
  "DEPRECATED, and a no-op for through-hole parts. It meant 'the male pin header should face upwards, out of the top layer', which is what a correctly mounted header does by default; its other effect was to delete the pins below the board, leaving a through-hole part that cannot be soldered into its own plated holes. Use `layer` for which side of the board a part is on, and `invert` to install it backwards"
15202
16143
  ),
15203
- nosilkscreen: z3.boolean().optional().describe("omit all silkscreen elements from the footprint"),
16144
+ nosilkscreen: z32.boolean().optional().describe("omit all silkscreen elements from the footprint"),
15204
16145
  rounded: length.refine((radius) => radius >= 0, {
15205
16146
  message: "rounded radius must be non-negative"
15206
16147
  }).optional().describe("corner radius applied to all rectangular copper pads"),
15207
16148
  pin1location: pin1_location.optional().describe("rotate the footprint to place pin 1 on a requested side"),
15208
- cathodepin: z3.coerce.number().pipe(z3.union([z3.literal(1), z3.literal(2)])).optional().describe("identify which diode pad is the cathode"),
15209
- anodepin: z3.coerce.number().pipe(z3.union([z3.literal(1), z3.literal(2)])).optional().describe("identify which diode pad is the anode")
16149
+ cathodepin: z32.coerce.number().pipe(z32.union([z32.literal(1), z32.literal(2)])).optional().describe("identify which diode pad is the cathode"),
16150
+ anodepin: z32.coerce.number().pipe(z32.union([z32.literal(1), z32.literal(2)])).optional().describe("identify which diode pad is the anode")
15210
16151
  });
15211
16152
  var platedhole = (pn, x, y, id, od) => {
15212
16153
  return {
@@ -15215,8 +16156,8 @@ var platedhole = (pn, x, y, id, od) => {
15215
16156
  shape: "circle",
15216
16157
  x,
15217
16158
  y,
15218
- hole_diameter: mm(id),
15219
- outer_diameter: mm(od),
16159
+ hole_diameter: mm2(id),
16160
+ outer_diameter: mm2(od),
15220
16161
  pcb_port_id: "",
15221
16162
  layers: ["top", "bottom"],
15222
16163
  port_hints: [pn.toString()]
@@ -15240,11 +16181,11 @@ var platedHoleWithRectPad = (options) => {
15240
16181
  shape: "circular_hole_with_rect_pad",
15241
16182
  x,
15242
16183
  y,
15243
- hole_diameter: mm(holeDiameter),
16184
+ hole_diameter: mm2(holeDiameter),
15244
16185
  hole_shape: "circle",
15245
16186
  pad_shape: "rect",
15246
- rect_pad_width: mm(rectPadWidth),
15247
- rect_pad_height: mm(rectPadHeight),
16187
+ rect_pad_width: mm2(rectPadWidth),
16188
+ rect_pad_height: mm2(rectPadHeight),
15248
16189
  ...rectBorderRadius !== void 0 && {
15249
16190
  rect_border_radius: rectBorderRadius
15250
16191
  },
@@ -15364,17 +16305,17 @@ function convertMilToMm(value) {
15364
16305
  }
15365
16306
  return Number(value);
15366
16307
  }
15367
- var lengthInMm = z4.union([z4.string(), z4.number()]).transform((val) => convertMilToMm(val));
16308
+ var lengthInMm = z42.union([z42.string(), z42.number()]).transform((val) => convertMilToMm(val));
15368
16309
  var extendDipDef = (newDefaults) => base_def.extend({
15369
- fn: z4.string(),
15370
- num_pins: z4.number().optional().default(6),
15371
- wide: z4.boolean().optional(),
15372
- narrow: z4.boolean().optional(),
16310
+ fn: z42.string(),
16311
+ num_pins: z42.number().optional().default(6),
16312
+ wide: z42.boolean().optional(),
16313
+ narrow: z42.boolean().optional(),
15373
16314
  w: lengthInMm.optional(),
15374
16315
  p: lengthInMm.default(newDefaults.p ?? "2.54mm"),
15375
16316
  id: lengthInMm.optional(),
15376
16317
  od: lengthInMm.optional(),
15377
- nosquareplating: z4.boolean().optional().default(false).describe("do not use rectangular pad for pin 1")
16318
+ nosquareplating: z42.boolean().optional().default(false).describe("do not use rectangular pad for pin 1")
15378
16319
  }).transform((v) => {
15379
16320
  if (!v.id && !v.od) {
15380
16321
  if (Math.abs(v.p - 1.27) < 0.01) {
@@ -15554,8 +16495,8 @@ var silkscreenpath = (route, options = {}) => {
15554
16495
  };
15555
16496
  };
15556
16497
  var dpak_def = base_def.extend({
15557
- fn: z5.string(),
15558
- num_pins: z5.union([z5.literal(3), z5.literal(6)]).default(3),
16498
+ fn: z52.string(),
16499
+ num_pins: z52.union([z52.literal(3), z52.literal(6)]).default(3),
15559
16500
  p: length2.default("2.29mm").describe("pitch between adjacent lead positions"),
15560
16501
  pw: length2.default("1.6mm").describe("lead pad width along the pin column"),
15561
16502
  pl: length2.default("3mm").describe("lead pad length toward the package"),
@@ -15564,7 +16505,7 @@ var dpak_def = base_def.extend({
15564
16505
  span: length2.default("6.85mm").describe("center-to-center distance from the leads to the tab"),
15565
16506
  w: length2.default("6.6mm").describe("package body width"),
15566
16507
  h: length2.default("6.5mm").describe("package body height"),
15567
- string: z5.string().optional()
16508
+ string: z52.string().optional()
15568
16509
  });
15569
16510
  var d2pakDefaults = {
15570
16511
  p: "2.54mm",
@@ -15838,9 +16779,9 @@ var createCourtyardRect = (width10, height10) => ({
15838
16779
  layer: "top"
15839
16780
  });
15840
16781
  var passive_def = base_def.extend({
15841
- fn: z6.string().optional(),
15842
- string: z6.string().optional(),
15843
- tht: z6.boolean(),
16782
+ fn: z62.string().optional(),
16783
+ string: z62.string().optional(),
16784
+ tht: z62.boolean(),
15844
16785
  p: length3.optional(),
15845
16786
  pw: length3.optional(),
15846
16787
  ph: length3.optional(),
@@ -15850,9 +16791,9 @@ var passive_def = base_def.extend({
15850
16791
  h: length3.optional(),
15851
16792
  cyw: length3.optional().describe("courtyard width"),
15852
16793
  cyh: length3.optional().describe("courtyard height"),
15853
- nonpolarized: z6.boolean().optional(),
15854
- textbottom: z6.boolean().optional(),
15855
- roundedPads: z6.boolean().optional()
16794
+ nonpolarized: z62.boolean().optional(),
16795
+ textbottom: z62.boolean().optional(),
16796
+ roundedPads: z62.boolean().optional()
15856
16797
  });
15857
16798
  var passive = (params) => {
15858
16799
  let {
@@ -17818,16 +18759,16 @@ var mlp = (parameters) => {
17818
18759
  return quad(parameters);
17819
18760
  };
17820
18761
  var ssop_def = base_def.extend({
17821
- fn: z22.string(),
17822
- num_pins: z22.number().optional().default(8),
18762
+ fn: z222.string(),
18763
+ num_pins: z222.number().optional().default(8),
17823
18764
  w: length19.default(length19.parse("3.9mm")),
17824
18765
  p: length19.default(length19.parse("1.27mm")),
17825
18766
  pw: length19.optional(),
17826
18767
  pl: length19.optional(),
17827
- legsoutside: z22.boolean().optional().default(false),
18768
+ legsoutside: z222.boolean().optional().default(false),
17828
18769
  thermalpad: dim2d.optional(),
17829
18770
  ...thermalPadOffsetFields,
17830
- silkscreen_stroke_width: z22.number().optional().default(0.1)
18771
+ silkscreen_stroke_width: z222.number().optional().default(0.1)
17831
18772
  }).transform((v) => {
17832
18773
  if (v.pw == null && v.pl == null) {
17833
18774
  v.pw = length19.parse("0.51mm");
@@ -19377,13 +20318,13 @@ var sot723WithoutParsing = (parameters) => {
19377
20318
  return pads;
19378
20319
  };
19379
20320
  var sod_def = base_def.extend({
19380
- fn: z32.string(),
19381
- num_pins: z32.literal(2).default(2),
19382
- w: z32.string().default("2.36mm"),
19383
- h: z32.string().default("1.22mm"),
19384
- pl: z32.string().default("0.9mm"),
19385
- pw: z32.string().default("1.2mm"),
19386
- p: z32.string().default("3.30mm")
20321
+ fn: z322.string(),
20322
+ num_pins: z322.literal(2).default(2),
20323
+ w: z322.string().default("2.36mm"),
20324
+ h: z322.string().default("1.22mm"),
20325
+ pl: z322.string().default("0.9mm"),
20326
+ pw: z322.string().default("1.2mm"),
20327
+ p: z322.string().default("3.30mm")
19387
20328
  });
19388
20329
  var sod123 = (raw_params) => {
19389
20330
  const parameters = sod_def.parse(raw_params);
@@ -21067,8 +22008,8 @@ var pad_def = base_def.extend({
21067
22008
  });
21068
22009
  var pad = (params) => {
21069
22010
  const { w, h: h2 } = params;
21070
- const width10 = mm(w);
21071
- const height10 = mm(h2);
22011
+ const width10 = mm2(w);
22012
+ const height10 = mm2(h2);
21072
22013
  return {
21073
22014
  circuitJson: [
21074
22015
  rectpad(1, 0, 0, width10, height10),
@@ -21084,10 +22025,10 @@ var platedHolePill = (pn, x, y, holeDiameter, outerWidth, outerHeight) => {
21084
22025
  shape: "pill",
21085
22026
  x,
21086
22027
  y,
21087
- outer_width: mm(outerWidth),
21088
- outer_height: mm(outerHeight),
21089
- hole_width: mm(holeDiameter),
21090
- hole_height: mm(holeDiameter),
22028
+ outer_width: mm2(outerWidth),
22029
+ outer_height: mm2(outerHeight),
22030
+ hole_width: mm2(holeDiameter),
22031
+ hole_height: mm2(holeDiameter),
21091
22032
  pcb_port_id: "",
21092
22033
  layers: ["top", "bottom"],
21093
22034
  port_hints: [pn.toString()],
@@ -22011,13 +22952,13 @@ var sodWithoutParsing8 = (parameters) => {
22011
22952
  return pads;
22012
22953
  };
22013
22954
  var sod123FL_def = base_def.extend({
22014
- fn: z52.string(),
22015
- num_pins: z52.literal(2).default(2),
22016
- w: z52.string().default("4.4mm"),
22017
- h: z52.string().default("2.1mm"),
22018
- pl: z52.string().default("0.91mm"),
22019
- pw: z52.string().default("1.22mm"),
22020
- p: z52.string().default("3.146mm")
22955
+ fn: z522.string(),
22956
+ num_pins: z522.literal(2).default(2),
22957
+ w: z522.string().default("4.4mm"),
22958
+ h: z522.string().default("2.1mm"),
22959
+ pl: z522.string().default("0.91mm"),
22960
+ pw: z522.string().default("1.22mm"),
22961
+ p: z522.string().default("3.146mm")
22021
22962
  });
22022
22963
  var sod123fl = (raw_params) => {
22023
22964
  const parameters = sod123FL_def.parse(raw_params);
@@ -22599,9 +23540,9 @@ var to220f = (raw_params) => {
22599
23540
  i + 1,
22600
23541
  x,
22601
23542
  holeY,
22602
- mm(parameters.id),
22603
- mm(parameters.od),
22604
- mm(parameters.ph)
23543
+ mm2(parameters.id),
23544
+ mm2(parameters.od),
23545
+ mm2(parameters.ph)
22605
23546
  );
22606
23547
  }
22607
23548
  );
@@ -22970,13 +23911,13 @@ var microMelfWithoutParsing = (parameters) => {
22970
23911
  return pads;
22971
23912
  };
22972
23913
  var sma_def = base_def.extend({
22973
- fn: z62.string(),
22974
- num_pins: z62.literal(2).default(2),
22975
- w: z62.string().default("7.10mm"),
22976
- h: z62.string().default("3.40mm"),
22977
- pl: z62.string().default("2.50mm"),
22978
- pw: z62.string().default("1.80mm"),
22979
- p: z62.string().default("4.00mm")
23914
+ fn: z622.string(),
23915
+ num_pins: z622.literal(2).default(2),
23916
+ w: z622.string().default("7.10mm"),
23917
+ h: z622.string().default("3.40mm"),
23918
+ pl: z622.string().default("2.50mm"),
23919
+ pw: z622.string().default("1.80mm"),
23920
+ p: z622.string().default("4.00mm")
22980
23921
  });
22981
23922
  var sma = (raw_params) => {
22982
23923
  const parameters = sma_def.parse(raw_params);
@@ -26335,40 +27276,40 @@ var smtpad_def = base_def.extend({
26335
27276
  size: length73.optional(),
26336
27277
  string: z85.string().optional()
26337
27278
  }).transform((v) => {
26338
- let shape = "rect";
26339
- if (v.circle) shape = "circle";
26340
- if (v.square) shape = "square";
26341
- if (v.rect) shape = "rect";
26342
- if (v.pill) shape = "pill";
27279
+ let shape2 = "rect";
27280
+ if (v.circle) shape2 = "circle";
27281
+ if (v.square) shape2 = "square";
27282
+ if (v.rect) shape2 = "rect";
27283
+ if (v.pill) shape2 = "pill";
26343
27284
  let radius;
26344
27285
  let width10;
26345
27286
  let height10;
26346
- if (shape === "circle") {
26347
- if (v.r !== void 0) radius = mm(v.r);
26348
- else if (v.pr !== void 0) radius = mm(v.pr);
26349
- else if (v.radius !== void 0) radius = mm(v.radius);
26350
- else if (v.d !== void 0) radius = mm(v.d) / 2;
26351
- else if (v.pd !== void 0) radius = mm(v.pd) / 2;
26352
- else if (v.diameter !== void 0) radius = mm(v.diameter) / 2;
26353
- else radius = mm("1mm") / 2;
27287
+ if (shape2 === "circle") {
27288
+ if (v.r !== void 0) radius = mm2(v.r);
27289
+ else if (v.pr !== void 0) radius = mm2(v.pr);
27290
+ else if (v.radius !== void 0) radius = mm2(v.radius);
27291
+ else if (v.d !== void 0) radius = mm2(v.d) / 2;
27292
+ else if (v.pd !== void 0) radius = mm2(v.pd) / 2;
27293
+ else if (v.diameter !== void 0) radius = mm2(v.diameter) / 2;
27294
+ else radius = mm2("1mm") / 2;
26354
27295
  } else {
26355
- if (v.w !== void 0) width10 = mm(v.w);
26356
- else if (v.pw !== void 0) width10 = mm(v.pw);
26357
- else if (v.width !== void 0) width10 = mm(v.width);
26358
- else if (v.s !== void 0) width10 = mm(v.s);
26359
- else if (v.size !== void 0) width10 = mm(v.size);
26360
- else width10 = mm("1mm");
26361
- if (v.h !== void 0) height10 = mm(v.h);
26362
- else if (v.ph !== void 0) height10 = mm(v.ph);
26363
- else if (v.height !== void 0) height10 = mm(v.height);
26364
- else if (shape === "square") height10 = width10;
26365
- else if (shape === "rect")
27296
+ if (v.w !== void 0) width10 = mm2(v.w);
27297
+ else if (v.pw !== void 0) width10 = mm2(v.pw);
27298
+ else if (v.width !== void 0) width10 = mm2(v.width);
27299
+ else if (v.s !== void 0) width10 = mm2(v.s);
27300
+ else if (v.size !== void 0) width10 = mm2(v.size);
27301
+ else width10 = mm2("1mm");
27302
+ if (v.h !== void 0) height10 = mm2(v.h);
27303
+ else if (v.ph !== void 0) height10 = mm2(v.ph);
27304
+ else if (v.height !== void 0) height10 = mm2(v.height);
27305
+ else if (shape2 === "square") height10 = width10;
27306
+ else if (shape2 === "rect")
26366
27307
  height10 = width10;
26367
- else height10 = mm("1mm");
27308
+ else height10 = mm2("1mm");
26368
27309
  }
26369
27310
  return {
26370
27311
  fn: v.fn,
26371
- shape,
27312
+ shape: shape2,
26372
27313
  radius,
26373
27314
  width: width10,
26374
27315
  height: height10
@@ -26376,13 +27317,13 @@ var smtpad_def = base_def.extend({
26376
27317
  });
26377
27318
  var smtpad = (raw_params) => {
26378
27319
  const params = smtpad_def.parse(raw_params);
26379
- const { shape, radius, width: width10, height: height10 } = params;
27320
+ const { shape: shape2, radius, width: width10, height: height10 } = params;
26380
27321
  let pad2;
26381
27322
  let silkscreenOffset;
26382
- if (shape === "circle") {
27323
+ if (shape2 === "circle") {
26383
27324
  pad2 = circlepad(1, { x: 0, y: 0, radius });
26384
27325
  silkscreenOffset = radius + 0.5;
26385
- } else if (shape === "pill") {
27326
+ } else if (shape2 === "pill") {
26386
27327
  pad2 = pillpad(1, 0, 0, width10, height10);
26387
27328
  silkscreenOffset = Math.max(width10, height10) / 2 + 0.5;
26388
27329
  } else {
@@ -26763,14 +27704,14 @@ var platedhole_def = base_def.extend({
26763
27704
  squarepad: z90.boolean().optional().default(false)
26764
27705
  }).transform((v) => {
26765
27706
  let holeD;
26766
- if (v.d !== void 0) holeD = mm(v.d);
26767
- else if (v.hd !== void 0) holeD = mm(v.hd);
26768
- else if (v.r !== void 0) holeD = mm(v.r) * 2;
26769
- else if (v.hr !== void 0) holeD = mm(v.hr) * 2;
26770
- else holeD = mm("1mm");
27707
+ if (v.d !== void 0) holeD = mm2(v.d);
27708
+ else if (v.hd !== void 0) holeD = mm2(v.hd);
27709
+ else if (v.r !== void 0) holeD = mm2(v.r) * 2;
27710
+ else if (v.hr !== void 0) holeD = mm2(v.hr) * 2;
27711
+ else holeD = mm2("1mm");
26771
27712
  let padD;
26772
- if (v.pd !== void 0) padD = mm(v.pd);
26773
- else if (v.pr !== void 0) padD = mm(v.pr) * 2;
27713
+ if (v.pd !== void 0) padD = mm2(v.pd);
27714
+ else if (v.pr !== void 0) padD = mm2(v.pr) * 2;
26774
27715
  else padD = holeD * (1.5 / 1);
26775
27716
  return {
26776
27717
  fn: v.fn,
@@ -28269,7 +29210,7 @@ var applyPin1Location = (elements, pin1Location) => {
28269
29210
  var clampRadius = (radius, width10, height10) => Math.min(radius, width10 / 2, height10 / 2);
28270
29211
  var applyRounded = (elements, rounded) => {
28271
29212
  if (rounded === void 0) return elements;
28272
- const radius = mm(rounded);
29213
+ const radius = mm2(rounded);
28273
29214
  if (!Number.isFinite(radius) || radius < 0) {
28274
29215
  throw new Error(
28275
29216
  `rounded radius must be a non-negative length, got "${rounded}"`
@@ -28437,425 +29378,551 @@ footprinter.string = string2;
28437
29378
  footprinter.getFootprintNames = getFootprintNames;
28438
29379
  var fp = footprinter;
28439
29380
 
28440
- // node_modules/@tscircuit/modelprinter/node_modules/@tscircuit/mm/dist/index.js
28441
- var unitToMm2 = {
28442
- in: 25.4,
28443
- inch: 25.4,
28444
- mil: 0.0254,
28445
- mm: 1,
28446
- m: 1e3,
28447
- cm: 10,
28448
- ft: 304.8,
28449
- feet: 304.8
28450
- };
28451
- var mmNumberFormatter = new Intl.NumberFormat("en-US", {
28452
- useGrouping: false,
28453
- notation: "standard",
28454
- maximumFractionDigits: 12
28455
- });
28456
- var mm2 = (n) => {
28457
- let unit = typeof n === "number" ? "mm" : n.replace(/^[^a-zA-Z]+/g, "").toLowerCase();
28458
- if (!unit)
28459
- unit = "mm";
28460
- const val = typeof n === "number" ? n : Number.parseFloat(n.split(unit)[0]);
28461
- if (unit in unitToMm2) {
28462
- return val * unitToMm2[unit];
28463
- }
28464
- throw new Error(`Unsupported unit: ${unit}`);
28465
- };
29381
+ // node_modules/jscad-electronics/dist/vanilla.js
29382
+ var import_modeling = __toESM(require_src(), 1);
28466
29383
 
28467
- // node_modules/@tscircuit/modelprinter/dist/index.js
28468
- import { z as z27 } from "zod";
28469
- var modelLengthSchema = z27.union([z27.number(), z27.string()]).transform((value, context) => {
28470
- try {
28471
- const parsed = mm2(value);
28472
- if (!Number.isFinite(parsed)) throw new Error("Length is not finite");
28473
- return parsed;
28474
- } catch {
28475
- context.addIssue({
28476
- code: "custom",
28477
- message: `Invalid model length: ${String(value)}`
28478
- });
28479
- return z27.NEVER;
29384
+ // node_modules/earcut/src/earcut.js
29385
+ var steiners = /* @__PURE__ */ new Set();
29386
+ var filteredOut = false;
29387
+ function earcut(data, holeIndices, dim = 2) {
29388
+ const hasHoles = holeIndices && holeIndices.length;
29389
+ const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
29390
+ if (steiners.size) steiners.clear();
29391
+ let outerNode = linkedList(data, 0, outerLen, dim, true);
29392
+ const triangles = [];
29393
+ if (!outerNode || outerNode.next === outerNode.prev) return triangles;
29394
+ let minX = 0, minY = 0, invSize = 0;
29395
+ if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
29396
+ if (data.length > 80 * dim) {
29397
+ minX = data[0];
29398
+ minY = data[1];
29399
+ let maxX = minX;
29400
+ let maxY = minY;
29401
+ for (let i = dim; i < outerLen; i += dim) {
29402
+ const x = data[i];
29403
+ const y = data[i + 1];
29404
+ if (x < minX) minX = x;
29405
+ if (y < minY) minY = y;
29406
+ if (x > maxX) maxX = x;
29407
+ if (y > maxY) maxY = y;
29408
+ }
29409
+ invSize = Math.max(maxX - minX, maxY - minY);
29410
+ invSize = invSize !== 0 ? 32767 / invSize : 0;
28480
29411
  }
28481
- });
28482
- var positiveModelLengthSchema = modelLengthSchema.refine(
28483
- (value) => value > 0,
28484
- "Length must be greater than zero"
28485
- );
28486
- var nonnegativeModelLengthSchema = modelLengthSchema.refine(
28487
- (value) => value >= 0,
28488
- "Length cannot be negative"
28489
- );
28490
- var flexScreenOrientationSchema = z27.enum([
28491
- "sitsFlat",
28492
- "sitsFlatBelowBoard",
28493
- "foldedToFaceAboveBoard",
28494
- "foldedToFaceBelowBoard",
28495
- "foldedToRightAngleAboveBoard",
28496
- "foldedToRightAngleBelowBoard"
28497
- ]);
28498
- var positiveFiniteNumberSchema = z27.number().finite().positive();
28499
- var aspectRatioStringSchema = z27.string().refine((value) => {
28500
- const parts = value.split(":");
28501
- if (parts.length !== 2) return false;
28502
- const width10 = Number(parts[0]);
28503
- const height10 = Number(parts[1]);
28504
- return Number.isFinite(width10) && Number.isFinite(height10) && width10 > 0 && height10 > 0;
28505
- }, 'Aspect ratio must look like "16:9"').transform((value) => value);
28506
- var flexScreenAspectRatioSchema = z27.union([
28507
- positiveFiniteNumberSchema,
28508
- aspectRatioStringSchema,
28509
- z27.tuple([positiveFiniteNumberSchema, positiveFiniteNumberSchema])
28510
- ]);
28511
- var modelPointSchema = z27.object({
28512
- x: modelLengthSchema.optional(),
28513
- y: modelLengthSchema.optional(),
28514
- z: modelLengthSchema.optional()
28515
- }).strict();
28516
- var rotationValueSchema = z27.union([z27.number().finite(), z27.string().min(1)]);
28517
- var modelRotationSchema = z27.tuple([
28518
- rotationValueSchema,
28519
- rotationValueSchema,
28520
- rotationValueSchema
28521
- ]);
28522
- var orientationShortcutKeys = [
28523
- "sitsFlat",
28524
- "sitsFlatBelowBoard",
28525
- "foldedToFaceAboveBoard",
28526
- "foldedToFaceBelowBoard",
28527
- "foldsAboveBoard",
28528
- "foldsBelowBoard",
28529
- "foldedToRightAngleAboveBoard",
28530
- "foldedToRightAngleBelowBoard"
28531
- ];
28532
- var flexScreenModelPropsShape = {
28533
- width: positiveModelLengthSchema.optional(),
28534
- height: positiveModelLengthSchema.optional(),
28535
- diagonal: positiveModelLengthSchema.optional(),
28536
- aspectRatio: flexScreenAspectRatioSchema.optional(),
28537
- ratio: flexScreenAspectRatioSchema.optional(),
28538
- defaultDiagonal: positiveModelLengthSchema.optional(),
28539
- orientation: flexScreenOrientationSchema.optional(),
28540
- sitsFlat: z27.boolean().optional(),
28541
- sitsFlatBelowBoard: z27.boolean().optional(),
28542
- foldedToFaceAboveBoard: z27.boolean().optional(),
28543
- foldedToFaceBelowBoard: z27.boolean().optional(),
28544
- foldsAboveBoard: z27.boolean().optional(),
28545
- foldsBelowBoard: z27.boolean().optional(),
28546
- foldedToRightAngleAboveBoard: z27.boolean().optional(),
28547
- foldedToRightAngleBelowBoard: z27.boolean().optional(),
28548
- screenThickness: positiveModelLengthSchema.optional(),
28549
- bezelInset: nonnegativeModelLengthSchema.optional(),
28550
- bezelDepth: positiveModelLengthSchema.optional(),
28551
- activeAreaWidth: positiveModelLengthSchema.optional(),
28552
- activeAreaHeight: positiveModelLengthSchema.optional(),
28553
- screenColor: z27.string().min(1).optional(),
28554
- bezelColor: z27.string().min(1).optional(),
28555
- showScreen: z27.boolean().optional(),
28556
- flexCableLength: positiveModelLengthSchema.optional(),
28557
- flexCableWidth: positiveModelLengthSchema.optional(),
28558
- flexCableThickness: positiveModelLengthSchema.optional(),
28559
- flexCableColor: z27.string().min(1).optional(),
28560
- conductorCount: z27.number().int().positive().optional(),
28561
- conductorPitch: positiveModelLengthSchema.optional(),
28562
- conductorWidth: positiveModelLengthSchema.optional(),
28563
- conductorThickness: positiveModelLengthSchema.optional(),
28564
- conductorColor: z27.string().min(1).optional(),
28565
- cableEdgeMargin: nonnegativeModelLengthSchema.optional(),
28566
- exposedContactLength: nonnegativeModelLengthSchema.optional(),
28567
- showConductors: z27.boolean().optional(),
28568
- showFlexCable: z27.boolean().optional(),
28569
- showStiffeners: z27.boolean().optional(),
28570
- stiffenerLength: nonnegativeModelLengthSchema.optional(),
28571
- stiffenerThickness: positiveModelLengthSchema.optional(),
28572
- stiffenerColor: z27.string().min(1).optional(),
28573
- bendRadius: positiveModelLengthSchema.optional(),
28574
- bendSegments: z27.number().int().min(2).optional(),
28575
- rightAngleVerticalLead: nonnegativeModelLengthSchema.optional(),
28576
- distanceAboveBoard: nonnegativeModelLengthSchema.optional(),
28577
- distanceBelowBoard: nonnegativeModelLengthSchema.optional(),
28578
- foldDistanceFromConnector: nonnegativeModelLengthSchema.optional(),
28579
- foldOutset: positiveModelLengthSchema.optional(),
28580
- foldSegments: z27.number().int().min(4).optional(),
28581
- screenGap: nonnegativeModelLengthSchema.optional(),
28582
- boardTopZ: modelLengthSchema.optional(),
28583
- boardThickness: positiveModelLengthSchema.optional(),
28584
- boardClearance: nonnegativeModelLengthSchema.optional(),
28585
- cableStartX: modelLengthSchema.optional(),
28586
- cableStartY: modelLengthSchema.optional(),
28587
- cableStartZ: modelLengthSchema.optional(),
28588
- cableLateralOffset: modelLengthSchema.optional(),
28589
- screenOffset: modelPointSchema.optional(),
28590
- screenRotation: modelRotationSchema.optional(),
28591
- rotation: modelRotationSchema.optional(),
28592
- offset: modelPointSchema.optional()
28593
- };
28594
- var addOrientationShortcutIssue = (props, addIssue) => {
28595
- const selectedShortcuts = orientationShortcutKeys.filter(
28596
- (key) => props[key] === true
28597
- );
28598
- if (selectedShortcuts.length > 1) addIssue(selectedShortcuts[1]);
28599
- };
28600
- var flexScreenModelPropsSchema = z27.object(flexScreenModelPropsShape).strict().superRefine((props, context) => {
28601
- addOrientationShortcutIssue(props, (path) => {
28602
- context.addIssue({
28603
- code: "custom",
28604
- message: "Only one FlexScreen orientation shortcut can be true",
28605
- path: [path]
28606
- });
28607
- });
28608
- });
28609
- var flexScreenModelDefinitionSchema = z27.object({
28610
- fn: z27.literal("flexscreen"),
28611
- ...flexScreenModelPropsShape
28612
- }).strict().superRefine((model, context) => {
28613
- addOrientationShortcutIssue(model, (path) => {
28614
- context.addIssue({
28615
- code: "custom",
28616
- message: "Only one FlexScreen orientation shortcut can be true",
28617
- path: [path]
28618
- });
28619
- });
28620
- });
28621
- var parsePart = (part) => {
28622
- const match = part.match(/^([a-zA-Z]+)([\(\d\.\+\-].*)?$/);
28623
- if (!match?.[1]) return void 0;
28624
- return {
28625
- fn: match[1].toLowerCase(),
28626
- value: match[2]
28627
- };
28628
- };
28629
- var parseModelStringParams = (definition) => {
28630
- const normalizedDefinition = definition.trim();
28631
- if (!normalizedDefinition) throw new Error("Model string cannot be empty");
28632
- const parts = normalizedDefinition.split("_");
28633
- const firstPart = parts[0];
28634
- const first = parsePart(firstPart);
28635
- const params = {};
28636
- const fn = first?.fn ?? firstPart.toLowerCase();
28637
- params[fn] = true;
28638
- params.fn = fn;
28639
- if (first?.value) {
28640
- const numericValue = Number.parseFloat(first.value);
28641
- if (Number.isFinite(numericValue)) params.num_pins = numericValue;
29412
+ earcutLinked(outerNode, triangles, minX, minY, invSize);
29413
+ return triangles;
29414
+ }
29415
+ function linkedList(data, start, end, dim, clockwise) {
29416
+ let last = null;
29417
+ if (clockwise === signedArea(data, start, end, dim) > 0) {
29418
+ for (let i = start; i < end; i += dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);
29419
+ } else {
29420
+ for (let i = end - dim; i >= start; i -= dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);
28642
29421
  }
28643
- for (const part of parts.slice(1)) {
28644
- if (!part) throw new Error("Model strings cannot contain empty tokens");
28645
- const parsed = parsePart(part);
28646
- if (!parsed) throw new Error(`Invalid model string token "${part}"`);
28647
- params[parsed.fn] = parsed.value ?? true;
29422
+ if (last && equals(last, last.next)) {
29423
+ removeNode(last);
29424
+ last = last.next;
28648
29425
  }
28649
- params.string = normalizedDefinition;
28650
- return params;
28651
- };
28652
- var orientationTokens = {
28653
- sitsflat: "sitsFlat",
28654
- sitsflatbelow: "sitsFlatBelowBoard",
28655
- sitsflatbelowboard: "sitsFlatBelowBoard",
28656
- foldsabove: "foldedToFaceAboveBoard",
28657
- foldsaboveboard: "foldedToFaceAboveBoard",
28658
- foldedtofaceaboveboard: "foldedToFaceAboveBoard",
28659
- foldsbelow: "foldedToFaceBelowBoard",
28660
- foldsbelowboard: "foldedToFaceBelowBoard",
28661
- foldedtofacebelowboard: "foldedToFaceBelowBoard",
28662
- rightangleabove: "foldedToRightAngleAboveBoard",
28663
- rightangleaboveboard: "foldedToRightAngleAboveBoard",
28664
- foldedtorightangleaboveboard: "foldedToRightAngleAboveBoard",
28665
- rightanglebelow: "foldedToRightAngleBelowBoard",
28666
- rightanglebelowboard: "foldedToRightAngleBelowBoard",
28667
- foldedtorightanglebelowboard: "foldedToRightAngleBelowBoard"
28668
- };
28669
- var lengthProperties = {
28670
- width: ["width", "w"],
28671
- height: ["height", "h"],
28672
- diagonal: ["diagonal", "diag", "d"],
28673
- defaultDiagonal: ["defaultdiagonal", "defaultdiag"],
28674
- screenThickness: ["screenthickness"],
28675
- bezelInset: ["bezelinset"],
28676
- bezelDepth: ["bezeldepth"],
28677
- activeAreaWidth: ["activeareawidth", "activew"],
28678
- activeAreaHeight: ["activeareaheight", "activeh"],
28679
- flexCableLength: ["flexcablelength", "flexlength", "flex"],
28680
- flexCableWidth: ["flexcablewidth", "flexwidth"],
28681
- flexCableThickness: ["flexcablethickness", "flexthickness"],
28682
- conductorPitch: ["conductorpitch"],
28683
- conductorWidth: ["conductorwidth"],
28684
- conductorThickness: ["conductorthickness"],
28685
- cableEdgeMargin: ["cableedgemargin", "edgemargin"],
28686
- exposedContactLength: ["exposedcontactlength", "contactlength"],
28687
- stiffenerLength: ["stiffenerlength"],
28688
- stiffenerThickness: ["stiffenerthickness"],
28689
- bendRadius: ["bendradius"],
28690
- rightAngleVerticalLead: ["rightangleverticallead", "verticallead"],
28691
- distanceAboveBoard: ["distanceaboveboard", "distanceabove"],
28692
- distanceBelowBoard: ["distancebelowboard", "distancebelow"],
28693
- foldDistanceFromConnector: [
28694
- "folddistancefromconnector",
28695
- "folddistance",
28696
- "foldstart"
28697
- ],
28698
- foldOutset: ["foldoutset", "outset"],
28699
- screenGap: ["screengap"],
28700
- boardTopZ: ["boardtopz"],
28701
- boardThickness: ["boardthickness"],
28702
- boardClearance: ["boardclearance"],
28703
- cableStartX: ["cablestartx"],
28704
- cableStartY: ["cablestarty"],
28705
- cableStartZ: ["cablestartz"],
28706
- cableLateralOffset: ["cablelateraloffset", "lateraloffset"]
28707
- };
28708
- var lengthTokenToProperty = Object.fromEntries(
28709
- Object.entries(lengthProperties).flatMap(
28710
- ([property, tokens]) => tokens.map((token) => [token, property])
28711
- )
28712
- );
28713
- var integerTokenToProperty = {
28714
- conductorcount: "conductorCount",
28715
- conductors: "conductorCount",
28716
- bendsegments: "bendSegments",
28717
- foldsegments: "foldSegments"
28718
- };
28719
- var booleanTokens = {
28720
- showscreen: ["showScreen", true],
28721
- hidescreen: ["showScreen", false],
28722
- showflex: ["showFlexCable", true],
28723
- hideflex: ["showFlexCable", false],
28724
- showconductors: ["showConductors", true],
28725
- hideconductors: ["showConductors", false],
28726
- showstiffeners: ["showStiffeners", true],
28727
- hidestiffeners: ["showStiffeners", false]
28728
- };
28729
- var colorProperties = {
28730
- screencolor: "screenColor",
28731
- bezelcolor: "bezelColor",
28732
- flexcolor: "flexCableColor",
28733
- conductorcolor: "conductorColor",
28734
- stiffenercolor: "stiffenerColor"
28735
- };
28736
- var parseAspectRatio = (value) => {
28737
- const normalized = String(value).toLowerCase().replace("x", ":");
28738
- if (normalized.includes(":")) {
28739
- const [width10, height10, extra] = normalized.split(":");
28740
- const numericWidth = Number(width10);
28741
- const numericHeight = Number(height10);
28742
- if (extra !== void 0 || !Number.isFinite(numericWidth) || !Number.isFinite(numericHeight) || numericWidth <= 0 || numericHeight <= 0) {
28743
- throw new Error(`Invalid FlexScreen aspect ratio "${String(value)}"`);
29426
+ return last;
29427
+ }
29428
+ function filterPoints(start, end = start) {
29429
+ const full = end === start;
29430
+ let p = start, again;
29431
+ do {
29432
+ again = false;
29433
+ if (p !== p.next && (steiners.size === 0 || !steiners.has(p)) && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
29434
+ if (full || p === end) end = p.prev;
29435
+ filteredOut = true;
29436
+ removeNode(p);
29437
+ p = p.prev;
29438
+ again = true;
29439
+ } else if (full || p !== end) {
29440
+ p = p.next;
29441
+ again = !full;
29442
+ }
29443
+ } while (again || p !== end);
29444
+ return end;
29445
+ }
29446
+ function earcutLinked(ear, triangles, minX, minY, invSize) {
29447
+ if (invSize) indexCurve(ear, minX, minY, invSize);
29448
+ let stop = ear, cured = false;
29449
+ while (ear.prev !== ear.next) {
29450
+ const prev = ear.prev;
29451
+ const next = ear.next;
29452
+ if (area(prev, ear, next) < 0 && (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear))) {
29453
+ triangles.push(prev.i, ear.i, next.i);
29454
+ removeNode(ear);
29455
+ ear = next;
29456
+ stop = next;
29457
+ continue;
29458
+ }
29459
+ ear = next;
29460
+ if (ear === stop) {
29461
+ filteredOut = false;
29462
+ ear = filterPoints(ear);
29463
+ if (filteredOut) {
29464
+ stop = ear;
29465
+ continue;
29466
+ }
29467
+ if (!cured) {
29468
+ ear = cureLocalIntersections(ear, triangles);
29469
+ stop = ear;
29470
+ cured = true;
29471
+ continue;
29472
+ }
29473
+ splitEarcut(ear, triangles, minX, minY, invSize);
29474
+ break;
28744
29475
  }
28745
- return `${numericWidth}:${numericHeight}`;
28746
- }
28747
- const numeric = Number(normalized);
28748
- if (!Number.isFinite(numeric) || numeric <= 0) {
28749
- throw new Error(`Invalid FlexScreen aspect ratio "${String(value)}"`);
28750
29476
  }
28751
- return numeric;
28752
- };
28753
- var unwrapFunctionValue = (value, token) => {
28754
- if (typeof value !== "string" || !/^\(.+\)$/.test(value)) {
28755
- throw new Error(`FlexScreen token "${token}" requires a value in (...)`);
29477
+ }
29478
+ function isEar(ear) {
29479
+ const a = ear.prev, b = ear, c = ear.next, ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y, x0 = Math.min(ax, bx, cx), y0 = Math.min(ay, by, cy), x1 = Math.max(ax, bx, cx), y1 = Math.max(ay, by, cy);
29480
+ let p = c.next;
29481
+ while (p !== a) {
29482
+ if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && !(ax === p.x && ay === p.y) && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
29483
+ p = p.next;
28756
29484
  }
28757
- return value.slice(1, -1);
28758
- };
28759
- var assertBareToken = (value, token) => {
28760
- if (value !== true) {
28761
- throw new Error(`FlexScreen token "${token}" does not accept a value`);
29485
+ return true;
29486
+ }
29487
+ function isEarHashed(ear, minX, minY, invSize) {
29488
+ const a = ear.prev, b = ear, c = ear.next, ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y, x0 = Math.min(ax, bx, cx), y0 = Math.min(ay, by, cy), x1 = Math.max(ax, bx, cx), y1 = Math.max(ay, by, cy), minZ = zOrder(x0, y0, minX, minY, invSize), maxZ = zOrder(x1, y1, minX, minY, invSize);
29489
+ let p = ear.prevZ;
29490
+ while (p && p.z >= minZ) {
29491
+ if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== c && !(ax === p.x && ay === p.y) && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
29492
+ p = p.prevZ;
28762
29493
  }
28763
- };
28764
- var parseFlexScreenModelParams = (rawParams) => {
28765
- if (rawParams.fn !== "flexscreen") {
28766
- throw new Error(`Expected FlexScreen params, got "${rawParams.fn}"`);
29494
+ let n = ear.nextZ;
29495
+ while (n && n.z <= maxZ) {
29496
+ if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== c && !(ax === n.x && ay === n.y) && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
29497
+ n = n.nextZ;
28767
29498
  }
28768
- const props = {};
28769
- let orientation2;
28770
- let relativeDistance;
28771
- for (const [token, value] of Object.entries(rawParams)) {
28772
- if (token === "fn" || token === "string" || token === "flexscreen") {
28773
- continue;
29499
+ return true;
29500
+ }
29501
+ function cureLocalIntersections(start, triangles) {
29502
+ let p = start;
29503
+ let cured = false;
29504
+ do {
29505
+ const a = p.prev, b = p.next.next;
29506
+ if (intersects(a, p, p.next, b, false) && locallyInside(a, b) && locallyInside(b, a)) {
29507
+ triangles.push(a.i, p.i, b.i);
29508
+ removeNode(p);
29509
+ removeNode(p.next);
29510
+ p = start = b;
29511
+ cured = true;
28774
29512
  }
28775
- const tokenOrientation = orientationTokens[token];
28776
- if (tokenOrientation) {
28777
- assertBareToken(value, token);
28778
- if (orientation2 && orientation2 !== tokenOrientation) {
28779
- throw new Error(
28780
- "A FlexScreen model string can only set one orientation"
28781
- );
29513
+ p = p.next;
29514
+ } while (p !== start);
29515
+ return cured ? filterPoints(p) : p;
29516
+ }
29517
+ function splitEarcut(start, triangles, minX, minY, invSize) {
29518
+ let a = start;
29519
+ do {
29520
+ let b = a.next.next;
29521
+ while (b !== a.prev) {
29522
+ if (a.i !== b.i && isValidDiagonal(a, b)) {
29523
+ let c = splitPolygon(a, b);
29524
+ a = filterPoints(a, a.next);
29525
+ c = filterPoints(c, c.next);
29526
+ earcutLinked(a, triangles, minX, minY, invSize);
29527
+ earcutLinked(c, triangles, minX, minY, invSize);
29528
+ return;
28782
29529
  }
28783
- orientation2 = tokenOrientation;
28784
- props.orientation = tokenOrientation;
28785
- continue;
28786
- }
28787
- if (token in booleanTokens) {
28788
- assertBareToken(value, token);
28789
- const [property, enabled] = booleanTokens[token];
28790
- props[property] = enabled;
28791
- continue;
28792
- }
28793
- const colorProperty = colorProperties[token];
28794
- if (colorProperty) {
28795
- props[colorProperty] = unwrapFunctionValue(value, token);
28796
- continue;
28797
- }
28798
- if (token === "ratio") {
28799
- props.aspectRatio = parseAspectRatio(value);
28800
- continue;
28801
- }
28802
- const lengthProperty = lengthTokenToProperty[token];
28803
- if (lengthProperty) {
28804
- props[lengthProperty] = value;
28805
- continue;
28806
- }
28807
- if (token === "distance") {
28808
- relativeDistance = value;
28809
- continue;
29530
+ b = b.next;
28810
29531
  }
28811
- const integerProperty = integerTokenToProperty[token];
28812
- if (integerProperty) {
28813
- const parsed = Number(value);
28814
- if (!Number.isInteger(parsed) || parsed < 1) {
28815
- throw new Error(
28816
- `Invalid positive integer in FlexScreen token "${token}${String(value)}"`
28817
- );
29532
+ a = a.next;
29533
+ } while (a !== start);
29534
+ }
29535
+ var indexActive = false;
29536
+ function eliminateHoles(data, holeIndices, outerNode, dim) {
29537
+ const queue = [];
29538
+ for (let i = 0, len = holeIndices.length; i < len; i++) {
29539
+ const start = holeIndices[i] * dim;
29540
+ const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
29541
+ const list = (
29542
+ /** @type {Node} */
29543
+ linkedList(data, start, end, dim, false)
29544
+ );
29545
+ if (list === list.next) steiners.add(list);
29546
+ queue.push(getLeftmost(list));
29547
+ }
29548
+ queue.sort(compareXYSlope);
29549
+ buildBlockIndex(data.length / dim, holeIndices.length);
29550
+ indexSegment(outerNode, outerNode);
29551
+ indexActive = true;
29552
+ for (let i = 0; i < queue.length; i++) {
29553
+ outerNode = eliminateHole(queue[i], outerNode);
29554
+ }
29555
+ indexActive = false;
29556
+ return filterPoints(outerNode);
29557
+ }
29558
+ function compareXYSlope(a, b) {
29559
+ return a.x - b.x || a.y - b.y || (a.next.y - a.y) / (a.next.x - a.x) - (b.next.y - b.y) / (b.next.x - b.x);
29560
+ }
29561
+ function eliminateHole(hole, outerNode) {
29562
+ const bridge = findHoleBridge(hole, outerNode);
29563
+ if (!bridge) {
29564
+ return outerNode;
29565
+ }
29566
+ const bridgeReverse = splitPolygon(bridge, hole);
29567
+ const bridge2 = bridgeReverse.next;
29568
+ indexSegment(bridge, bridge2.next);
29569
+ filterPoints(bridgeReverse, bridgeReverse.next);
29570
+ return filterPoints(bridge, bridge.next);
29571
+ }
29572
+ var K = 16;
29573
+ var blockBBox = new Float64Array(0);
29574
+ var numBlocks = 0;
29575
+ var blockHead = [];
29576
+ var blockStop = [];
29577
+ function buildBlockIndex(maxNodes, numHoles) {
29578
+ const maxBlocks = Math.ceil((maxNodes + 2 * numHoles) / K) + numHoles + 2;
29579
+ if (blockBBox.length < maxBlocks * 4) blockBBox = new Float64Array(maxBlocks * 4);
29580
+ numBlocks = 0;
29581
+ }
29582
+ function indexSegment(head, stop) {
29583
+ let p = head;
29584
+ do {
29585
+ const b = numBlocks++;
29586
+ blockHead[b] = p;
29587
+ let minX = p.x, minY = p.y, maxX = p.x, maxY = p.y;
29588
+ let k = 0;
29589
+ do {
29590
+ const c = p.next;
29591
+ p.z = b;
29592
+ if (c.x < minX) minX = c.x;
29593
+ if (c.x > maxX) maxX = c.x;
29594
+ if (c.y < minY) minY = c.y;
29595
+ if (c.y > maxY) maxY = c.y;
29596
+ p = c;
29597
+ } while (++k < K && p !== stop);
29598
+ blockStop[b] = p;
29599
+ const g = b * 4;
29600
+ blockBBox[g] = minX;
29601
+ blockBBox[g + 1] = minY;
29602
+ blockBBox[g + 2] = maxX;
29603
+ blockBBox[g + 3] = maxY;
29604
+ } while (p !== stop);
29605
+ }
29606
+ function growBlock(head, tail) {
29607
+ const g = head.z * 4;
29608
+ if (tail.x < blockBBox[g]) blockBBox[g] = tail.x;
29609
+ if (tail.y < blockBBox[g + 1]) blockBBox[g + 1] = tail.y;
29610
+ if (tail.x > blockBBox[g + 2]) blockBBox[g + 2] = tail.x;
29611
+ if (tail.y > blockBBox[g + 3]) blockBBox[g + 3] = tail.y;
29612
+ }
29613
+ function liveBlockStop(b) {
29614
+ let stop = blockStop[b];
29615
+ while (stop.prev.next !== stop) stop = stop.next;
29616
+ blockStop[b] = stop;
29617
+ return stop;
29618
+ }
29619
+ function liveBlockHead(b) {
29620
+ let head = blockHead[b];
29621
+ while (head.prev.next !== head) head = head.next;
29622
+ blockHead[b] = head;
29623
+ return head;
29624
+ }
29625
+ function findHoleBridge(hole, outerNode) {
29626
+ let p = outerNode;
29627
+ const hx = hole.x;
29628
+ const hy = hole.y;
29629
+ let qx = -Infinity;
29630
+ let m;
29631
+ if (equals(hole, p)) return p;
29632
+ for (let b = 0, g = 0; b < numBlocks; b++, g += 4) {
29633
+ if (hy < blockBBox[g + 1] || hy > blockBBox[g + 3] || blockBBox[g] > hx || blockBBox[g + 2] <= qx) continue;
29634
+ const stop = liveBlockStop(b);
29635
+ p = liveBlockHead(b);
29636
+ do {
29637
+ if (p.prev.next === p) {
29638
+ if (equals(hole, p.next)) return p.next;
29639
+ else if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
29640
+ const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
29641
+ if (x <= hx && x > qx) {
29642
+ qx = x;
29643
+ m = p.x < p.next.x ? p : p.next;
29644
+ if (x === hx) return m;
29645
+ }
29646
+ }
28818
29647
  }
28819
- props[integerProperty] = parsed;
29648
+ p = p.next;
29649
+ } while (p !== stop);
29650
+ }
29651
+ if (!m) return null;
29652
+ const mx = m.x;
29653
+ const my = m.y;
29654
+ const tminY = Math.min(hy, my);
29655
+ const tmaxY = Math.max(hy, my);
29656
+ let tanMin = Infinity;
29657
+ for (let b = 0, g = 0; b < numBlocks; b++, g += 4) {
29658
+ if (blockBBox[g + 2] < mx || blockBBox[g] > hx || blockBBox[g + 3] < tminY || blockBBox[g + 1] > tmaxY) continue;
29659
+ const stop = liveBlockStop(b);
29660
+ p = liveBlockHead(b);
29661
+ do {
29662
+ if (p.prev.next === p && hx >= p.x && p.x >= mx && hx !== p.x && // skip dead nodes
29663
+ pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
29664
+ const tan = Math.abs(hy - p.y) / (hx - p.x);
29665
+ if ((locallyInside(p, hole) || p.y === hy && p.next.y === hy && p.next.x > hx) && (tan < tanMin || tan === tanMin && (p.x > m.x || p.x === m.x && sectorContainsSector(m, p)))) {
29666
+ m = p;
29667
+ tanMin = tan;
29668
+ }
29669
+ }
29670
+ p = p.next;
29671
+ } while (p !== stop);
29672
+ }
29673
+ return m;
29674
+ }
29675
+ function sectorContainsSector(m, p) {
29676
+ return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
29677
+ }
29678
+ var sortArr = [];
29679
+ var sortBuf = [];
29680
+ var zArr = new Uint32Array(0);
29681
+ var zBuf = new Uint32Array(0);
29682
+ var counts = new Uint32Array(256);
29683
+ function indexCurve(start, minX, minY, invSize) {
29684
+ let p = start;
29685
+ let n = 0;
29686
+ do {
29687
+ p.z = zOrder(p.x, p.y, minX, minY, invSize);
29688
+ sortArr[n++] = p;
29689
+ p = p.next;
29690
+ } while (p !== start);
29691
+ sortNodes(n);
29692
+ let prev = null;
29693
+ for (let i = 0; i < n; i++) {
29694
+ const node = sortArr[i];
29695
+ node.prevZ = prev;
29696
+ if (prev) prev.nextZ = node;
29697
+ prev = node;
29698
+ }
29699
+ prev.nextZ = null;
29700
+ sortArr.fill(
29701
+ /** @type {Node} */
29702
+ /** @type {unknown} */
29703
+ null,
29704
+ 0,
29705
+ n
29706
+ );
29707
+ sortBuf.fill(
29708
+ /** @type {Node} */
29709
+ /** @type {unknown} */
29710
+ null,
29711
+ 0,
29712
+ n
29713
+ );
29714
+ }
29715
+ function sortNodes(n) {
29716
+ if (n <= 32) {
29717
+ for (let i = 1; i < n; i++) {
29718
+ const node = sortArr[i], z27 = node.z;
29719
+ let j = i - 1;
29720
+ while (j >= 0 && sortArr[j].z > z27) {
29721
+ sortArr[j + 1] = sortArr[j];
29722
+ j--;
29723
+ }
29724
+ sortArr[j + 1] = node;
29725
+ }
29726
+ return;
29727
+ }
29728
+ if (zArr.length < n) {
29729
+ zArr = new Uint32Array(n);
29730
+ zBuf = new Uint32Array(n);
29731
+ sortBuf = new Array(n);
29732
+ }
29733
+ for (let i = 0; i < n; i++) zArr[i] = sortArr[i].z;
29734
+ radixPass(n, sortArr, zArr, sortBuf, zBuf, 0);
29735
+ radixPass(n, sortBuf, zBuf, sortArr, zArr, 8);
29736
+ radixPass(n, sortArr, zArr, sortBuf, zBuf, 16);
29737
+ radixPass(n, sortBuf, zBuf, sortArr, zArr, 24);
29738
+ }
29739
+ function radixPass(n, src, srcZ, dst, dstZ, shift4) {
29740
+ counts.fill(0);
29741
+ for (let i = 0; i < n; i++) counts[srcZ[i] >>> shift4 & 255]++;
29742
+ let sum = 0;
29743
+ for (let b = 0; b < 256; b++) {
29744
+ const c = counts[b];
29745
+ counts[b] = sum;
29746
+ sum += c;
29747
+ }
29748
+ for (let i = 0; i < n; i++) {
29749
+ const z27 = srcZ[i];
29750
+ const pos = counts[z27 >>> shift4 & 255]++;
29751
+ dst[pos] = src[i];
29752
+ dstZ[pos] = z27;
29753
+ }
29754
+ }
29755
+ function zOrder(x, y, minX, minY, invSize) {
29756
+ x = (x - minX) * invSize | 0;
29757
+ y = (y - minY) * invSize | 0;
29758
+ x = (x | x << 8) & 16711935;
29759
+ x = (x | x << 4) & 252645135;
29760
+ x = (x | x << 2) & 858993459;
29761
+ x = (x | x << 1) & 1431655765;
29762
+ y = (y | y << 8) & 16711935;
29763
+ y = (y | y << 4) & 252645135;
29764
+ y = (y | y << 2) & 858993459;
29765
+ y = (y | y << 1) & 1431655765;
29766
+ return x | y << 1;
29767
+ }
29768
+ function getLeftmost(start) {
29769
+ let p = start, leftmost = start;
29770
+ do {
29771
+ if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y) leftmost = p;
29772
+ p = p.next;
29773
+ } while (p !== start);
29774
+ return leftmost;
29775
+ }
29776
+ function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
29777
+ return (cx - px) * (ay - py) >= (ax - px) * (cy - py) && (ax - px) * (by - py) >= (bx - px) * (ay - py) && (bx - px) * (cy - py) >= (cx - px) * (by - py);
29778
+ }
29779
+ function isValidDiagonal(a, b) {
29780
+ const zeroLength = equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0;
29781
+ return a.next.i !== b.i && (zeroLength || locallyInside(a, b) && locallyInside(b, a) && // // locally visible
29782
+ (area(a.prev, a, b.prev) !== 0 || area(a, b.prev, b) !== 0)) && // no opposite-facing sectors
29783
+ !intersectsPolygon(a, b) && (zeroLength || middleInside(a, b));
29784
+ }
29785
+ function area(p, q, r) {
29786
+ return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
29787
+ }
29788
+ function equals(p1, p2) {
29789
+ return p1.x === p2.x && p1.y === p2.y;
29790
+ }
29791
+ function intersects(p1, q1, p2, q2, includeBoundary = true) {
29792
+ const o1 = area(p1, q1, p2);
29793
+ const o2 = area(p1, q1, q2);
29794
+ const o3 = area(p2, q2, p1);
29795
+ const o4 = area(p2, q2, q1);
29796
+ if ((o1 > 0 && o2 < 0 || o1 < 0 && o2 > 0) && (o3 > 0 && o4 < 0 || o3 < 0 && o4 > 0)) return true;
29797
+ if (!includeBoundary) return false;
29798
+ if (o1 === 0 && onSegment(p1, p2, q1)) return true;
29799
+ if (o2 === 0 && onSegment(p1, q2, q1)) return true;
29800
+ if (o3 === 0 && onSegment(p2, p1, q2)) return true;
29801
+ if (o4 === 0 && onSegment(p2, q1, q2)) return true;
29802
+ return false;
29803
+ }
29804
+ function onSegment(p, q, r) {
29805
+ return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
29806
+ }
29807
+ function intersectsPolygon(a, b) {
29808
+ const minX = Math.min(a.x, b.x);
29809
+ const maxX = Math.max(a.x, b.x);
29810
+ const minY = Math.min(a.y, b.y);
29811
+ const maxY = Math.max(a.y, b.y);
29812
+ let p = a;
29813
+ do {
29814
+ const n = p.next;
29815
+ if (p.x > maxX && n.x > maxX || p.x < minX && n.x < minX || p.y > maxY && n.y > maxY || p.y < minY && n.y < minY) {
29816
+ p = n;
28820
29817
  continue;
28821
29818
  }
28822
- throw new Error(`Unknown FlexScreen model token "${token}${String(value)}"`);
29819
+ if (p.i !== a.i && n.i !== a.i && p.i !== b.i && n.i !== b.i && intersects(p, n, a, b)) return true;
29820
+ p = n;
29821
+ } while (p !== a);
29822
+ return false;
29823
+ }
29824
+ function locallyInside(a, b) {
29825
+ return area(a.prev, a, a.next) < 0 ? area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
29826
+ }
29827
+ function middleInside(a, b) {
29828
+ let p = a;
29829
+ let inside = false;
29830
+ const px = (a.x + b.x) / 2;
29831
+ const py = (a.y + b.y) / 2;
29832
+ do {
29833
+ const n = p.next;
29834
+ if (p.y > py !== n.y > py && px < (n.x - p.x) * (py - p.y) / (n.y - p.y) + p.x)
29835
+ inside = !inside;
29836
+ p = n;
29837
+ } while (p !== a);
29838
+ return inside;
29839
+ }
29840
+ function splitPolygon(a, b) {
29841
+ const a2 = createNode(a.i, a.x, a.y), b2 = createNode(b.i, b.x, b.y), an = a.next, bp = b.prev;
29842
+ a.next = b;
29843
+ b.prev = a;
29844
+ a2.next = an;
29845
+ an.prev = a2;
29846
+ b2.next = a2;
29847
+ a2.prev = b2;
29848
+ bp.next = b2;
29849
+ b2.prev = bp;
29850
+ return b2;
29851
+ }
29852
+ function insertNode(i, x, y, last) {
29853
+ const p = createNode(i, x, y);
29854
+ if (!last) {
29855
+ p.prev = p;
29856
+ p.next = p;
29857
+ } else {
29858
+ p.next = last.next;
29859
+ p.prev = last;
29860
+ last.next.prev = p;
29861
+ last.next = p;
28823
29862
  }
28824
- if (relativeDistance !== void 0) {
28825
- if (orientation2 === "foldedToFaceAboveBoard") {
28826
- props.distanceAboveBoard = relativeDistance;
28827
- } else if (orientation2 === "foldedToFaceBelowBoard") {
28828
- props.distanceBelowBoard = relativeDistance;
28829
- } else {
28830
- throw new Error(
28831
- 'The "distance" token requires foldsabove or foldsbelow; use distanceabove or distancebelow for an explicit side'
28832
- );
29863
+ return p;
29864
+ }
29865
+ function removeNode(p) {
29866
+ p.next.prev = p.prev;
29867
+ p.prev.next = p.next;
29868
+ if (p.prevZ) p.prevZ.nextZ = p.nextZ;
29869
+ if (p.nextZ) p.nextZ.prevZ = p.prevZ;
29870
+ if (indexActive) growBlock(p.prev, p.next);
29871
+ }
29872
+ function createNode(i, x, y) {
29873
+ return (
29874
+ /** @type {Node} */
29875
+ /** @type {unknown} */
29876
+ {
29877
+ i,
29878
+ // vertex index in coordinates array
29879
+ x,
29880
+ y,
29881
+ // vertex coordinates
29882
+ prev: null,
29883
+ // previous and next vertex nodes in a polygon ring
29884
+ next: null,
29885
+ z: 0,
29886
+ // z-order curve value; doubles as owning block in the hole-bridge index during eliminateHoles
29887
+ prevZ: null,
29888
+ // previous and next nodes in z-order
29889
+ nextZ: null
28833
29890
  }
29891
+ );
29892
+ }
29893
+ function signedArea(data, start, end, dim) {
29894
+ let sum = 0;
29895
+ for (let i = start, j = end - dim; i < end; i += dim) {
29896
+ sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
29897
+ j = i;
28834
29898
  }
28835
- return flexScreenModelDefinitionSchema.parse({ fn: "flexscreen", ...props });
28836
- };
28837
- var modelFunctions = {
28838
- flexscreen: parseFlexScreenModelParams
29899
+ return sum;
29900
+ }
29901
+
29902
+ // node_modules/jscad-electronics/dist/vanilla.js
29903
+ var import_modeling2 = __toESM(require_src(), 1);
29904
+
29905
+ // node_modules/jscad-electronics/node_modules/@tscircuit/mm/dist/index.js
29906
+ var unitToMm3 = {
29907
+ in: 25.4,
29908
+ inch: 25.4,
29909
+ mil: 0.0254,
29910
+ mm: 1,
29911
+ m: 1e3,
29912
+ cm: 10,
29913
+ ft: 304.8,
29914
+ feet: 304.8
28839
29915
  };
28840
- var modelParamsToJson = (params) => {
28841
- const modelFunction = modelFunctions[params.fn];
28842
- if (modelFunction) {
28843
- return modelFunction(params);
29916
+ var mm3 = (n) => {
29917
+ let unit = typeof n === "number" ? "mm" : n.replace(/^[^a-zA-Z]+/g, "").toLowerCase();
29918
+ if (!unit)
29919
+ unit = "mm";
29920
+ const val = typeof n === "number" ? n : Number.parseFloat(n.split(unit)[0]);
29921
+ if (unit in unitToMm3) {
29922
+ return val * unitToMm3[unit];
28844
29923
  }
28845
- throw new Error(`Unsupported modelprinter function "${params.fn}"`);
28846
- };
28847
- var string = (value) => {
28848
- const params = parseModelStringParams(value);
28849
- return {
28850
- params: () => params,
28851
- json: () => modelParamsToJson(params)
28852
- };
28853
- };
28854
- var modelprinter = {
28855
- string,
28856
- getModelNames: () => Object.keys(modelFunctions)
29924
+ throw new Error(`Unsupported unit: ${unit}`);
28857
29925
  };
28858
- var mp = modelprinter;
28859
29926
 
28860
29927
  // node_modules/jscad-electronics/dist/vanilla.js
28861
29928
  import {
@@ -28895,6 +29962,7 @@ var Colorize = /* @__PURE__ */ Symbol("Colorize");
28895
29962
  var Polygon = /* @__PURE__ */ Symbol("Polygon");
28896
29963
  var ExtrudeLinear = /* @__PURE__ */ Symbol("ExtrudeLinear");
28897
29964
  var RoundedCylinder = /* @__PURE__ */ Symbol("RoundedCylinder");
29965
+ var Custom = /* @__PURE__ */ Symbol("Custom");
28898
29966
  var Fragment2 = Fragment;
28899
29967
  var jsx3 = (type, props, _key) => h(type, props);
28900
29968
  var jsxs = (type, props, _key) => h(type, props);
@@ -28985,6 +30053,363 @@ var FootprintPlatedHole = ({
28985
30053
  }
28986
30054
  throw new Error("Shape not supported: " + hole.shape);
28987
30055
  };
30056
+ var createHexSocketBoltMesh = (input) => {
30057
+ const props = hexSocketBoltModelPropsSchema.parse(input);
30058
+ const {
30059
+ diameter,
30060
+ threadPitch: pitch,
30061
+ headDiameter,
30062
+ headHeight,
30063
+ socketWidth,
30064
+ socketDepth
30065
+ } = hexSocketBoltDimensions[props.metricSize];
30066
+ const { length: length83, showThreads } = props;
30067
+ const segments = 96;
30068
+ const steps = Math.max(2, Math.ceil(length83 / pitch * 24));
30069
+ if (steps > 24e3)
30070
+ throw new Error(
30071
+ "Bolt length exceeds mesh resolution limit (1000 thread turns)"
30072
+ );
30073
+ const positions = [];
30074
+ const indices = [];
30075
+ const radius = diameter / 2;
30076
+ const depth = pitch * 0.61343;
30077
+ const bevel = Math.min(0.2, headHeight * 0.08);
30078
+ const tipBevel = Math.min(pitch * 0.6, length83 / 3);
30079
+ const ring = (z27, radiusAt) => {
30080
+ const start = positions.length / 3;
30081
+ for (let i = 0; i < segments; i++) {
30082
+ const angle = i * Math.PI * 2 / segments;
30083
+ const r = radiusAt(angle);
30084
+ positions.push(r * Math.cos(angle), r * Math.sin(angle), z27);
30085
+ }
30086
+ return start;
30087
+ };
30088
+ const connect = (a, b) => {
30089
+ for (let i = 0; i < segments; i++) {
30090
+ const next = (i + 1) % segments;
30091
+ indices.push(a + i, a + next, b + next, a + i, b + next, b + i);
30092
+ }
30093
+ };
30094
+ const cap2 = (start, z27, upward) => {
30095
+ const center = positions.length / 3;
30096
+ positions.push(0, 0, z27);
30097
+ for (let i = 0; i < segments; i++) {
30098
+ const a = start + i;
30099
+ const b = start + (i + 1) % segments;
30100
+ indices.push(center, upward ? a : b, upward ? b : a);
30101
+ }
30102
+ };
30103
+ let previous = -1;
30104
+ for (let step = 0; step <= steps; step++) {
30105
+ const z27 = -length83 + length83 * step / steps;
30106
+ const current = ring(z27, (angle) => {
30107
+ const phase = ((z27 / pitch - angle / (2 * Math.PI)) % 1 + 1) % 1;
30108
+ const distance22 = Math.min(phase, 1 - phase);
30109
+ const groove = Math.min(
30110
+ depth,
30111
+ Math.max(0, (distance22 - 1 / 16) * pitch * Math.sqrt(3))
30112
+ );
30113
+ const endRamp = Math.min(
30114
+ 1,
30115
+ (z27 + length83) / tipBevel,
30116
+ -z27 / Math.min(pitch / 2, length83 / 3)
30117
+ );
30118
+ const tipCut = tipBevel * Math.max(0, 1 - (z27 + length83) / tipBevel);
30119
+ return radius - (showThreads ? groove * endRamp : 0) - tipCut;
30120
+ });
30121
+ if (previous < 0) cap2(current, z27, false);
30122
+ else connect(previous, current);
30123
+ previous = current;
30124
+ }
30125
+ const addRing = (z27, radiusAt) => {
30126
+ const current = ring(z27, radiusAt);
30127
+ connect(previous, current);
30128
+ previous = current;
30129
+ };
30130
+ addRing(0, () => headDiameter / 2 - bevel);
30131
+ addRing(bevel, () => headDiameter / 2);
30132
+ addRing(headHeight - bevel, () => headDiameter / 2);
30133
+ addRing(headHeight, () => headDiameter / 2 - bevel);
30134
+ const hexRadius = (angle, acrossFlats) => acrossFlats / 2 / Math.cos((angle + Math.PI / 6) % (Math.PI / 3) - Math.PI / 6);
30135
+ addRing(headHeight, (angle) => hexRadius(angle, socketWidth + bevel));
30136
+ addRing(headHeight - bevel / 2, (angle) => hexRadius(angle, socketWidth));
30137
+ addRing(headHeight - socketDepth, (angle) => hexRadius(angle, socketWidth));
30138
+ cap2(previous, headHeight - socketDepth, true);
30139
+ return { positions, indices };
30140
+ };
30141
+ function indexedMeshToGeom3(mesh) {
30142
+ const polygons = [];
30143
+ for (let i = 0; i < mesh.indices.length; i += 3)
30144
+ polygons.push(
30145
+ mesh.indices.slice(i, i + 3).map((index2) => [
30146
+ mesh.positions[index2 * 3],
30147
+ mesh.positions[index2 * 3 + 1],
30148
+ mesh.positions[index2 * 3 + 2]
30149
+ ])
30150
+ );
30151
+ return import_modeling.default.geometries.geom3.fromPoints(polygons);
30152
+ }
30153
+ function createHexSocketBoltGeom(input) {
30154
+ return indexedMeshToGeom3(createHexSocketBoltMesh(input));
30155
+ }
30156
+ function HexSocketBolt({
30157
+ color = "#737e8f",
30158
+ ...props
30159
+ }) {
30160
+ return /* @__PURE__ */ jsx3(Colorize, { color, children: /* @__PURE__ */ jsx3(Custom, { geometry: createHexSocketBoltGeom(props) }) });
30161
+ }
30162
+ function holeOutline(hole) {
30163
+ const radius = (hole.shape === "round" ? hole.diameter : hole.width) / 2;
30164
+ const straight = hole.shape === "slot" ? (hole.length - hole.width) / 2 : 0;
30165
+ if (straight < 0) throw new Error("Slot length must be at least its width");
30166
+ return Array.from({ length: 64 }, (_, i) => {
30167
+ if (hole.shape === "round") {
30168
+ const angle2 = i * Math.PI / 32;
30169
+ return {
30170
+ u: hole.u + radius * Math.cos(angle2),
30171
+ v: hole.v + radius * Math.sin(angle2)
30172
+ };
30173
+ }
30174
+ const half = i < 32 ? 1 : -1;
30175
+ const angle = -Math.PI / 2 + (i < 32 ? i : i - 32) * Math.PI / 31 + (i < 32 ? 0 : Math.PI);
30176
+ const along = half * straight + radius * Math.cos(angle);
30177
+ const across = radius * Math.sin(angle);
30178
+ return hole.shape === "slot" && hole.axis === "v" ? { u: hole.u - across, v: hole.v + along } : { u: hole.u + along, v: hole.v + across };
30179
+ });
30180
+ }
30181
+ function createSheetMetalMesh(input) {
30182
+ const props = sheetMetalModelPropsSchema.parse(input);
30183
+ const { width: width10, baseLength, flangeHeight, thickness, profile } = props;
30184
+ const radius = props.insideBendRadius + thickness / 2;
30185
+ const positions = [];
30186
+ const indices = [];
30187
+ const addTriangle = (vertices, reverse = false) => {
30188
+ const start = positions.length / 3;
30189
+ for (const vertex of vertices) positions.push(...vertex);
30190
+ indices.push(start, start + (reverse ? 2 : 1), start + (reverse ? 1 : 2));
30191
+ };
30192
+ const addQuad = (vertices, reverse = false) => {
30193
+ addTriangle([vertices[0], vertices[1], vertices[2]], reverse);
30194
+ addTriangle([vertices[0], vertices[2], vertices[3]], reverse);
30195
+ };
30196
+ const panels = profile === "plate" ? ["base"] : profile === "angle" ? ["base", "right"] : ["base", "left", "right"];
30197
+ for (const hole of props.holes) {
30198
+ if (!panels.includes(hole.panel))
30199
+ throw new Error(`No ${hole.panel} panel on ${profile}`);
30200
+ }
30201
+ for (const panel of panels) {
30202
+ const length83 = panel === "base" ? baseLength : flangeHeight;
30203
+ const holes = props.holes.filter((hole) => hole.panel === panel).map(holeOutline);
30204
+ const bounds = holes.map((outline2) => ({
30205
+ minU: Math.min(...outline2.map((p) => p.u)),
30206
+ maxU: Math.max(...outline2.map((p) => p.u)),
30207
+ minV: Math.min(...outline2.map((p) => p.v)),
30208
+ maxV: Math.max(...outline2.map((p) => p.v))
30209
+ }));
30210
+ for (const [i, box] of bounds.entries()) {
30211
+ if (box.minU <= -length83 / 2 || box.maxU >= length83 / 2 || box.minV <= -width10 / 2 || box.maxV >= width10 / 2)
30212
+ throw new Error(`Hole crosses ${panel} panel edge or bend tangent`);
30213
+ for (const previous of bounds.slice(0, i))
30214
+ if (box.minU <= previous.maxU && box.maxU >= previous.minU && box.minV <= previous.maxV && box.maxV >= previous.minV)
30215
+ throw new Error("Hole bounding boxes must not overlap");
30216
+ }
30217
+ const outline = [
30218
+ { u: -length83 / 2, v: -width10 / 2 },
30219
+ { u: length83 / 2, v: -width10 / 2 },
30220
+ { u: length83 / 2, v: width10 / 2 },
30221
+ { u: -length83 / 2, v: width10 / 2 }
30222
+ ];
30223
+ const loops = [outline, ...holes.map((hole) => [...hole].reverse())];
30224
+ const points = loops.flat();
30225
+ const starts = holes.map((_, i) => 4 + i * 64);
30226
+ const triangles = earcut(
30227
+ points.flatMap((p) => [p.u, p.v]),
30228
+ starts
30229
+ );
30230
+ const project = (point, offset4) => panel === "base" ? [point.u, point.v, offset4] : [
30231
+ (panel === "left" ? -1 : 1) * (baseLength / 2 + radius - offset4),
30232
+ point.v,
30233
+ radius + flangeHeight / 2 + point.u
30234
+ ];
30235
+ const reverse = panel === "left";
30236
+ for (let i = 0; i < triangles.length; i += 3) {
30237
+ const face2 = triangles.slice(i, i + 3).map((index2) => points[index2]);
30238
+ addTriangle(
30239
+ face2.map((p) => project(p, thickness / 2)),
30240
+ reverse
30241
+ );
30242
+ addTriangle(
30243
+ face2.map((p) => project(p, -thickness / 2)),
30244
+ !reverse
30245
+ );
30246
+ }
30247
+ for (const [loopIndex, loop] of loops.entries())
30248
+ for (let i = 0; i < loop.length; i++) {
30249
+ const a = loop[i], b = loop[(i + 1) % loop.length];
30250
+ if (loopIndex === 0 && a.u === b.u && (panel === "base" && (a.u > 0 && profile !== "plate" || a.u < 0 && profile === "channel") || panel !== "base" && a.u < 0))
30251
+ continue;
30252
+ addQuad(
30253
+ [
30254
+ project(a, -thickness / 2),
30255
+ project(b, -thickness / 2),
30256
+ project(b, thickness / 2),
30257
+ project(a, thickness / 2)
30258
+ ],
30259
+ reverse
30260
+ );
30261
+ }
30262
+ }
30263
+ const sides2 = profile === "plate" ? [] : profile === "angle" ? [1] : [-1, 1];
30264
+ for (const side of sides2) {
30265
+ const project = (angle, crossSection) => {
30266
+ const r = radius - crossSection.offset;
30267
+ return [
30268
+ side * (baseLength / 2 + r * Math.sin(angle)),
30269
+ crossSection.y,
30270
+ radius - r * Math.cos(angle)
30271
+ ];
30272
+ };
30273
+ for (let i = 0; i < 32; i++) {
30274
+ const a = i * Math.PI / 64, b = (i + 1) * Math.PI / 64;
30275
+ for (const offset4 of [-thickness / 2, thickness / 2]) {
30276
+ addQuad(
30277
+ [
30278
+ project(a, { y: -width10 / 2, offset: offset4 }),
30279
+ project(b, { y: -width10 / 2, offset: offset4 }),
30280
+ project(b, { y: width10 / 2, offset: offset4 }),
30281
+ project(a, { y: width10 / 2, offset: offset4 })
30282
+ ],
30283
+ offset4 < 0 !== side < 0
30284
+ );
30285
+ }
30286
+ for (const y of [-width10 / 2, width10 / 2]) {
30287
+ addQuad(
30288
+ [
30289
+ project(a, { y, offset: -thickness / 2 }),
30290
+ project(b, { y, offset: -thickness / 2 }),
30291
+ project(b, { y, offset: thickness / 2 }),
30292
+ project(a, { y, offset: thickness / 2 })
30293
+ ],
30294
+ y > 0 !== side < 0
30295
+ );
30296
+ }
30297
+ }
30298
+ }
30299
+ return { positions, indices };
30300
+ }
30301
+ function createSheetMetalGeom(input) {
30302
+ return indexedMeshToGeom3(createSheetMetalMesh(input));
30303
+ }
30304
+ function SheetMetal({ color = "#737e8f", ...props }) {
30305
+ return /* @__PURE__ */ jsx3(Colorize, { color, children: /* @__PURE__ */ jsx3(Custom, { geometry: createSheetMetalGeom(props) }) });
30306
+ }
30307
+ var resolveNemaMotorProps = nemaMotorModelPropsSchema.parse.bind(
30308
+ nemaMotorModelPropsSchema
30309
+ );
30310
+ var circle = (radius, x = 0, y = 0) => Array.from({ length: 96 }, (_, i) => [
30311
+ x + radius * Math.cos(i * Math.PI / 48),
30312
+ y + radius * Math.sin(i * Math.PI / 48)
30313
+ ]);
30314
+ var face = (width10, chamfer) => {
30315
+ const h2 = width10 / 2, c = chamfer;
30316
+ if (c === 0)
30317
+ return [
30318
+ [-h2, -h2],
30319
+ [h2, -h2],
30320
+ [h2, h2],
30321
+ [-h2, h2]
30322
+ ];
30323
+ return [
30324
+ [-h2 + c, -h2],
30325
+ [h2 - c, -h2],
30326
+ [h2, -h2 + c],
30327
+ [h2, h2 - c],
30328
+ [h2 - c, h2],
30329
+ [-h2 + c, h2],
30330
+ [-h2, h2 - c],
30331
+ [-h2, -h2 + c]
30332
+ ];
30333
+ };
30334
+ function createNemaMotorSections(input) {
30335
+ const p = resolveNemaMotorProps(input);
30336
+ const sections = [];
30337
+ const add = (name, outline, zMin, zMax, holes2 = []) => {
30338
+ if (zMax > zMin) sections.push({ name, outline, holes: holes2, zMin, zMax });
30339
+ };
30340
+ const front = face(p.bodyWidth, p.faceCornerChamfer);
30341
+ const core = face(p.bodyWidth, p.bodyCornerChamfer);
30342
+ const h2 = p.mountingHoleSpacing / 2;
30343
+ const centers = [
30344
+ [-h2, -h2],
30345
+ [h2, -h2],
30346
+ [h2, h2],
30347
+ [-h2, h2]
30348
+ ];
30349
+ const holes = centers.map(
30350
+ ([x, y]) => circle(p.mountingHoleDiameter / 2, x, y)
30351
+ );
30352
+ const holeDepth = p.mountingHoleThrough ? p.frontCapLength : p.mountingHoleDepth;
30353
+ add("frontCap", front, -holeDepth, 0, holes);
30354
+ add("frontCap", front, -p.frontCapLength, -holeDepth);
30355
+ add("body", core, -p.bodyLength + p.rearCapLength, -p.frontCapLength);
30356
+ add(
30357
+ "rearCap",
30358
+ p.mountingHoleThrough ? core : front,
30359
+ -p.bodyLength,
30360
+ -p.bodyLength + p.rearCapLength
30361
+ );
30362
+ add("pilot", circle(p.pilotDiameter / 2), 0, p.pilotLength);
30363
+ const r = p.shaftDiameter / 2;
30364
+ const round2 = circle(r);
30365
+ if (p.shaftShape === "round")
30366
+ add("shaft", round2, p.pilotLength, p.shaftLength);
30367
+ else {
30368
+ const cut = r - p.shaftFlatDepth;
30369
+ const angle = Math.acos(cut / r);
30370
+ const profile = Array.from({ length: 97 }, (_, i) => {
30371
+ const a = angle + (2 * Math.PI - 2 * angle) * i / 96;
30372
+ return [r * Math.cos(a), r * Math.sin(a)];
30373
+ });
30374
+ const rotation = p.shaftFlatAngle * Math.PI / 180;
30375
+ const d = profile.map(([x, y]) => [
30376
+ x * Math.cos(rotation) - y * Math.sin(rotation),
30377
+ x * Math.sin(rotation) + y * Math.cos(rotation)
30378
+ ]);
30379
+ add("shaft", round2, p.pilotLength, p.shaftLength - p.shaftFlatLength);
30380
+ add("shaft", d, p.shaftLength - p.shaftFlatLength, p.shaftLength);
30381
+ }
30382
+ return sections;
30383
+ }
30384
+ function NemaMotor({
30385
+ bodyColor = "#242830",
30386
+ capColor = "#aeb5bd",
30387
+ shaftColor = "#b8bec6",
30388
+ ...props
30389
+ }) {
30390
+ return /* @__PURE__ */ jsx3(Fragment2, { children: createNemaMotorSections(props).map((section, index2) => {
30391
+ const outline = import_modeling2.default.geometries.geom2.fromPoints(section.outline);
30392
+ const profile = section.holes.length ? import_modeling2.default.booleans.subtract(
30393
+ outline,
30394
+ ...section.holes.map((h2) => import_modeling2.default.geometries.geom2.fromPoints(h2))
30395
+ ) : outline;
30396
+ const geometry = import_modeling2.default.transforms.translate(
30397
+ [0, 0, section.zMin],
30398
+ import_modeling2.default.extrusions.extrudeLinear(
30399
+ { height: section.zMax - section.zMin },
30400
+ profile
30401
+ )
30402
+ );
30403
+ return /* @__PURE__ */ jsx3(
30404
+ Colorize,
30405
+ {
30406
+ color: section.name === "body" ? bodyColor : section.name === "shaft" ? shaftColor : capColor,
30407
+ children: /* @__PURE__ */ jsx3(Custom, { geometry })
30408
+ },
30409
+ `${section.name}-${index2}`
30410
+ );
30411
+ }) });
30412
+ }
28988
30413
  function LGA(p) {
28989
30414
  for (const k of [
28990
30415
  "bodyWidth",
@@ -29167,7 +30592,7 @@ function createDualRowGullWing(p) {
29167
30592
  ]);
29168
30593
  }
29169
30594
  points.push([root, midZ]);
29170
- const section = ([x, z42]) => /* @__PURE__ */ jsx3(Translate, { offset: { x: side * x, y, z: z42 }, children: /* @__PURE__ */ jsx3(Cuboid, { size: [slice, leadWidth, leadThickness] }) });
30595
+ const section = ([x, z27]) => /* @__PURE__ */ jsx3(Translate, { offset: { x: side * x, y, z: z27 }, children: /* @__PURE__ */ jsx3(Cuboid, { size: [slice, leadWidth, leadThickness] }) });
29171
30596
  return /* @__PURE__ */ jsx3(Union, { children: points.slice(1).map((point, i) => /* @__PURE__ */ jsxs(Hull, { children: [
29172
30597
  section(points[i]),
29173
30598
  section(point)
@@ -29423,10 +30848,10 @@ var svgPathPoints = normalizeOnY([
29423
30848
  ]);
29424
30849
  var DIP_PIN_HEIGHT = 5.47;
29425
30850
  var heightAboveSurface = 0.5;
29426
- var DipPinLeg = ({ x, y, z: z42 }) => {
30851
+ var DipPinLeg = ({ x, y, z: z27 }) => {
29427
30852
  const isRotated = x > 0;
29428
30853
  return /* @__PURE__ */ jsxs(Fragment2, { children: [
29429
- /* @__PURE__ */ jsx3(Translate, { offset: { x: x + 0.25 / 2, y, z: z42 }, children: /* @__PURE__ */ jsx3(Rotate, { rotation: ["-90deg", 0, "90deg"], children: /* @__PURE__ */ jsx3(ExtrudeLinear, { height: 0.25, children: /* @__PURE__ */ jsx3(
30854
+ /* @__PURE__ */ jsx3(Translate, { offset: { x: x + 0.25 / 2, y, z: z27 }, children: /* @__PURE__ */ jsx3(Rotate, { rotation: ["-90deg", 0, "90deg"], children: /* @__PURE__ */ jsx3(ExtrudeLinear, { height: 0.25, children: /* @__PURE__ */ jsx3(
29430
30855
  Polygon,
29431
30856
  {
29432
30857
  points: svgPathPoints.slice().reverse().map((p) => [p.x, p.y])
@@ -29438,7 +30863,7 @@ var DipPinLeg = ({ x, y, z: z42 }) => {
29438
30863
  offset: {
29439
30864
  x,
29440
30865
  y: y + (isRotated ? 1 : -1),
29441
- z: z42
30866
+ z: z27
29442
30867
  },
29443
30868
  children: /* @__PURE__ */ jsx3(Rotate, { rotation: ["-90deg", "90deg", isRotated ? "180deg" : "0deg"], children: /* @__PURE__ */ jsx3(ExtrudeLinear, { height: 2, children: /* @__PURE__ */ jsx3(
29444
30869
  Polygon,
@@ -29723,6 +31148,64 @@ var A0603 = ({ color = "#333" }) => {
29723
31148
  )
29724
31149
  ] });
29725
31150
  };
31151
+ var smdLedDimensions = {
31152
+ "0402": { length: 1, width: 0.5, height: 0.5, terminalLength: 0.2 },
31153
+ "0603": { length: 1.62, width: 0.8, height: 0.615, terminalLength: 0.21 },
31154
+ "0805": { length: 2, width: 1.25, height: 0.75, terminalLength: 0.35 }
31155
+ };
31156
+ function SmdLED({
31157
+ footprint,
31158
+ color = "#ffe8a0"
31159
+ }) {
31160
+ const p = smdLedDimensions[footprint];
31161
+ if (footprint === "0603")
31162
+ return /* @__PURE__ */ jsxs(Fragment2, { children: [
31163
+ /* @__PURE__ */ jsx3(Colorize, { color: "#f0eee7", children: /* @__PURE__ */ jsx3(
31164
+ RoundedCuboid,
31165
+ {
31166
+ size: [1.2, 0.79, 0.6],
31167
+ roundRadius: 0.02,
31168
+ center: [0, 0, 0.31]
31169
+ }
31170
+ ) }),
31171
+ /* @__PURE__ */ jsx3(Colorize, { color: "#c7c9ca", children: [-1, 1].map((sign) => /* @__PURE__ */ jsx3(
31172
+ Cuboid,
31173
+ {
31174
+ size: [0.21, 0.8, 0.22],
31175
+ center: [sign * 0.705, 0, 0.11]
31176
+ },
31177
+ sign
31178
+ )) }),
31179
+ /* @__PURE__ */ jsx3(Colorize, { color, children: /* @__PURE__ */ jsx3(Cuboid, { size: [0.72, 0.52, 0.01], center: [0, 0, 0.61] }) })
31180
+ ] });
31181
+ const terminalThickness = Math.min(0.1, p.height / 4);
31182
+ const apertureHeight = 0.02;
31183
+ return /* @__PURE__ */ jsxs(Fragment2, { children: [
31184
+ /* @__PURE__ */ jsx3(Colorize, { color: "#f0eee7", children: /* @__PURE__ */ jsx3(Translate, { z: (p.height + terminalThickness - apertureHeight) / 2, children: /* @__PURE__ */ jsx3(
31185
+ Cuboid,
31186
+ {
31187
+ size: [
31188
+ p.length,
31189
+ p.width,
31190
+ p.height - terminalThickness - apertureHeight
31191
+ ]
31192
+ }
31193
+ ) }) }),
31194
+ /* @__PURE__ */ jsx3(Colorize, { color: "#c7c9ca", children: [-1, 1].map((sign) => /* @__PURE__ */ jsx3(
31195
+ Translate,
31196
+ {
31197
+ offset: [
31198
+ sign * (p.length - p.terminalLength) / 2,
31199
+ 0,
31200
+ terminalThickness / 2
31201
+ ],
31202
+ children: /* @__PURE__ */ jsx3(Cuboid, { size: [p.terminalLength, p.width, terminalThickness] })
31203
+ },
31204
+ sign
31205
+ )) }),
31206
+ /* @__PURE__ */ jsx3(Colorize, { color, children: /* @__PURE__ */ jsx3(Translate, { z: p.height - apertureHeight / 2, children: /* @__PURE__ */ jsx3(Cuboid, { size: [p.length * 0.45, p.width * 0.65, apertureHeight] }) }) })
31207
+ ] });
31208
+ }
29726
31209
  var fullLength3 = 2;
29727
31210
  var width3 = 1.25;
29728
31211
  var height3 = 0.55;
@@ -30012,7 +31495,7 @@ var PinRow = ({
30012
31495
  const xoff = -((pinsPerRow - 1) / 2) * pitch;
30013
31496
  const throughHole = !smd && !rightangle;
30014
31497
  const flipped = throughHole ? !invert : Boolean(invert);
30015
- const flipZ = (z42) => flipped ? -z42 + bodyHeight : z42;
31498
+ const flipZ = (z27) => flipped ? -z27 + bodyHeight : z27;
30016
31499
  return /* @__PURE__ */ jsx3(Fragment2, { children: Array.from({ length: numberOfPins }, (_, i) => {
30017
31500
  const row = Math.floor(i / pinsPerRow);
30018
31501
  const col = i % pinsPerRow;
@@ -30743,7 +32226,7 @@ var A2512 = ({ color = "#333" }) => {
30743
32226
  var FemaleHeader = ({
30744
32227
  x,
30745
32228
  y,
30746
- z: z42 = 0,
32229
+ z: z27 = 0,
30747
32230
  pitch = 2.54,
30748
32231
  legsLength = 3,
30749
32232
  innerDiameter = 0.945,
@@ -30758,8 +32241,8 @@ var FemaleHeader = ({
30758
32241
  const socketEntryWidth = socketWidth * 1.8;
30759
32242
  const socketEntryHeight = Math.min(bodyHeight * 0.18, pitch * 0.24);
30760
32243
  const socketDepth = bodyHeight + 0.1;
30761
- const socketCenterZ = flipZ(z42 + socketDepth / 2);
30762
- const socketEntryBaseZ = z42 + bodyHeight - socketEntryHeight;
32244
+ const socketCenterZ = flipZ(z27 + socketDepth / 2);
32245
+ const socketEntryBaseZ = z27 + bodyHeight - socketEntryHeight;
30763
32246
  const gapWidth = pinThickness * 1.6;
30764
32247
  return /* @__PURE__ */ jsxs(Fragment2, { children: [
30765
32248
  /* @__PURE__ */ jsx3(Colorize, { color: "#1a1a1a", children: /* @__PURE__ */ jsxs(Subtract, { children: [
@@ -30768,7 +32251,7 @@ var FemaleHeader = ({
30768
32251
  {
30769
32252
  color: "#000",
30770
32253
  size: [bodyLength10, bodyWidth, bodyHeight],
30771
- center: [x, y, flipZ(z42 + bodyHeight / 2)]
32254
+ center: [x, y, flipZ(z27 + bodyHeight / 2)]
30772
32255
  }
30773
32256
  ),
30774
32257
  /* @__PURE__ */ jsx3(
@@ -30790,7 +32273,7 @@ var FemaleHeader = ({
30790
32273
  Cuboid,
30791
32274
  {
30792
32275
  size: [socketEntryWidth, socketEntryWidth, 0.01],
30793
- center: [x, y, flipZ(z42 + bodyHeight)]
32276
+ center: [x, y, flipZ(z27 + bodyHeight)]
30794
32277
  }
30795
32278
  )
30796
32279
  ] })
@@ -30802,7 +32285,7 @@ var FemaleHeader = ({
30802
32285
  {
30803
32286
  color: "silver",
30804
32287
  size: [pinThickness, pinThickness, legsLength * 0.9],
30805
- center: [x, y, flipZ(z42 + -legsLength / 2 * 0.9)]
32288
+ center: [x, y, flipZ(z27 + -legsLength / 2 * 0.9)]
30806
32289
  }
30807
32290
  ),
30808
32291
  /* @__PURE__ */ jsx3(
@@ -30810,7 +32293,7 @@ var FemaleHeader = ({
30810
32293
  {
30811
32294
  color: "silver",
30812
32295
  size: [pinThickness / 1.8, pinThickness / 1.8, legsLength],
30813
- center: [x, y, flipZ(z42 + -legsLength / 2)]
32296
+ center: [x, y, flipZ(z27 + -legsLength / 2)]
30814
32297
  }
30815
32298
  )
30816
32299
  ] }),
@@ -30819,7 +32302,7 @@ var FemaleHeader = ({
30819
32302
  {
30820
32303
  color: "silver",
30821
32304
  size: [gapWidth, gapWidth, gapWidth * 0.5],
30822
- center: [x, y, flipZ(z42 + gapWidth / 2 * 0.5)]
32305
+ center: [x, y, flipZ(z27 + gapWidth / 2 * 0.5)]
30823
32306
  }
30824
32307
  )
30825
32308
  ] })
@@ -30837,7 +32320,7 @@ var FemaleHeaderRow = ({
30837
32320
  const pinsPerRow = Math.ceil(numberOfPins / rows);
30838
32321
  const rowSpacing = 2.54;
30839
32322
  const xoff = -((pinsPerRow - 1) / 2) * pitch;
30840
- const flipZ = (z42) => invert ? -z42 + bodyHeight : z42;
32323
+ const flipZ = (z27) => invert ? -z27 + bodyHeight : z27;
30841
32324
  return /* @__PURE__ */ jsx3(Fragment2, { children: Array.from({ length: numberOfPins }, (_, i) => {
30842
32325
  const row = Math.floor(i / pinsPerRow);
30843
32326
  const col = i % pinsPerRow;
@@ -32227,13 +33710,13 @@ function createPhysicalLqfp(p) {
32227
33710
  ]);
32228
33711
  }
32229
33712
  points.push([root, midZ]);
32230
- const section = ([x, z42]) => /* @__PURE__ */ jsx3(
33713
+ const section = ([x, z27]) => /* @__PURE__ */ jsx3(
32231
33714
  Translate,
32232
33715
  {
32233
33716
  offset: {
32234
33717
  x: horizontal ? sign * x : along,
32235
33718
  y: horizontal ? along : sign * x,
32236
- z: z42
33719
+ z: z27
32237
33720
  },
32238
33721
  children: /* @__PURE__ */ jsx3(
32239
33722
  Cuboid,
@@ -34064,7 +35547,7 @@ var MountedPcbModule = ({
34064
35547
  shortSidePinLength,
34065
35548
  longSidePinLength,
34066
35549
  bodyHeight: pinBodyHeight,
34067
- flipZ: (z42) => z42
35550
+ flipZ: (z27) => z27
34068
35551
  },
34069
35552
  `pin-3d-${index2}`
34070
35553
  ));
@@ -34073,7 +35556,7 @@ var MountedPcbModule = ({
34073
35556
  {
34074
35557
  x: pin.x,
34075
35558
  y: pin.y,
34076
- flipZ: (z42) => -z42
35559
+ flipZ: (z27) => -z27
34077
35560
  },
34078
35561
  `female-pin-3d-${index2}`
34079
35562
  ));
@@ -34603,7 +36086,7 @@ function isJstShFootprint(footprint) {
34603
36086
  const p = fp.string(footprint).json();
34604
36087
  if (p.fn !== "jst") return false;
34605
36088
  return Boolean(
34606
- p.sh || p.smd && Math.abs(mm(p.p) - 1) < 0.01 && Math.abs(mm(p.mpx ?? 0) - (p.num_pins - 1 + 2.6)) < 0.15 && Math.abs(mm(p.mpy ?? 0) - 2.525) < 0.15
36089
+ p.sh || p.smd && Math.abs(mm3(p.p) - 1) < 0.01 && Math.abs(mm3(p.mpx ?? 0) - (p.num_pins - 1 + 2.6)) < 0.15 && Math.abs(mm3(p.mpy ?? 0) - 2.525) < 0.15
34607
36090
  );
34608
36091
  }
34609
36092
  var JstSh = ({ footprint = "jst6_sh" }) => {
@@ -34724,7 +36207,7 @@ var getRoundedRectProfile = ({
34724
36207
  length: length83,
34725
36208
  radius,
34726
36209
  height: height10,
34727
- z: z42
36210
+ z: z27
34728
36211
  }) => {
34729
36212
  const x = width10 / 2 - radius;
34730
36213
  const y = length83 / 2 - radius;
@@ -34736,11 +36219,11 @@ var getRoundedRectProfile = ({
34736
36219
  ].map(([cornerX, cornerY], index2) => /* @__PURE__ */ jsx3(
34737
36220
  Cylinder,
34738
36221
  {
34739
- center: [cornerX, cornerY, z42 + height10 / 2],
36222
+ center: [cornerX, cornerY, z27 + height10 / 2],
34740
36223
  height: height10,
34741
36224
  radius
34742
36225
  },
34743
- `${z42}-${index2}`
36226
+ `${z27}-${index2}`
34744
36227
  ));
34745
36228
  };
34746
36229
  var Crystal = ({
@@ -36718,6 +38201,18 @@ var Footprinter3d = ({ footprint }) => {
36718
38201
  if (mp.getModelNames().includes(modelFn)) {
36719
38202
  const model = mp.string(footprint).json();
36720
38203
  switch (model.fn) {
38204
+ case "nema": {
38205
+ const { fn, ...props } = model;
38206
+ return /* @__PURE__ */ jsx3(NemaMotor, { ...props });
38207
+ }
38208
+ case "hexsocketbolt": {
38209
+ const { fn, ...props } = model;
38210
+ return /* @__PURE__ */ jsx3(HexSocketBolt, { ...props });
38211
+ }
38212
+ case "sheetmetal": {
38213
+ const { fn, ...props } = model;
38214
+ return /* @__PURE__ */ jsx3(SheetMetal, { ...props });
38215
+ }
36721
38216
  case "flexscreen": {
36722
38217
  const { fn: _, ...flexScreenProps } = model;
36723
38218
  return /* @__PURE__ */ jsx3(FlexScreen, { ...flexScreenProps });
@@ -36743,7 +38238,7 @@ var Footprinter3d = ({ footprint }) => {
36743
38238
  const color = colorMatch ? colorMatch[1] : void 0;
36744
38239
  const dim = (value, fallback) => {
36745
38240
  if (value === void 0 || value === null) return fallback;
36746
- const parsed = mm(value);
38241
+ const parsed = mm3(value);
36747
38242
  return Number.isFinite(parsed) ? parsed : fallback;
36748
38243
  };
36749
38244
  const bodyModel = renderFootprinterBodyModel(fpJson);
@@ -36848,7 +38343,8 @@ var Footprinter3d = ({ footprint }) => {
36848
38343
  }
36849
38344
  );
36850
38345
  }
36851
- case "pinrow": {
38346
+ case "pinrow":
38347
+ case "headermodule": {
36852
38348
  const rowsMatch = footprint.match(/_rows(\d+)/);
36853
38349
  const rows = rowsMatch && rowsMatch[1] ? parseInt(rowsMatch[1], 10) : 1;
36854
38350
  if (fpJson.male)
@@ -36884,6 +38380,12 @@ var Footprinter3d = ({ footprint }) => {
36884
38380
  );
36885
38381
  case "led5050":
36886
38382
  return /* @__PURE__ */ jsx3(Led5050, { color });
38383
+ case "led": {
38384
+ const imperial = String(fpJson.imperial);
38385
+ if (imperial === "0402" || imperial === "0603" || imperial === "0805")
38386
+ return /* @__PURE__ */ jsx3(SmdLED, { footprint: imperial, color });
38387
+ break;
38388
+ }
36887
38389
  case "cap": {
36888
38390
  switch (fpJson.imperial) {
36889
38391
  case "0402":
@@ -37361,8 +38863,8 @@ var Footprinter3d = ({ footprint }) => {
37361
38863
  return /* @__PURE__ */ jsx3(A2512, { color });
37362
38864
  }
37363
38865
  if ((fpJson.fn === "res" || fpJson.fn === "cap") && fpJson.p !== void 0 && fpJson.ph !== void 0) {
37364
- const padPitch = mm(fpJson.p);
37365
- const padHeight = mm(fpJson.ph);
38866
+ const padPitch = mm3(fpJson.p);
38867
+ const padHeight = mm3(fpJson.ph);
37366
38868
  if (Number.isFinite(padPitch) && Number.isFinite(padHeight)) {
37367
38869
  return /* @__PURE__ */ jsx3(
37368
38870
  ParametricChip,
@@ -37452,6 +38954,9 @@ function renderNode(node, colorCtx, renderCtx) {
37452
38954
  else geom = hulls.hull(geoms);
37453
38955
  return [{ geom, color: colorCtx }];
37454
38956
  }
38957
+ if (type === Custom) {
38958
+ return [{ geom: props.geometry, color: colorCtx }];
38959
+ }
37455
38960
  if (type === Polygon) {
37456
38961
  const points = props?.points ?? [];
37457
38962
  const g2 = geometries.geom2.fromPoints(points);
@@ -37512,8 +39017,8 @@ function renderNode(node, colorCtx, renderCtx) {
37512
39017
  }
37513
39018
  return (children ?? []).flatMap((c) => renderNode(c, colorCtx, renderCtx));
37514
39019
  }
37515
- function render(root, jscad3) {
37516
- const geometries = renderNode(root, void 0, { jscad: jscad3 });
39020
+ function render(root, jscad32) {
39021
+ const geometries = renderNode(root, void 0, { jscad: jscad32 });
37517
39022
  return { geometries };
37518
39023
  }
37519
39024
  function convertCSGToThreeGeom(csg) {
@@ -37592,9 +39097,9 @@ function convertCSGToThreeGeom(csg) {
37592
39097
  console.error("Invalid CSG object: neither polygons nor sides found");
37593
39098
  return new BufferGeometry();
37594
39099
  }
37595
- function getJscadModelForFootprint(footprint, jscad3) {
39100
+ function getJscadModelForFootprint(footprint, jscad32) {
37596
39101
  const vnode = h(Footprinter3d, { footprint });
37597
- return render(vnode, jscad3);
39102
+ return render(vnode, jscad32);
37598
39103
  }
37599
39104
 
37600
39105
  // src/three-components/FootprinterModel.tsx
@@ -38197,7 +39702,7 @@ function GltfModel({
38197
39702
 
38198
39703
  // src/three-components/JscadModel.tsx
38199
39704
  var import_jscad_planner = __toESM(require_dist(), 1);
38200
- var import_modeling = __toESM(require_src(), 1);
39705
+ var import_modeling3 = __toESM(require_src(), 1);
38201
39706
  import * as THREE11 from "three";
38202
39707
  import { useState as useState6, useEffect as useEffect9 } from "react";
38203
39708
  import { jsx as jsx8 } from "react/jsx-runtime";
@@ -38218,7 +39723,7 @@ var JscadModel = ({
38218
39723
  }) => {
38219
39724
  const [mesh, setMesh] = useState6(null);
38220
39725
  useEffect9(() => {
38221
- const jscadObject = (0, import_jscad_planner.executeJscadOperations)(import_modeling.default, jscadPlan);
39726
+ const jscadObject = (0, import_jscad_planner.executeJscadOperations)(import_modeling3.default, jscadPlan);
38222
39727
  if (!jscadObject || !jscadObject.polygons && !jscadObject.sides) {
38223
39728
  setMesh(null);
38224
39729
  return;
@@ -38597,12 +40102,12 @@ async function convertStepUrlToGlb(stepUrl) {
38597
40102
  }
38598
40103
  const group = occtMeshesToGroup(result.meshes);
38599
40104
  const exporter = new GLTFExporter();
38600
- const glb = await new Promise((resolve, reject) => {
40105
+ const glb = await new Promise((resolve2, reject) => {
38601
40106
  exporter.parse(
38602
40107
  group,
38603
40108
  (output) => {
38604
40109
  if (output instanceof ArrayBuffer) {
38605
- resolve(output);
40110
+ resolve2(output);
38606
40111
  } else {
38607
40112
  reject(new Error("GLTFExporter did not return binary output"));
38608
40113
  }
@@ -38782,9 +40287,9 @@ var StepModel = ({
38782
40287
  // src/utils/cad-model-loader-transform.ts
38783
40288
  import * as THREE13 from "three";
38784
40289
  function applyCoordinateTransform(point, config) {
38785
- let { x, y, z: z42 } = point;
40290
+ let { x, y, z: z27 } = point;
38786
40291
  if (config.axisMapping) {
38787
- const original = { x, y, z: z42 };
40292
+ const original = { x, y, z: z27 };
38788
40293
  if (config.axisMapping.x) {
38789
40294
  x = getAxisValue(original, config.axisMapping.x);
38790
40295
  }
@@ -38792,30 +40297,30 @@ function applyCoordinateTransform(point, config) {
38792
40297
  y = getAxisValue(original, config.axisMapping.y);
38793
40298
  }
38794
40299
  if (config.axisMapping.z) {
38795
- z42 = getAxisValue(original, config.axisMapping.z);
40300
+ z27 = getAxisValue(original, config.axisMapping.z);
38796
40301
  }
38797
40302
  }
38798
40303
  x *= config.flipX ?? 1;
38799
40304
  y *= config.flipY ?? 1;
38800
- z42 *= config.flipZ ?? 1;
40305
+ z27 *= config.flipZ ?? 1;
38801
40306
  if (config.rotation) {
38802
40307
  if (config.rotation.x) {
38803
40308
  const rad = config.rotation.x * Math.PI / 180;
38804
40309
  const cos = Math.cos(rad);
38805
40310
  const sin = Math.sin(rad);
38806
- const newY = y * cos - z42 * sin;
38807
- const newZ = y * sin + z42 * cos;
40311
+ const newY = y * cos - z27 * sin;
40312
+ const newZ = y * sin + z27 * cos;
38808
40313
  y = newY;
38809
- z42 = newZ;
40314
+ z27 = newZ;
38810
40315
  }
38811
40316
  if (config.rotation.y) {
38812
40317
  const rad = config.rotation.y * Math.PI / 180;
38813
40318
  const cos = Math.cos(rad);
38814
40319
  const sin = Math.sin(rad);
38815
- const newX = x * cos + z42 * sin;
38816
- const newZ = -x * sin + z42 * cos;
40320
+ const newX = x * cos + z27 * sin;
40321
+ const newZ = -x * sin + z27 * cos;
38817
40322
  x = newX;
38818
- z42 = newZ;
40323
+ z27 = newZ;
38819
40324
  }
38820
40325
  if (config.rotation.z) {
38821
40326
  const rad = config.rotation.z * Math.PI / 180;
@@ -38827,7 +40332,7 @@ function applyCoordinateTransform(point, config) {
38827
40332
  y = newY;
38828
40333
  }
38829
40334
  }
38830
- return { x, y, z: z42 };
40335
+ return { x, y, z: z27 };
38831
40336
  }
38832
40337
  function getAxisValue(original, mapping) {
38833
40338
  switch (mapping) {
@@ -39383,7 +40888,7 @@ import * as THREE25 from "three";
39383
40888
  // package.json
39384
40889
  var package_default = {
39385
40890
  name: "@tscircuit/3d-viewer",
39386
- version: "0.0.610",
40891
+ version: "0.0.611",
39387
40892
  repository: {
39388
40893
  type: "git",
39389
40894
  url: "https://github.com/tscircuit/3d-viewer"
@@ -39459,7 +40964,7 @@ var package_default = {
39459
40964
  "bun-match-svg": "^0.0.9",
39460
40965
  "bun-types": "1.2.1",
39461
40966
  debug: "^4.4.0",
39462
- "jscad-electronics": "^0.0.178",
40967
+ "jscad-electronics": "^0.0.182",
39463
40968
  "jscad-planner": "^0.0.13",
39464
40969
  jsdom: "^26.0.0",
39465
40970
  "manifold-3d": "^3.2.1",
@@ -39472,11 +40977,14 @@ var package_default = {
39472
40977
  vite: "^7.1.5",
39473
40978
  "vite-tsconfig-paths": "^4.3.2",
39474
40979
  "circuit-json-to-gltf": "0.0.129",
39475
- modelprinter: "https://jscdn.tscircuit.com/@tscircuit/modelprinter/0.0.4.tgz",
39476
- zod: "^3.25.67"
40980
+ zod: "^3.25.67",
40981
+ "@tscircuit/modelprinter": "^0.0.4"
39477
40982
  },
39478
40983
  patchedDependencies: {
39479
40984
  "@tscircuit/fanout-solver@0.0.78": "patches/@tscircuit%2Ffanout-solver@0.0.78.patch"
40985
+ },
40986
+ engines: {
40987
+ node: "24.x"
39480
40988
  }
39481
40989
  };
39482
40990
 
@@ -39587,11 +41095,11 @@ var CameraControllerProvider = ({ children, defaultTarget, initialCameraPosition
39587
41095
  new THREE15.Euler(0, 0, 0)
39588
41096
  );
39589
41097
  const baseDistance = useMemo11(() => {
39590
- const [x, y, z42] = initialCameraPosition ?? [5, -5, 5];
41098
+ const [x, y, z27] = initialCameraPosition ?? [5, -5, 5];
39591
41099
  const distance6 = Math.hypot(
39592
41100
  x - defaultTarget.x,
39593
41101
  y - defaultTarget.y,
39594
- z42 - defaultTarget.z
41102
+ z27 - defaultTarget.z
39595
41103
  );
39596
41104
  return distance6 > 0 ? distance6 : 5;
39597
41105
  }, [initialCameraPosition, defaultTarget]);
@@ -40640,37 +42148,37 @@ var createRoundedRectangleShape = (width10, height10, radius) => {
40640
42148
  const halfWidth = width10 / 2;
40641
42149
  const halfHeight = height10 / 2;
40642
42150
  const safeRadius = Math.min(radius, halfWidth, halfHeight);
40643
- const shape = new THREE23.Shape();
40644
- shape.moveTo(-halfWidth + safeRadius, -halfHeight);
40645
- shape.lineTo(halfWidth - safeRadius, -halfHeight);
40646
- shape.quadraticCurveTo(
42151
+ const shape2 = new THREE23.Shape();
42152
+ shape2.moveTo(-halfWidth + safeRadius, -halfHeight);
42153
+ shape2.lineTo(halfWidth - safeRadius, -halfHeight);
42154
+ shape2.quadraticCurveTo(
40647
42155
  halfWidth,
40648
42156
  -halfHeight,
40649
42157
  halfWidth,
40650
42158
  -halfHeight + safeRadius
40651
42159
  );
40652
- shape.lineTo(halfWidth, halfHeight - safeRadius);
40653
- shape.quadraticCurveTo(
42160
+ shape2.lineTo(halfWidth, halfHeight - safeRadius);
42161
+ shape2.quadraticCurveTo(
40654
42162
  halfWidth,
40655
42163
  halfHeight,
40656
42164
  halfWidth - safeRadius,
40657
42165
  halfHeight
40658
42166
  );
40659
- shape.lineTo(-halfWidth + safeRadius, halfHeight);
40660
- shape.quadraticCurveTo(
42167
+ shape2.lineTo(-halfWidth + safeRadius, halfHeight);
42168
+ shape2.quadraticCurveTo(
40661
42169
  -halfWidth,
40662
42170
  halfHeight,
40663
42171
  -halfWidth,
40664
42172
  halfHeight - safeRadius
40665
42173
  );
40666
- shape.lineTo(-halfWidth, -halfHeight + safeRadius);
40667
- shape.quadraticCurveTo(
42174
+ shape2.lineTo(-halfWidth, -halfHeight + safeRadius);
42175
+ shape2.quadraticCurveTo(
40668
42176
  -halfWidth,
40669
42177
  -halfHeight,
40670
42178
  -halfWidth + safeRadius,
40671
42179
  -halfHeight
40672
42180
  );
40673
- return shape;
42181
+ return shape2;
40674
42182
  };
40675
42183
  var createRoundedPrismGeometry = (width10, height10, depth, radius) => {
40676
42184
  return createPrismGeometryFromShape(
@@ -40678,8 +42186,8 @@ var createRoundedPrismGeometry = (width10, height10, depth, radius) => {
40678
42186
  depth
40679
42187
  );
40680
42188
  };
40681
- var createPrismGeometryFromShape = (shape, depth) => {
40682
- const geometry = new THREE23.ExtrudeGeometry(shape, {
42189
+ var createPrismGeometryFromShape = (shape2, depth) => {
42190
+ const geometry = new THREE23.ExtrudeGeometry(shape2, {
40683
42191
  depth,
40684
42192
  bevelEnabled: false,
40685
42193
  curveSegments: 24
@@ -41292,11 +42800,11 @@ var createBoardGeomWithOutline = (board, depth = 1.2, options = {}) => {
41292
42800
  if (arePointsClockwise(outlineVec2)) {
41293
42801
  outlineVec2 = outlineVec2.reverse();
41294
42802
  }
41295
- let shape = (0, import_primitives.polygon)({ points: outlineVec2 });
42803
+ let shape2 = (0, import_primitives.polygon)({ points: outlineVec2 });
41296
42804
  if (xyOutset !== 0) {
41297
- shape = (0, import_expansions.expand)({ delta: xyOutset, corners: "edge" }, shape);
42805
+ shape2 = (0, import_expansions.expand)({ delta: xyOutset, corners: "edge" }, shape2);
41298
42806
  }
41299
- let boardGeom = (0, import_extrusions.extrudeLinear)({ height: depth }, shape);
42807
+ let boardGeom = (0, import_extrusions.extrudeLinear)({ height: depth }, shape2);
41300
42808
  boardGeom = (0, import_transforms.translate)([0, 0, -depth / 2], boardGeom);
41301
42809
  return boardGeom;
41302
42810
  };
@@ -41619,19 +43127,19 @@ var platedHole = (plated_hole, ctx, options = {}) => {
41619
43127
  const holeWidth = plated_hole.hole_width || 0;
41620
43128
  const holeHeight = plated_hole.hole_height || 0;
41621
43129
  const copperBody = (() => {
41622
- const circle = (0, import_primitives4.cylinder)({
43130
+ const circle2 = (0, import_primitives4.cylinder)({
41623
43131
  center: [0, 0, 0],
41624
43132
  radius: 1,
41625
43133
  height: copperFillHeight,
41626
43134
  segments: 64
41627
43135
  // High segment count for smooth ellipse
41628
43136
  });
41629
- const scaled = (0, import_transforms3.scale)([outerWidth / 2, outerHeight / 2, 1], circle);
43137
+ const scaled = (0, import_transforms3.scale)([outerWidth / 2, outerHeight / 2, 1], circle2);
41630
43138
  return (0, import_transforms4.translate)([plated_hole.x, plated_hole.y, 0], scaled);
41631
43139
  })();
41632
43140
  const copperSolid = maybeClip(copperBody, clipGeom);
41633
43141
  const drill = (() => {
41634
- const circle = (0, import_primitives4.cylinder)({
43142
+ const circle2 = (0, import_primitives4.cylinder)({
41635
43143
  center: [0, 0, 0],
41636
43144
  radius: 1,
41637
43145
  height: throughDrillHeight,
@@ -41640,7 +43148,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
41640
43148
  });
41641
43149
  const scaled = (0, import_transforms3.scale)(
41642
43150
  [Math.max(holeWidth / 2, 0.01), Math.max(holeHeight / 2, 0.01), 1],
41643
- circle
43151
+ circle2
41644
43152
  );
41645
43153
  return (0, import_transforms4.translate)([plated_hole.x, plated_hole.y, 0], scaled);
41646
43154
  })();
@@ -42732,7 +44240,7 @@ var useBoardGeomBuilder = (circuitJson) => {
42732
44240
  while (!isDone && !isCancelled) {
42733
44241
  isDone = builder.step(1);
42734
44242
  if (!isDone) {
42735
- await new Promise((resolve) => setTimeout(resolve, 0));
44243
+ await new Promise((resolve2) => setTimeout(resolve2, 0));
42736
44244
  }
42737
44245
  }
42738
44246
  if (!isCancelled) {
@@ -45619,524 +47127,6 @@ var CadViewerJscad = forwardRef3(
45619
47127
  }
45620
47128
  );
45621
47129
 
45622
- // node_modules/earcut/src/earcut.js
45623
- var steiners = /* @__PURE__ */ new Set();
45624
- var filteredOut = false;
45625
- function earcut(data, holeIndices, dim = 2) {
45626
- const hasHoles = holeIndices && holeIndices.length;
45627
- const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
45628
- if (steiners.size) steiners.clear();
45629
- let outerNode = linkedList(data, 0, outerLen, dim, true);
45630
- const triangles = [];
45631
- if (!outerNode || outerNode.next === outerNode.prev) return triangles;
45632
- let minX = 0, minY = 0, invSize = 0;
45633
- if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
45634
- if (data.length > 80 * dim) {
45635
- minX = data[0];
45636
- minY = data[1];
45637
- let maxX = minX;
45638
- let maxY = minY;
45639
- for (let i = dim; i < outerLen; i += dim) {
45640
- const x = data[i];
45641
- const y = data[i + 1];
45642
- if (x < minX) minX = x;
45643
- if (y < minY) minY = y;
45644
- if (x > maxX) maxX = x;
45645
- if (y > maxY) maxY = y;
45646
- }
45647
- invSize = Math.max(maxX - minX, maxY - minY);
45648
- invSize = invSize !== 0 ? 32767 / invSize : 0;
45649
- }
45650
- earcutLinked(outerNode, triangles, minX, minY, invSize);
45651
- return triangles;
45652
- }
45653
- function linkedList(data, start, end, dim, clockwise) {
45654
- let last = null;
45655
- if (clockwise === signedArea(data, start, end, dim) > 0) {
45656
- for (let i = start; i < end; i += dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);
45657
- } else {
45658
- for (let i = end - dim; i >= start; i -= dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);
45659
- }
45660
- if (last && equals(last, last.next)) {
45661
- removeNode(last);
45662
- last = last.next;
45663
- }
45664
- return last;
45665
- }
45666
- function filterPoints(start, end = start) {
45667
- const full = end === start;
45668
- let p = start, again;
45669
- do {
45670
- again = false;
45671
- if (p !== p.next && (steiners.size === 0 || !steiners.has(p)) && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
45672
- if (full || p === end) end = p.prev;
45673
- filteredOut = true;
45674
- removeNode(p);
45675
- p = p.prev;
45676
- again = true;
45677
- } else if (full || p !== end) {
45678
- p = p.next;
45679
- again = !full;
45680
- }
45681
- } while (again || p !== end);
45682
- return end;
45683
- }
45684
- function earcutLinked(ear, triangles, minX, minY, invSize) {
45685
- if (invSize) indexCurve(ear, minX, minY, invSize);
45686
- let stop = ear, cured = false;
45687
- while (ear.prev !== ear.next) {
45688
- const prev = ear.prev;
45689
- const next = ear.next;
45690
- if (area(prev, ear, next) < 0 && (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear))) {
45691
- triangles.push(prev.i, ear.i, next.i);
45692
- removeNode(ear);
45693
- ear = next;
45694
- stop = next;
45695
- continue;
45696
- }
45697
- ear = next;
45698
- if (ear === stop) {
45699
- filteredOut = false;
45700
- ear = filterPoints(ear);
45701
- if (filteredOut) {
45702
- stop = ear;
45703
- continue;
45704
- }
45705
- if (!cured) {
45706
- ear = cureLocalIntersections(ear, triangles);
45707
- stop = ear;
45708
- cured = true;
45709
- continue;
45710
- }
45711
- splitEarcut(ear, triangles, minX, minY, invSize);
45712
- break;
45713
- }
45714
- }
45715
- }
45716
- function isEar(ear) {
45717
- const a = ear.prev, b = ear, c = ear.next, ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y, x0 = Math.min(ax, bx, cx), y0 = Math.min(ay, by, cy), x1 = Math.max(ax, bx, cx), y1 = Math.max(ay, by, cy);
45718
- let p = c.next;
45719
- while (p !== a) {
45720
- if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && !(ax === p.x && ay === p.y) && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
45721
- p = p.next;
45722
- }
45723
- return true;
45724
- }
45725
- function isEarHashed(ear, minX, minY, invSize) {
45726
- const a = ear.prev, b = ear, c = ear.next, ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y, x0 = Math.min(ax, bx, cx), y0 = Math.min(ay, by, cy), x1 = Math.max(ax, bx, cx), y1 = Math.max(ay, by, cy), minZ = zOrder(x0, y0, minX, minY, invSize), maxZ = zOrder(x1, y1, minX, minY, invSize);
45727
- let p = ear.prevZ;
45728
- while (p && p.z >= minZ) {
45729
- if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== c && !(ax === p.x && ay === p.y) && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
45730
- p = p.prevZ;
45731
- }
45732
- let n = ear.nextZ;
45733
- while (n && n.z <= maxZ) {
45734
- if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== c && !(ax === n.x && ay === n.y) && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
45735
- n = n.nextZ;
45736
- }
45737
- return true;
45738
- }
45739
- function cureLocalIntersections(start, triangles) {
45740
- let p = start;
45741
- let cured = false;
45742
- do {
45743
- const a = p.prev, b = p.next.next;
45744
- if (intersects(a, p, p.next, b, false) && locallyInside(a, b) && locallyInside(b, a)) {
45745
- triangles.push(a.i, p.i, b.i);
45746
- removeNode(p);
45747
- removeNode(p.next);
45748
- p = start = b;
45749
- cured = true;
45750
- }
45751
- p = p.next;
45752
- } while (p !== start);
45753
- return cured ? filterPoints(p) : p;
45754
- }
45755
- function splitEarcut(start, triangles, minX, minY, invSize) {
45756
- let a = start;
45757
- do {
45758
- let b = a.next.next;
45759
- while (b !== a.prev) {
45760
- if (a.i !== b.i && isValidDiagonal(a, b)) {
45761
- let c = splitPolygon(a, b);
45762
- a = filterPoints(a, a.next);
45763
- c = filterPoints(c, c.next);
45764
- earcutLinked(a, triangles, minX, minY, invSize);
45765
- earcutLinked(c, triangles, minX, minY, invSize);
45766
- return;
45767
- }
45768
- b = b.next;
45769
- }
45770
- a = a.next;
45771
- } while (a !== start);
45772
- }
45773
- var indexActive = false;
45774
- function eliminateHoles(data, holeIndices, outerNode, dim) {
45775
- const queue = [];
45776
- for (let i = 0, len = holeIndices.length; i < len; i++) {
45777
- const start = holeIndices[i] * dim;
45778
- const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
45779
- const list = (
45780
- /** @type {Node} */
45781
- linkedList(data, start, end, dim, false)
45782
- );
45783
- if (list === list.next) steiners.add(list);
45784
- queue.push(getLeftmost(list));
45785
- }
45786
- queue.sort(compareXYSlope);
45787
- buildBlockIndex(data.length / dim, holeIndices.length);
45788
- indexSegment(outerNode, outerNode);
45789
- indexActive = true;
45790
- for (let i = 0; i < queue.length; i++) {
45791
- outerNode = eliminateHole(queue[i], outerNode);
45792
- }
45793
- indexActive = false;
45794
- return filterPoints(outerNode);
45795
- }
45796
- function compareXYSlope(a, b) {
45797
- return a.x - b.x || a.y - b.y || (a.next.y - a.y) / (a.next.x - a.x) - (b.next.y - b.y) / (b.next.x - b.x);
45798
- }
45799
- function eliminateHole(hole, outerNode) {
45800
- const bridge = findHoleBridge(hole, outerNode);
45801
- if (!bridge) {
45802
- return outerNode;
45803
- }
45804
- const bridgeReverse = splitPolygon(bridge, hole);
45805
- const bridge2 = bridgeReverse.next;
45806
- indexSegment(bridge, bridge2.next);
45807
- filterPoints(bridgeReverse, bridgeReverse.next);
45808
- return filterPoints(bridge, bridge.next);
45809
- }
45810
- var K = 16;
45811
- var blockBBox = new Float64Array(0);
45812
- var numBlocks = 0;
45813
- var blockHead = [];
45814
- var blockStop = [];
45815
- function buildBlockIndex(maxNodes, numHoles) {
45816
- const maxBlocks = Math.ceil((maxNodes + 2 * numHoles) / K) + numHoles + 2;
45817
- if (blockBBox.length < maxBlocks * 4) blockBBox = new Float64Array(maxBlocks * 4);
45818
- numBlocks = 0;
45819
- }
45820
- function indexSegment(head, stop) {
45821
- let p = head;
45822
- do {
45823
- const b = numBlocks++;
45824
- blockHead[b] = p;
45825
- let minX = p.x, minY = p.y, maxX = p.x, maxY = p.y;
45826
- let k = 0;
45827
- do {
45828
- const c = p.next;
45829
- p.z = b;
45830
- if (c.x < minX) minX = c.x;
45831
- if (c.x > maxX) maxX = c.x;
45832
- if (c.y < minY) minY = c.y;
45833
- if (c.y > maxY) maxY = c.y;
45834
- p = c;
45835
- } while (++k < K && p !== stop);
45836
- blockStop[b] = p;
45837
- const g = b * 4;
45838
- blockBBox[g] = minX;
45839
- blockBBox[g + 1] = minY;
45840
- blockBBox[g + 2] = maxX;
45841
- blockBBox[g + 3] = maxY;
45842
- } while (p !== stop);
45843
- }
45844
- function growBlock(head, tail) {
45845
- const g = head.z * 4;
45846
- if (tail.x < blockBBox[g]) blockBBox[g] = tail.x;
45847
- if (tail.y < blockBBox[g + 1]) blockBBox[g + 1] = tail.y;
45848
- if (tail.x > blockBBox[g + 2]) blockBBox[g + 2] = tail.x;
45849
- if (tail.y > blockBBox[g + 3]) blockBBox[g + 3] = tail.y;
45850
- }
45851
- function liveBlockStop(b) {
45852
- let stop = blockStop[b];
45853
- while (stop.prev.next !== stop) stop = stop.next;
45854
- blockStop[b] = stop;
45855
- return stop;
45856
- }
45857
- function liveBlockHead(b) {
45858
- let head = blockHead[b];
45859
- while (head.prev.next !== head) head = head.next;
45860
- blockHead[b] = head;
45861
- return head;
45862
- }
45863
- function findHoleBridge(hole, outerNode) {
45864
- let p = outerNode;
45865
- const hx = hole.x;
45866
- const hy = hole.y;
45867
- let qx = -Infinity;
45868
- let m;
45869
- if (equals(hole, p)) return p;
45870
- for (let b = 0, g = 0; b < numBlocks; b++, g += 4) {
45871
- if (hy < blockBBox[g + 1] || hy > blockBBox[g + 3] || blockBBox[g] > hx || blockBBox[g + 2] <= qx) continue;
45872
- const stop = liveBlockStop(b);
45873
- p = liveBlockHead(b);
45874
- do {
45875
- if (p.prev.next === p) {
45876
- if (equals(hole, p.next)) return p.next;
45877
- else if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
45878
- const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
45879
- if (x <= hx && x > qx) {
45880
- qx = x;
45881
- m = p.x < p.next.x ? p : p.next;
45882
- if (x === hx) return m;
45883
- }
45884
- }
45885
- }
45886
- p = p.next;
45887
- } while (p !== stop);
45888
- }
45889
- if (!m) return null;
45890
- const mx = m.x;
45891
- const my = m.y;
45892
- const tminY = Math.min(hy, my);
45893
- const tmaxY = Math.max(hy, my);
45894
- let tanMin = Infinity;
45895
- for (let b = 0, g = 0; b < numBlocks; b++, g += 4) {
45896
- if (blockBBox[g + 2] < mx || blockBBox[g] > hx || blockBBox[g + 3] < tminY || blockBBox[g + 1] > tmaxY) continue;
45897
- const stop = liveBlockStop(b);
45898
- p = liveBlockHead(b);
45899
- do {
45900
- if (p.prev.next === p && hx >= p.x && p.x >= mx && hx !== p.x && // skip dead nodes
45901
- pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
45902
- const tan = Math.abs(hy - p.y) / (hx - p.x);
45903
- if ((locallyInside(p, hole) || p.y === hy && p.next.y === hy && p.next.x > hx) && (tan < tanMin || tan === tanMin && (p.x > m.x || p.x === m.x && sectorContainsSector(m, p)))) {
45904
- m = p;
45905
- tanMin = tan;
45906
- }
45907
- }
45908
- p = p.next;
45909
- } while (p !== stop);
45910
- }
45911
- return m;
45912
- }
45913
- function sectorContainsSector(m, p) {
45914
- return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
45915
- }
45916
- var sortArr = [];
45917
- var sortBuf = [];
45918
- var zArr = new Uint32Array(0);
45919
- var zBuf = new Uint32Array(0);
45920
- var counts = new Uint32Array(256);
45921
- function indexCurve(start, minX, minY, invSize) {
45922
- let p = start;
45923
- let n = 0;
45924
- do {
45925
- p.z = zOrder(p.x, p.y, minX, minY, invSize);
45926
- sortArr[n++] = p;
45927
- p = p.next;
45928
- } while (p !== start);
45929
- sortNodes(n);
45930
- let prev = null;
45931
- for (let i = 0; i < n; i++) {
45932
- const node = sortArr[i];
45933
- node.prevZ = prev;
45934
- if (prev) prev.nextZ = node;
45935
- prev = node;
45936
- }
45937
- prev.nextZ = null;
45938
- sortArr.fill(
45939
- /** @type {Node} */
45940
- /** @type {unknown} */
45941
- null,
45942
- 0,
45943
- n
45944
- );
45945
- sortBuf.fill(
45946
- /** @type {Node} */
45947
- /** @type {unknown} */
45948
- null,
45949
- 0,
45950
- n
45951
- );
45952
- }
45953
- function sortNodes(n) {
45954
- if (n <= 32) {
45955
- for (let i = 1; i < n; i++) {
45956
- const node = sortArr[i], z42 = node.z;
45957
- let j = i - 1;
45958
- while (j >= 0 && sortArr[j].z > z42) {
45959
- sortArr[j + 1] = sortArr[j];
45960
- j--;
45961
- }
45962
- sortArr[j + 1] = node;
45963
- }
45964
- return;
45965
- }
45966
- if (zArr.length < n) {
45967
- zArr = new Uint32Array(n);
45968
- zBuf = new Uint32Array(n);
45969
- sortBuf = new Array(n);
45970
- }
45971
- for (let i = 0; i < n; i++) zArr[i] = sortArr[i].z;
45972
- radixPass(n, sortArr, zArr, sortBuf, zBuf, 0);
45973
- radixPass(n, sortBuf, zBuf, sortArr, zArr, 8);
45974
- radixPass(n, sortArr, zArr, sortBuf, zBuf, 16);
45975
- radixPass(n, sortBuf, zBuf, sortArr, zArr, 24);
45976
- }
45977
- function radixPass(n, src, srcZ, dst, dstZ, shift4) {
45978
- counts.fill(0);
45979
- for (let i = 0; i < n; i++) counts[srcZ[i] >>> shift4 & 255]++;
45980
- let sum = 0;
45981
- for (let b = 0; b < 256; b++) {
45982
- const c = counts[b];
45983
- counts[b] = sum;
45984
- sum += c;
45985
- }
45986
- for (let i = 0; i < n; i++) {
45987
- const z42 = srcZ[i];
45988
- const pos = counts[z42 >>> shift4 & 255]++;
45989
- dst[pos] = src[i];
45990
- dstZ[pos] = z42;
45991
- }
45992
- }
45993
- function zOrder(x, y, minX, minY, invSize) {
45994
- x = (x - minX) * invSize | 0;
45995
- y = (y - minY) * invSize | 0;
45996
- x = (x | x << 8) & 16711935;
45997
- x = (x | x << 4) & 252645135;
45998
- x = (x | x << 2) & 858993459;
45999
- x = (x | x << 1) & 1431655765;
46000
- y = (y | y << 8) & 16711935;
46001
- y = (y | y << 4) & 252645135;
46002
- y = (y | y << 2) & 858993459;
46003
- y = (y | y << 1) & 1431655765;
46004
- return x | y << 1;
46005
- }
46006
- function getLeftmost(start) {
46007
- let p = start, leftmost = start;
46008
- do {
46009
- if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y) leftmost = p;
46010
- p = p.next;
46011
- } while (p !== start);
46012
- return leftmost;
46013
- }
46014
- function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
46015
- return (cx - px) * (ay - py) >= (ax - px) * (cy - py) && (ax - px) * (by - py) >= (bx - px) * (ay - py) && (bx - px) * (cy - py) >= (cx - px) * (by - py);
46016
- }
46017
- function isValidDiagonal(a, b) {
46018
- const zeroLength = equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0;
46019
- return a.next.i !== b.i && (zeroLength || locallyInside(a, b) && locallyInside(b, a) && // // locally visible
46020
- (area(a.prev, a, b.prev) !== 0 || area(a, b.prev, b) !== 0)) && // no opposite-facing sectors
46021
- !intersectsPolygon(a, b) && (zeroLength || middleInside(a, b));
46022
- }
46023
- function area(p, q, r) {
46024
- return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
46025
- }
46026
- function equals(p1, p2) {
46027
- return p1.x === p2.x && p1.y === p2.y;
46028
- }
46029
- function intersects(p1, q1, p2, q2, includeBoundary = true) {
46030
- const o1 = area(p1, q1, p2);
46031
- const o2 = area(p1, q1, q2);
46032
- const o3 = area(p2, q2, p1);
46033
- const o4 = area(p2, q2, q1);
46034
- if ((o1 > 0 && o2 < 0 || o1 < 0 && o2 > 0) && (o3 > 0 && o4 < 0 || o3 < 0 && o4 > 0)) return true;
46035
- if (!includeBoundary) return false;
46036
- if (o1 === 0 && onSegment2(p1, p2, q1)) return true;
46037
- if (o2 === 0 && onSegment2(p1, q2, q1)) return true;
46038
- if (o3 === 0 && onSegment2(p2, p1, q2)) return true;
46039
- if (o4 === 0 && onSegment2(p2, q1, q2)) return true;
46040
- return false;
46041
- }
46042
- function onSegment2(p, q, r) {
46043
- return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
46044
- }
46045
- function intersectsPolygon(a, b) {
46046
- const minX = Math.min(a.x, b.x);
46047
- const maxX = Math.max(a.x, b.x);
46048
- const minY = Math.min(a.y, b.y);
46049
- const maxY = Math.max(a.y, b.y);
46050
- let p = a;
46051
- do {
46052
- const n = p.next;
46053
- if (p.x > maxX && n.x > maxX || p.x < minX && n.x < minX || p.y > maxY && n.y > maxY || p.y < minY && n.y < minY) {
46054
- p = n;
46055
- continue;
46056
- }
46057
- if (p.i !== a.i && n.i !== a.i && p.i !== b.i && n.i !== b.i && intersects(p, n, a, b)) return true;
46058
- p = n;
46059
- } while (p !== a);
46060
- return false;
46061
- }
46062
- function locallyInside(a, b) {
46063
- return area(a.prev, a, a.next) < 0 ? area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
46064
- }
46065
- function middleInside(a, b) {
46066
- let p = a;
46067
- let inside = false;
46068
- const px = (a.x + b.x) / 2;
46069
- const py = (a.y + b.y) / 2;
46070
- do {
46071
- const n = p.next;
46072
- if (p.y > py !== n.y > py && px < (n.x - p.x) * (py - p.y) / (n.y - p.y) + p.x)
46073
- inside = !inside;
46074
- p = n;
46075
- } while (p !== a);
46076
- return inside;
46077
- }
46078
- function splitPolygon(a, b) {
46079
- const a2 = createNode(a.i, a.x, a.y), b2 = createNode(b.i, b.x, b.y), an = a.next, bp = b.prev;
46080
- a.next = b;
46081
- b.prev = a;
46082
- a2.next = an;
46083
- an.prev = a2;
46084
- b2.next = a2;
46085
- a2.prev = b2;
46086
- bp.next = b2;
46087
- b2.prev = bp;
46088
- return b2;
46089
- }
46090
- function insertNode(i, x, y, last) {
46091
- const p = createNode(i, x, y);
46092
- if (!last) {
46093
- p.prev = p;
46094
- p.next = p;
46095
- } else {
46096
- p.next = last.next;
46097
- p.prev = last;
46098
- last.next.prev = p;
46099
- last.next = p;
46100
- }
46101
- return p;
46102
- }
46103
- function removeNode(p) {
46104
- p.next.prev = p.prev;
46105
- p.prev.next = p.next;
46106
- if (p.prevZ) p.prevZ.nextZ = p.nextZ;
46107
- if (p.nextZ) p.nextZ.prevZ = p.prevZ;
46108
- if (indexActive) growBlock(p.prev, p.next);
46109
- }
46110
- function createNode(i, x, y) {
46111
- return (
46112
- /** @type {Node} */
46113
- /** @type {unknown} */
46114
- {
46115
- i,
46116
- // vertex index in coordinates array
46117
- x,
46118
- y,
46119
- // vertex coordinates
46120
- prev: null,
46121
- // previous and next vertex nodes in a polygon ring
46122
- next: null,
46123
- z: 0,
46124
- // z-order curve value; doubles as owning block in the hole-bridge index during eliminateHoles
46125
- prevZ: null,
46126
- // previous and next nodes in z-order
46127
- nextZ: null
46128
- }
46129
- );
46130
- }
46131
- function signedArea(data, start, end, dim) {
46132
- let sum = 0;
46133
- for (let i = start, j = end - dim; i < end; i += dim) {
46134
- sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
46135
- j = i;
46136
- }
46137
- return sum;
46138
- }
46139
-
46140
47130
  // node_modules/@tscircuit/flex-utils/dist/index.js
46141
47131
  var EPS = 1e-7;
46142
47132
  function createPcbFold(records, thickness) {
@@ -46313,7 +47303,7 @@ function foldSurfaceMesh(mesh, fold) {
46313
47303
  };
46314
47304
  const triangles = [];
46315
47305
  for (const triangle of mesh.triangles) {
46316
- const face = triangle.pcbFace ?? (triangle.normal.z > 0.8 ? "top" : triangle.normal.z < -0.8 ? "bottom" : "side");
47306
+ const face2 = triangle.pcbFace ?? (triangle.normal.z > 0.8 ? "top" : triangle.normal.z < -0.8 ? "bottom" : "side");
46317
47307
  let polygons = [
46318
47308
  triangle.vertices.map((p, index2) => ({
46319
47309
  p,
@@ -46356,7 +47346,7 @@ function foldSurfaceMesh(mesh, fold) {
46356
47346
  ...triangle,
46357
47347
  vertices,
46358
47348
  normal: { x: n.x / l, y: n.y / l, z: n.z / l },
46359
- pcbFace: face,
47349
+ pcbFace: face2,
46360
47350
  uvs: verts.map(({ uv }) => uv)
46361
47351
  });
46362
47352
  }
@@ -46370,12 +47360,12 @@ var axes = [
46370
47360
  { x: 0, y: 0, z: 1 }
46371
47361
  ];
46372
47362
  function rotateVector(v, degrees) {
46373
- const [x, y, z42] = [degrees.x, degrees.y, degrees.z].map(
47363
+ const [x, y, z27] = [degrees.x, degrees.y, degrees.z].map(
46374
47364
  (a2) => a2 * Math.PI / 180
46375
47365
  );
46376
47366
  const a = {
46377
- x: Math.cos(z42) * v.x - Math.sin(z42) * v.y,
46378
- y: Math.sin(z42) * v.x + Math.cos(z42) * v.y,
47367
+ x: Math.cos(z27) * v.x - Math.sin(z27) * v.y,
47368
+ y: Math.sin(z27) * v.x + Math.cos(z27) * v.y,
46379
47369
  z: v.z
46380
47370
  };
46381
47371
  const b = {
@@ -47195,8 +48185,8 @@ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbT
47195
48185
  depth,
47196
48186
  sizeDelta = 0
47197
48187
  }) => {
47198
- const shape = ph.shape;
47199
- if (shape !== "hole_with_polygon_pad") {
48188
+ const shape2 = ph.shape;
48189
+ if (shape2 !== "hole_with_polygon_pad") {
47200
48190
  return null;
47201
48191
  }
47202
48192
  const padOutline = ph.pad_outline;
@@ -56711,7 +57701,7 @@ function createGeometryFromPolygons(polygons) {
56711
57701
  }
56712
57702
 
56713
57703
  // src/utils/render-component.tsx
56714
- var import_modeling2 = __toESM(require_src(), 1);
57704
+ var import_modeling4 = __toESM(require_src(), 1);
56715
57705
  var import_jscad_planner2 = __toESM(require_dist(), 1);
56716
57706
  var jscadModeling2 = __toESM(require_src(), 1);
56717
57707
  import * as THREE57 from "three";
@@ -56774,7 +57764,7 @@ async function renderComponent(component, scene) {
56774
57764
  }
56775
57765
  if (component.model_jscad) {
56776
57766
  const jscadObject = (0, import_jscad_planner2.executeJscadOperations)(
56777
- import_modeling2.default,
57767
+ import_modeling4.default,
56778
57768
  component.model_jscad
56779
57769
  );
56780
57770
  if (jscadObject && (jscadObject.polygons || jscadObject.sides)) {
@@ -56996,7 +57986,7 @@ function useExportGltfUrl(options = {}) {
56996
57986
  function useParser(options = {}) {
56997
57987
  const exporter = useMemo34(() => new GLTFExporter3(), []);
56998
57988
  return (instance) => {
56999
- const { promise, resolve, reject } = Promise.withResolvers();
57989
+ const { promise, resolve: resolve2, reject } = Promise.withResolvers();
57000
57990
  exporter.parse(
57001
57991
  instance,
57002
57992
  (gltf) => {
@@ -57005,7 +57995,7 @@ function useParser(options = {}) {
57005
57995
  [gltf instanceof ArrayBuffer ? gltf : JSON.stringify(gltf)],
57006
57996
  { type: `model/${type}` }
57007
57997
  );
57008
- resolve(URL.createObjectURL(blob));
57998
+ resolve2(URL.createObjectURL(blob));
57009
57999
  },
57010
58000
  reject,
57011
58001
  options