@tscircuit/3d-viewer 0.0.443 → 0.0.445

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 +233 -94
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1073,13 +1073,13 @@ var require_rotateZ = __commonJS({
1073
1073
  var require_scale = __commonJS({
1074
1074
  "node_modules/@jscad/modeling/src/maths/vec3/scale.js"(exports, module) {
1075
1075
  "use strict";
1076
- var scale2 = (out, vector, amount) => {
1076
+ var scale3 = (out, vector, amount) => {
1077
1077
  out[0] = vector[0] * amount;
1078
1078
  out[1] = vector[1] * amount;
1079
1079
  out[2] = vector[2] * amount;
1080
1080
  return out;
1081
1081
  };
1082
- module.exports = scale2;
1082
+ module.exports = scale3;
1083
1083
  }
1084
1084
  });
1085
1085
 
@@ -1646,7 +1646,7 @@ var require_rotateZ2 = __commonJS({
1646
1646
  var require_scale2 = __commonJS({
1647
1647
  "node_modules/@jscad/modeling/src/maths/mat4/scale.js"(exports, module) {
1648
1648
  "use strict";
1649
- var scale2 = (out, matrix, dimensions) => {
1649
+ var scale3 = (out, matrix, dimensions) => {
1650
1650
  const x = dimensions[0];
1651
1651
  const y = dimensions[1];
1652
1652
  const z135 = dimensions[2];
@@ -1668,7 +1668,7 @@ var require_scale2 = __commonJS({
1668
1668
  out[15] = matrix[15];
1669
1669
  return out;
1670
1670
  };
1671
- module.exports = scale2;
1671
+ module.exports = scale3;
1672
1672
  }
1673
1673
  });
1674
1674
 
@@ -2153,12 +2153,12 @@ var require_normalize2 = __commonJS({
2153
2153
  var require_scale3 = __commonJS({
2154
2154
  "node_modules/@jscad/modeling/src/maths/vec2/scale.js"(exports, module) {
2155
2155
  "use strict";
2156
- var scale2 = (out, vector, amount) => {
2156
+ var scale3 = (out, vector, amount) => {
2157
2157
  out[0] = vector[0] * amount;
2158
2158
  out[1] = vector[1] * amount;
2159
2159
  return out;
2160
2160
  };
2161
- module.exports = scale2;
2161
+ module.exports = scale3;
2162
2162
  }
2163
2163
  });
2164
2164
 
@@ -2914,7 +2914,7 @@ var require_Face = __commonJS({
2914
2914
  var dot = require_dot();
2915
2915
  var length2 = require_length();
2916
2916
  var normalize = require_normalize();
2917
- var scale2 = require_scale();
2917
+ var scale3 = require_scale();
2918
2918
  var subtract6 = require_subtract();
2919
2919
  var HalfEdge = require_HalfEdge();
2920
2920
  var VISIBLE = 0;
@@ -2962,7 +2962,7 @@ var require_Face = __commonJS({
2962
2962
  this.nVertices += 1;
2963
2963
  }
2964
2964
  this.area = length2(this.normal);
2965
- this.normal = scale2(this.normal, this.normal, 1 / this.area);
2965
+ this.normal = scale3(this.normal, this.normal, 1 / this.area);
2966
2966
  }
2967
2967
  computeNormalMinArea(minArea) {
2968
2968
  this.computeNormal();
@@ -2982,9 +2982,9 @@ var require_Face = __commonJS({
2982
2982
  const p2 = maxEdge.head().point;
2983
2983
  const maxVector = subtract6([], p2, p1);
2984
2984
  const maxLength = Math.sqrt(maxSquaredLength);
2985
- scale2(maxVector, maxVector, 1 / maxLength);
2985
+ scale3(maxVector, maxVector, 1 / maxLength);
2986
2986
  const maxProjection = dot(this.normal, maxVector);
2987
- scale2(maxVector, maxVector, -maxProjection);
2987
+ scale3(maxVector, maxVector, -maxProjection);
2988
2988
  add(this.normal, this.normal, maxVector);
2989
2989
  normalize(this.normal, this.normal);
2990
2990
  }
@@ -2996,7 +2996,7 @@ var require_Face = __commonJS({
2996
2996
  add(this.centroid, this.centroid, edge.head().point);
2997
2997
  edge = edge.next;
2998
2998
  } while (edge !== this.edge);
2999
- scale2(this.centroid, this.centroid, 1 / this.nVertices);
2999
+ scale3(this.centroid, this.centroid, 1 / this.nVertices);
3000
3000
  }
3001
3001
  computeNormalAndCentroid(minArea) {
3002
3002
  if (typeof minArea !== "undefined") {
@@ -13656,7 +13656,7 @@ var require_scale4 = __commonJS({
13656
13656
  var geom2 = require_geom2();
13657
13657
  var geom3 = require_geom3();
13658
13658
  var path2 = require_path2();
13659
- var scale2 = (factors, ...objects) => {
13659
+ var scale3 = (factors, ...objects) => {
13660
13660
  if (!Array.isArray(factors)) throw new Error("factors must be an array");
13661
13661
  objects = flatten(objects);
13662
13662
  if (objects.length === 0) throw new Error("wrong number of arguments");
@@ -13672,11 +13672,11 @@ var require_scale4 = __commonJS({
13672
13672
  });
13673
13673
  return results.length === 1 ? results[0] : results;
13674
13674
  };
13675
- var scaleX = (factor, ...objects) => scale2([factor, 1, 1], objects);
13676
- var scaleY = (factor, ...objects) => scale2([1, factor, 1], objects);
13677
- var scaleZ = (factor, ...objects) => scale2([1, 1, factor], objects);
13675
+ var scaleX = (factor, ...objects) => scale3([factor, 1, 1], objects);
13676
+ var scaleY = (factor, ...objects) => scale3([1, factor, 1], objects);
13677
+ var scaleZ = (factor, ...objects) => scale3([1, 1, factor], objects);
13678
13678
  module.exports = {
13679
- scale: scale2,
13679
+ scale: scale3,
13680
13680
  scaleX,
13681
13681
  scaleY,
13682
13682
  scaleZ
@@ -14530,7 +14530,7 @@ function MixedStlModel({
14530
14530
  onHover,
14531
14531
  onUnhover,
14532
14532
  isHovered,
14533
- scale: scale2
14533
+ scale: scale3
14534
14534
  }) {
14535
14535
  const obj = useGlobalObjLoader(url);
14536
14536
  const { rootObject } = useThree();
@@ -14570,8 +14570,8 @@ function MixedStlModel({
14570
14570
  model.rotation.copy(rotation2);
14571
14571
  }
14572
14572
  }
14573
- if (scale2 !== void 0) {
14574
- model.scale.setScalar(scale2);
14573
+ if (scale3 !== void 0) {
14574
+ model.scale.setScalar(scale3);
14575
14575
  }
14576
14576
  }, [
14577
14577
  model,
@@ -14581,7 +14581,7 @@ function MixedStlModel({
14581
14581
  Array.isArray(rotation2) ? rotation2[0] : rotation2?.x,
14582
14582
  Array.isArray(rotation2) ? rotation2[1] : rotation2?.y,
14583
14583
  Array.isArray(rotation2) ? rotation2[2] : rotation2?.z,
14584
- scale2
14584
+ scale3
14585
14585
  ]);
14586
14586
  if (obj instanceof Error) {
14587
14587
  throw obj;
@@ -14639,10 +14639,11 @@ function GltfModel({
14639
14639
  onHover,
14640
14640
  onUnhover,
14641
14641
  isHovered,
14642
- scale: scale2
14642
+ scale: scale3
14643
14643
  }) {
14644
14644
  const { renderer, rootObject } = useThree();
14645
14645
  const [model, setModel] = useState3(null);
14646
+ const [loadError, setLoadError] = useState3(null);
14646
14647
  useEffect5(() => {
14647
14648
  if (!gltfUrl) return;
14648
14649
  const loader = new GLTFLoader();
@@ -14654,8 +14655,10 @@ function GltfModel({
14654
14655
  },
14655
14656
  void 0,
14656
14657
  (error) => {
14657
- if (isMounted)
14658
- console.error(`An error happened loading ${gltfUrl}`, error);
14658
+ if (!isMounted) return;
14659
+ console.error(`An error happened loading ${gltfUrl}`, error);
14660
+ const err = error instanceof Error ? error : new Error(`Failed to load glTF model from ${gltfUrl}`);
14661
+ setLoadError(err);
14659
14662
  }
14660
14663
  );
14661
14664
  return () => {
@@ -14666,7 +14669,7 @@ function GltfModel({
14666
14669
  if (!model) return;
14667
14670
  if (position) model.position.fromArray(position);
14668
14671
  if (rotation2) model.rotation.fromArray(rotation2);
14669
- if (scale2 !== void 0) model.scale.setScalar(scale2);
14672
+ if (scale3 !== void 0) model.scale.setScalar(scale3);
14670
14673
  }, [
14671
14674
  model,
14672
14675
  position?.[0],
@@ -14675,7 +14678,7 @@ function GltfModel({
14675
14678
  rotation2?.[0],
14676
14679
  rotation2?.[1],
14677
14680
  rotation2?.[2],
14678
- scale2
14681
+ scale3
14679
14682
  ]);
14680
14683
  useEffect5(() => {
14681
14684
  if (!rootObject || !model) return;
@@ -14734,6 +14737,9 @@ function GltfModel({
14734
14737
  }
14735
14738
  });
14736
14739
  }, [isHovered, model]);
14740
+ if (loadError) {
14741
+ throw loadError;
14742
+ }
14737
14743
  if (!model) return null;
14738
14744
  return /* @__PURE__ */ jsx4(
14739
14745
  ContainerWithTooltip_default,
@@ -24828,9 +24834,9 @@ function getExpandedStroke(strokeInput, width10) {
24828
24834
  addPoint(current2, normalPrev, -1);
24829
24835
  addPoint(current2, normalNext, -1);
24830
24836
  } else {
24831
- const scale2 = 1 / miterLength;
24832
- addPoint(current2, { x: miterX * scale2, y: miterY * scale2 }, 1);
24833
- addPoint(current2, { x: miterX * scale2, y: miterY * scale2 }, -1);
24837
+ const scale3 = 1 / miterLength;
24838
+ addPoint(current2, { x: miterX * scale3, y: miterY * scale3 }, 1);
24839
+ addPoint(current2, { x: miterX * scale3, y: miterY * scale3 }, -1);
24834
24840
  }
24835
24841
  }
24836
24842
  const lastNormal = getNormal(
@@ -27905,7 +27911,7 @@ var JscadModel = ({
27905
27911
  onHover,
27906
27912
  onUnhover,
27907
27913
  isHovered,
27908
- scale: scale2
27914
+ scale: scale3
27909
27915
  }) => {
27910
27916
  const { rootObject } = useThree();
27911
27917
  const { threeGeom, material } = useMemo4(() => {
@@ -27936,7 +27942,7 @@ var JscadModel = ({
27936
27942
  if (!mesh) return;
27937
27943
  if (positionOffset) mesh.position.fromArray(positionOffset);
27938
27944
  if (rotationOffset) mesh.rotation.fromArray(rotationOffset);
27939
- if (scale2 !== void 0) mesh.scale.setScalar(scale2);
27945
+ if (scale3 !== void 0) mesh.scale.setScalar(scale3);
27940
27946
  }, [
27941
27947
  mesh,
27942
27948
  positionOffset?.[0],
@@ -27945,7 +27951,7 @@ var JscadModel = ({
27945
27951
  rotationOffset?.[0],
27946
27952
  rotationOffset?.[1],
27947
27953
  rotationOffset?.[2],
27948
- scale2
27954
+ scale3
27949
27955
  ]);
27950
27956
  useMemo4(() => {
27951
27957
  if (!material) return;
@@ -27982,7 +27988,7 @@ var FootprinterModel = ({
27982
27988
  onHover,
27983
27989
  onUnhover,
27984
27990
  isHovered,
27985
- scale: scale2
27991
+ scale: scale3
27986
27992
  }) => {
27987
27993
  const { rootObject } = useThree();
27988
27994
  const group = useMemo5(() => {
@@ -28018,7 +28024,7 @@ var FootprinterModel = ({
28018
28024
  if (!group) return;
28019
28025
  if (positionOffset) group.position.fromArray(positionOffset);
28020
28026
  if (rotationOffset) group.rotation.fromArray(rotationOffset);
28021
- if (scale2 !== void 0) group.scale.setScalar(scale2);
28027
+ if (scale3 !== void 0) group.scale.setScalar(scale3);
28022
28028
  }, [
28023
28029
  group,
28024
28030
  positionOffset?.[0],
@@ -28027,7 +28033,7 @@ var FootprinterModel = ({
28027
28033
  rotationOffset?.[0],
28028
28034
  rotationOffset?.[1],
28029
28035
  rotationOffset?.[2],
28030
- scale2
28036
+ scale3
28031
28037
  ]);
28032
28038
  useEffect7(() => {
28033
28039
  if (!group) return;
@@ -28318,7 +28324,7 @@ import * as THREE15 from "three";
28318
28324
  // package.json
28319
28325
  var package_default = {
28320
28326
  name: "@tscircuit/3d-viewer",
28321
- version: "0.0.442",
28327
+ version: "0.0.444",
28322
28328
  main: "./dist/index.js",
28323
28329
  module: "./dist/index.js",
28324
28330
  type: "module",
@@ -29617,7 +29623,7 @@ var createBoardGeomFromCircuitJson = (circuitJson, opts = {}) => {
29617
29623
  };
29618
29624
 
29619
29625
  // src/BoardGeomBuilder.ts
29620
- var import_transforms8 = __toESM(require_transforms(), 1);
29626
+ var import_transforms9 = __toESM(require_transforms(), 1);
29621
29627
  var import_primitives10 = __toESM(require_primitives(), 1);
29622
29628
  var import_colors7 = __toESM(require_colors(), 1);
29623
29629
  var import_booleans6 = __toESM(require_booleans(), 1);
@@ -29627,8 +29633,9 @@ import { su as su3 } from "@tscircuit/circuit-json-util";
29627
29633
  var import_primitives4 = __toESM(require_primitives(), 1);
29628
29634
  var import_colors2 = __toESM(require_colors(), 1);
29629
29635
  var import_booleans2 = __toESM(require_booleans(), 1);
29630
- var import_extrusions3 = __toESM(require_extrusions(), 1);
29631
29636
  var import_transforms3 = __toESM(require_transforms(), 1);
29637
+ var import_extrusions3 = __toESM(require_extrusions(), 1);
29638
+ var import_transforms4 = __toESM(require_transforms(), 1);
29632
29639
 
29633
29640
  // src/utils/rect-border-radius.ts
29634
29641
  function clampRectBorderRadius(width10, height10, rawRadius) {
@@ -29760,7 +29767,7 @@ var createRectPadGeom = ({
29760
29767
  });
29761
29768
  const extruded = (0, import_extrusions3.extrudeLinear)({ height: thickness }, rect2d);
29762
29769
  const offsetZ = center[2] - thickness / 2;
29763
- return (0, import_transforms3.translate)([center[0], center[1], offsetZ], extruded);
29770
+ return (0, import_transforms4.translate)([center[0], center[1], offsetZ], extruded);
29764
29771
  };
29765
29772
  var platedHole = (plated_hole, ctx, options = {}) => {
29766
29773
  const { clipGeom } = options;
@@ -29785,6 +29792,39 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29785
29792
  });
29786
29793
  return (0, import_colors2.colorize)(colors.copper, (0, import_booleans2.subtract)(copperSolid, drill));
29787
29794
  }
29795
+ if (plated_hole.shape === "oval") {
29796
+ const outerWidth = plated_hole.outer_width || plated_hole.hole_width || 0;
29797
+ const outerHeight = plated_hole.outer_height || plated_hole.hole_height || 0;
29798
+ const holeWidth = plated_hole.hole_width || 0;
29799
+ const holeHeight = plated_hole.hole_height || 0;
29800
+ const copperBody = (() => {
29801
+ const circle2 = (0, import_primitives4.cylinder)({
29802
+ center: [0, 0, 0],
29803
+ radius: 1,
29804
+ height: copperSpan + 0.01,
29805
+ segments: 64
29806
+ // High segment count for smooth ellipse
29807
+ });
29808
+ const scaled = (0, import_transforms3.scale)([outerWidth / 2, outerHeight / 2, 1], circle2);
29809
+ return (0, import_transforms4.translate)([plated_hole.x, plated_hole.y, 0], scaled);
29810
+ })();
29811
+ const copperSolid = maybeClip(copperBody, clipGeom);
29812
+ const drill = (() => {
29813
+ const circle2 = (0, import_primitives4.cylinder)({
29814
+ center: [0, 0, 0],
29815
+ radius: 1,
29816
+ height: throughDrillHeight,
29817
+ segments: 64
29818
+ // High segment count for smooth ellipse
29819
+ });
29820
+ const scaled = (0, import_transforms3.scale)(
29821
+ [Math.max(holeWidth / 2, 0.01), Math.max(holeHeight / 2, 0.01), 1],
29822
+ circle2
29823
+ );
29824
+ return (0, import_transforms4.translate)([plated_hole.x, plated_hole.y, 0], scaled);
29825
+ })();
29826
+ return (0, import_colors2.colorize)(colors.copper, (0, import_booleans2.subtract)(copperSolid, drill));
29827
+ }
29788
29828
  if (plated_hole.shape === "circular_hole_with_rect_pad") {
29789
29829
  const holeOffsetX = plated_hole.hole_offset_x || 0;
29790
29830
  const holeOffsetY = plated_hole.hole_offset_y || 0;
@@ -29823,7 +29863,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29823
29863
  segments: RECT_PAD_SEGMENTS
29824
29864
  });
29825
29865
  const extruded = (0, import_extrusions3.extrudeLinear)({ height: height10 }, rect2d);
29826
- return (0, import_transforms3.translate)(
29866
+ return (0, import_transforms4.translate)(
29827
29867
  [plated_hole.x, plated_hole.y, centerZ - height10 / 2],
29828
29868
  extruded
29829
29869
  );
@@ -29876,9 +29916,9 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29876
29916
  const rotationRadians = (plated_hole.ccw_rotation || 0) * Math.PI / 180;
29877
29917
  const rotateAroundCenter = (geom) => {
29878
29918
  if (!rotationRadians) return geom;
29879
- const toOrigin = (0, import_transforms3.translate)([-plated_hole.x, -plated_hole.y, 0], geom);
29880
- const rotated = (0, import_transforms3.rotate)([0, 0, rotationRadians], toOrigin);
29881
- return (0, import_transforms3.translate)([plated_hole.x, plated_hole.y, 0], rotated);
29919
+ const toOrigin = (0, import_transforms4.translate)([-plated_hole.x, -plated_hole.y, 0], geom);
29920
+ const rotated = (0, import_transforms4.rotate)([0, 0, rotationRadians], toOrigin);
29921
+ return (0, import_transforms4.translate)([plated_hole.x, plated_hole.y, 0], rotated);
29882
29922
  };
29883
29923
  const shouldRotate = plated_hole.hole_height > plated_hole.hole_width;
29884
29924
  const holeWidth = shouldRotate ? plated_hole.hole_height : plated_hole.hole_width;
@@ -30049,7 +30089,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
30049
30089
  segments: RECT_PAD_SEGMENTS
30050
30090
  });
30051
30091
  const extruded = (0, import_extrusions3.extrudeLinear)({ height: height10 }, rect2d);
30052
- return (0, import_transforms3.translate)(
30092
+ return (0, import_transforms4.translate)(
30053
30093
  [plated_hole.x, plated_hole.y, centerZ - height10 / 2],
30054
30094
  extruded
30055
30095
  );
@@ -30111,7 +30151,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
30111
30151
  const createPolygonPad = (thickness, zCenter) => {
30112
30152
  const safeThickness = Math.max(thickness, M);
30113
30153
  const extruded = (0, import_extrusions3.extrudeLinear)({ height: safeThickness }, polygon2d);
30114
- return (0, import_transforms3.translate)(
30154
+ return (0, import_transforms4.translate)(
30115
30155
  [plated_hole.x, plated_hole.y, zCenter - safeThickness / 2],
30116
30156
  extruded
30117
30157
  );
@@ -30449,7 +30489,7 @@ function createSilkscreenTextGeoms(silkscreenText) {
30449
30489
  var import_primitives5 = __toESM(require_primitives(), 1);
30450
30490
  var import_expansions2 = __toESM(require_expansions(), 1);
30451
30491
  var import_extrusions4 = __toESM(require_extrusions(), 1);
30452
- var import_transforms4 = __toESM(require_transforms(), 1);
30492
+ var import_transforms5 = __toESM(require_transforms(), 1);
30453
30493
  var import_colors3 = __toESM(require_colors(), 1);
30454
30494
 
30455
30495
  // src/utils/units.ts
@@ -30512,7 +30552,7 @@ function createSilkscreenPathGeom(sp, ctx) {
30512
30552
  );
30513
30553
  const layerSign = sp.layer === "bottom" ? -1 : 1;
30514
30554
  const zPos = layerSign * ctx.pcbThickness / 2 + layerSign * M * 1.5;
30515
- let pathGeom = (0, import_transforms4.translate)(
30555
+ let pathGeom = (0, import_transforms5.translate)(
30516
30556
  [0, 0, zPos],
30517
30557
  (0, import_extrusions4.extrudeLinear)({ height: 0.012 }, expandedPath)
30518
30558
  // Standard silkscreen thickness
@@ -30525,7 +30565,7 @@ function createSilkscreenPathGeom(sp, ctx) {
30525
30565
  var import_primitives6 = __toESM(require_primitives(), 1);
30526
30566
  var import_expansions3 = __toESM(require_expansions(), 1);
30527
30567
  var import_extrusions5 = __toESM(require_extrusions(), 1);
30528
- var import_transforms5 = __toESM(require_transforms(), 1);
30568
+ var import_transforms6 = __toESM(require_transforms(), 1);
30529
30569
  var import_colors4 = __toESM(require_colors(), 1);
30530
30570
  function createSilkscreenLineGeom(sl, ctx) {
30531
30571
  const x1 = parseDimensionToMm(sl.x1) ?? 0;
@@ -30545,7 +30585,7 @@ function createSilkscreenLineGeom(sl, ctx) {
30545
30585
  );
30546
30586
  const layerSign = sl.layer === "bottom" ? -1 : 1;
30547
30587
  const zPos = layerSign * ctx.pcbThickness / 2 + layerSign * M * 1.5;
30548
- let lineGeom = (0, import_transforms5.translate)(
30588
+ let lineGeom = (0, import_transforms6.translate)(
30549
30589
  [0, 0, zPos],
30550
30590
  (0, import_extrusions5.extrudeLinear)({ height: 0.012 }, expandedLine)
30551
30591
  );
@@ -30556,7 +30596,7 @@ function createSilkscreenLineGeom(sl, ctx) {
30556
30596
  // src/geoms/create-geoms-for-silkscreen-rect.ts
30557
30597
  var import_primitives7 = __toESM(require_primitives(), 1);
30558
30598
  var import_extrusions6 = __toESM(require_extrusions(), 1);
30559
- var import_transforms6 = __toESM(require_transforms(), 1);
30599
+ var import_transforms7 = __toESM(require_transforms(), 1);
30560
30600
  var import_colors5 = __toESM(require_colors(), 1);
30561
30601
  var import_booleans3 = __toESM(require_booleans(), 1);
30562
30602
  var RECT_SEGMENTS = 64;
@@ -30611,14 +30651,14 @@ function createSilkscreenRectGeom(rect, ctx) {
30611
30651
  if (!rectGeom) return void 0;
30612
30652
  const layerSign = rect.layer === "bottom" ? -1 : 1;
30613
30653
  const zPos = layerSign * ctx.pcbThickness / 2 + layerSign * M * 1.5;
30614
- rectGeom = (0, import_transforms6.translate)([centerX, centerY, zPos], rectGeom);
30654
+ rectGeom = (0, import_transforms7.translate)([centerX, centerY, zPos], rectGeom);
30615
30655
  return (0, import_colors5.colorize)([1, 1, 1], rectGeom);
30616
30656
  }
30617
30657
 
30618
30658
  // src/geoms/create-geoms-for-silkscreen-circle.ts
30619
30659
  var import_primitives8 = __toESM(require_primitives(), 1);
30620
30660
  var import_extrusions7 = __toESM(require_extrusions(), 1);
30621
- var import_transforms7 = __toESM(require_transforms(), 1);
30661
+ var import_transforms8 = __toESM(require_transforms(), 1);
30622
30662
  var import_colors6 = __toESM(require_colors(), 1);
30623
30663
  var import_booleans4 = __toESM(require_booleans(), 1);
30624
30664
  var CIRCLE_SEGMENTS = 64;
@@ -30654,7 +30694,7 @@ function createSilkscreenCircleGeom(circleEl, ctx) {
30654
30694
  const filledCircle2d = (0, import_primitives8.circle)({ radius, segments: CIRCLE_SEGMENTS });
30655
30695
  circleGeom = (0, import_extrusions7.extrudeLinear)({ height: baseHeight }, filledCircle2d);
30656
30696
  }
30657
- const translatedGeom = (0, import_transforms7.translate)([centerX, centerY, zPos], circleGeom);
30697
+ const translatedGeom = (0, import_transforms8.translate)([centerX, centerY, zPos], circleGeom);
30658
30698
  return (0, import_colors6.colorize)([1, 1, 1], translatedGeom);
30659
30699
  }
30660
30700
 
@@ -30758,7 +30798,7 @@ var createCenteredRectPadGeom = (width10, height10, thickness, rectBorderRadius)
30758
30798
  segments: PAD_ROUNDED_SEGMENTS
30759
30799
  });
30760
30800
  const extruded = (0, import_extrusions8.extrudeLinear)({ height: thickness }, rect2d);
30761
- return (0, import_transforms8.translate)([0, 0, -thickness / 2], extruded);
30801
+ return (0, import_transforms9.translate)([0, 0, -thickness / 2], extruded);
30762
30802
  };
30763
30803
  var buildStateOrder = [
30764
30804
  "initializing",
@@ -31037,8 +31077,8 @@ var BoardGeomBuilder = class {
31037
31077
  segments: PAD_ROUNDED_SEGMENTS
31038
31078
  });
31039
31079
  cutoutGeom = (0, import_extrusions8.extrudeLinear)({ height: cutoutHeight }, rect2d);
31040
- cutoutGeom = (0, import_transforms8.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
31041
- cutoutGeom = (0, import_transforms8.translate)(
31080
+ cutoutGeom = (0, import_transforms9.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
31081
+ cutoutGeom = (0, import_transforms9.translate)(
31042
31082
  [cutout.center.x, cutout.center.y, 0],
31043
31083
  cutoutGeom
31044
31084
  );
@@ -31047,14 +31087,14 @@ var BoardGeomBuilder = class {
31047
31087
  center: [0, 0, 0],
31048
31088
  size: [cutout.width, cutout.height, cutoutHeight]
31049
31089
  });
31050
- cutoutGeom = (0, import_transforms8.translate)(
31090
+ cutoutGeom = (0, import_transforms9.translate)(
31051
31091
  [cutout.center.x, cutout.center.y, 0],
31052
31092
  baseCutoutGeom
31053
31093
  );
31054
31094
  }
31055
31095
  if (cutout.rotation) {
31056
31096
  const rotationRadians = cutout.rotation * Math.PI / 180;
31057
- cutoutGeom = (0, import_transforms8.rotateZ)(rotationRadians, cutoutGeom);
31097
+ cutoutGeom = (0, import_transforms9.rotateZ)(rotationRadians, cutoutGeom);
31058
31098
  }
31059
31099
  break;
31060
31100
  case "circle":
@@ -31077,7 +31117,7 @@ var BoardGeomBuilder = class {
31077
31117
  }
31078
31118
  const polygon2d = (0, import_primitives10.polygon)({ points: pointsVec2 });
31079
31119
  cutoutGeom = (0, import_extrusions8.extrudeLinear)({ height: cutoutHeight }, polygon2d);
31080
- cutoutGeom = (0, import_transforms8.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
31120
+ cutoutGeom = (0, import_transforms9.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
31081
31121
  break;
31082
31122
  }
31083
31123
  if (cutoutGeom) {
@@ -31096,15 +31136,15 @@ var BoardGeomBuilder = class {
31096
31136
  });
31097
31137
  if ("rotation" in pour && pour.rotation) {
31098
31138
  const rotationRadians = pour.rotation * Math.PI / 180;
31099
- baseGeom = (0, import_transforms8.rotateZ)(rotationRadians, baseGeom);
31139
+ baseGeom = (0, import_transforms9.rotateZ)(rotationRadians, baseGeom);
31100
31140
  }
31101
- pourGeom = (0, import_transforms8.translate)([pour.center.x, pour.center.y, zPos], baseGeom);
31141
+ pourGeom = (0, import_transforms9.translate)([pour.center.x, pour.center.y, zPos], baseGeom);
31102
31142
  } else if (pour.shape === "brep") {
31103
31143
  const brepShape = pour.brep_shape;
31104
31144
  if (brepShape && brepShape.outer_ring) {
31105
31145
  const pourGeom2 = createGeom2FromBRep(brepShape);
31106
31146
  pourGeom = (0, import_extrusions8.extrudeLinear)({ height: M }, pourGeom2);
31107
- pourGeom = (0, import_transforms8.translate)([0, 0, zPos], pourGeom);
31147
+ pourGeom = (0, import_transforms9.translate)([0, 0, zPos], pourGeom);
31108
31148
  }
31109
31149
  } else if (pour.shape === "polygon") {
31110
31150
  let pointsVec2 = pour.points.map((p) => [p.x, p.y]);
@@ -31119,7 +31159,7 @@ var BoardGeomBuilder = class {
31119
31159
  }
31120
31160
  const polygon2d = (0, import_primitives10.polygon)({ points: pointsVec2 });
31121
31161
  pourGeom = (0, import_extrusions8.extrudeLinear)({ height: M }, polygon2d);
31122
- pourGeom = (0, import_transforms8.translate)([0, 0, zPos], pourGeom);
31162
+ pourGeom = (0, import_transforms9.translate)([0, 0, zPos], pourGeom);
31123
31163
  }
31124
31164
  if (pourGeom) {
31125
31165
  if (this.boardClipGeom) {
@@ -31191,9 +31231,9 @@ var BoardGeomBuilder = class {
31191
31231
  );
31192
31232
  if (ph.ccw_rotation) {
31193
31233
  const rotationRadians = ph.ccw_rotation * Math.PI / 180;
31194
- pillHole = (0, import_transforms8.translate)(
31234
+ pillHole = (0, import_transforms9.translate)(
31195
31235
  [ph.x, ph.y, 0],
31196
- (0, import_transforms8.rotateZ)(rotationRadians, (0, import_transforms8.translate)([-ph.x, -ph.y, 0], pillHole))
31236
+ (0, import_transforms9.rotateZ)(rotationRadians, (0, import_transforms9.translate)([-ph.x, -ph.y, 0], pillHole))
31197
31237
  );
31198
31238
  }
31199
31239
  if (!opts.dontCutBoard) {
@@ -31343,7 +31383,7 @@ var BoardGeomBuilder = class {
31343
31383
  }
31344
31384
  if (isRotated) {
31345
31385
  const rotationRadians = hole.ccw_rotation * Math.PI / 180;
31346
- pillHole = (0, import_transforms8.rotateZ)(rotationRadians, pillHole);
31386
+ pillHole = (0, import_transforms9.rotateZ)(rotationRadians, pillHole);
31347
31387
  }
31348
31388
  this.boardGeom = (0, import_booleans6.subtract)(this.boardGeom, pillHole);
31349
31389
  this.padGeoms = this.padGeoms.map(
@@ -31366,7 +31406,7 @@ var BoardGeomBuilder = class {
31366
31406
  M,
31367
31407
  rectBorderRadius
31368
31408
  );
31369
- const positionedPadGeom = (0, import_transforms8.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31409
+ const positionedPadGeom = (0, import_transforms9.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31370
31410
  let finalPadGeom = positionedPadGeom;
31371
31411
  if (this.boardClipGeom) {
31372
31412
  finalPadGeom = (0, import_booleans6.intersect)(this.boardClipGeom, finalPadGeom);
@@ -31381,8 +31421,8 @@ var BoardGeomBuilder = class {
31381
31421
  rectBorderRadius
31382
31422
  );
31383
31423
  const rotationRadians = pad2.ccw_rotation * Math.PI / 180;
31384
- basePadGeom = (0, import_transforms8.rotateZ)(rotationRadians, basePadGeom);
31385
- const positionedPadGeom = (0, import_transforms8.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31424
+ basePadGeom = (0, import_transforms9.rotateZ)(rotationRadians, basePadGeom);
31425
+ const positionedPadGeom = (0, import_transforms9.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31386
31426
  let finalPadGeom = positionedPadGeom;
31387
31427
  if (this.boardClipGeom) {
31388
31428
  finalPadGeom = (0, import_booleans6.intersect)(this.boardClipGeom, finalPadGeom);
@@ -31417,7 +31457,7 @@ var BoardGeomBuilder = class {
31417
31457
  { delta: currentWidth / 2, corners: "round" },
31418
31458
  linePath
31419
31459
  );
31420
- let traceGeom = (0, import_transforms8.translate)(
31460
+ let traceGeom = (0, import_transforms9.translate)(
31421
31461
  [0, 0, zCenter - M / 2],
31422
31462
  (0, import_extrusions8.extrudeLinear)({ height: M }, expandedPath)
31423
31463
  );
@@ -31527,13 +31567,13 @@ var BoardGeomBuilder = class {
31527
31567
  );
31528
31568
  let textGeom;
31529
31569
  if (st.layer === "bottom") {
31530
- textGeom = (0, import_transforms8.translate)(
31570
+ textGeom = (0, import_transforms9.translate)(
31531
31571
  [0, 0, -this.ctx.pcbThickness / 2 - M],
31532
31572
  // Position above board
31533
31573
  (0, import_extrusions8.extrudeLinear)({ height: 0.012 }, expandedPath)
31534
31574
  );
31535
31575
  } else {
31536
- textGeom = (0, import_transforms8.translate)(
31576
+ textGeom = (0, import_transforms9.translate)(
31537
31577
  [0, 0, this.ctx.pcbThickness / 2 + M],
31538
31578
  // Position above board
31539
31579
  (0, import_extrusions8.extrudeLinear)({ height: 0.012 }, expandedPath)
@@ -31653,7 +31693,7 @@ var Text = ({
31653
31693
  parent,
31654
31694
  position,
31655
31695
  rotation: rotation2,
31656
- scale: scale2,
31696
+ scale: scale3,
31657
31697
  color,
31658
31698
  fontSize,
31659
31699
  anchorX,
@@ -31666,7 +31706,7 @@ var Text = ({
31666
31706
  textMesh.text = children;
31667
31707
  if (position) textMesh.position.fromArray(position);
31668
31708
  if (rotation2) textMesh.rotation.fromArray(rotation2);
31669
- if (scale2) textMesh.scale.fromArray(scale2);
31709
+ if (scale3) textMesh.scale.fromArray(scale3);
31670
31710
  textMesh.color = color || "white";
31671
31711
  textMesh.fontSize = fontSize || 1;
31672
31712
  textMesh.anchorX = anchorX || "center";
@@ -31679,7 +31719,7 @@ var Text = ({
31679
31719
  children,
31680
31720
  position,
31681
31721
  rotation2,
31682
- scale2,
31722
+ scale3,
31683
31723
  color,
31684
31724
  fontSize,
31685
31725
  anchorX,
@@ -33088,6 +33128,105 @@ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbT
33088
33128
  geometry: threeGeom,
33089
33129
  color: COPPER_COLOR
33090
33130
  });
33131
+ } else if (ph.shape === "oval") {
33132
+ const holeW = ph.hole_width;
33133
+ const holeH = ph.hole_height;
33134
+ const outerW = ph.outer_width ?? holeW + 0.4;
33135
+ const outerH = ph.outer_height ?? holeH + 0.4;
33136
+ const drillW = holeW + 2 * MANIFOLD_Z_OFFSET;
33137
+ const drillH = holeH + 2 * MANIFOLD_Z_OFFSET;
33138
+ const drillDepth = pcbThickness * 1.2;
33139
+ let boardDrillPoints = createEllipsePoints(
33140
+ drillW,
33141
+ drillH,
33142
+ SMOOTH_CIRCLE_SEGMENTS
33143
+ );
33144
+ if (arePointsClockwise3(boardDrillPoints)) {
33145
+ boardDrillPoints = boardDrillPoints.reverse();
33146
+ }
33147
+ const boardDrillCrossSection = CrossSection.ofPolygons([boardDrillPoints]);
33148
+ manifoldInstancesForCleanup.push(boardDrillCrossSection);
33149
+ let boardDrillOp = Manifold.extrude(
33150
+ boardDrillCrossSection,
33151
+ drillDepth,
33152
+ 0,
33153
+ 0,
33154
+ [1, 1],
33155
+ true
33156
+ );
33157
+ manifoldInstancesForCleanup.push(boardDrillOp);
33158
+ if (ph.ccw_rotation) {
33159
+ const rotatedDrill = boardDrillOp.rotate([0, 0, ph.ccw_rotation]);
33160
+ manifoldInstancesForCleanup.push(rotatedDrill);
33161
+ boardDrillOp = rotatedDrill;
33162
+ }
33163
+ const translatedDrill = boardDrillOp.translate([ph.x, ph.y, 0]);
33164
+ manifoldInstancesForCleanup.push(translatedDrill);
33165
+ platedHoleBoardDrills.push(translatedDrill);
33166
+ const copperPartThickness = pcbThickness + 2 * MANIFOLD_Z_OFFSET;
33167
+ let outerPoints = createEllipsePoints(
33168
+ outerW,
33169
+ outerH,
33170
+ SMOOTH_CIRCLE_SEGMENTS
33171
+ );
33172
+ if (arePointsClockwise3(outerPoints)) {
33173
+ outerPoints = outerPoints.reverse();
33174
+ }
33175
+ const outerCrossSection = CrossSection.ofPolygons([outerPoints]);
33176
+ manifoldInstancesForCleanup.push(outerCrossSection);
33177
+ let outerCopperOp = Manifold.extrude(
33178
+ outerCrossSection,
33179
+ copperPartThickness,
33180
+ 0,
33181
+ 0,
33182
+ [1, 1],
33183
+ true
33184
+ );
33185
+ manifoldInstancesForCleanup.push(outerCopperOp);
33186
+ let innerPoints = createEllipsePoints(
33187
+ holeW,
33188
+ holeH,
33189
+ SMOOTH_CIRCLE_SEGMENTS
33190
+ );
33191
+ if (arePointsClockwise3(innerPoints)) {
33192
+ innerPoints = innerPoints.reverse();
33193
+ }
33194
+ const innerCrossSection = CrossSection.ofPolygons([innerPoints]);
33195
+ manifoldInstancesForCleanup.push(innerCrossSection);
33196
+ let innerDrillOp = Manifold.extrude(
33197
+ innerCrossSection,
33198
+ copperPartThickness * 1.05,
33199
+ 0,
33200
+ 0,
33201
+ [1, 1],
33202
+ true
33203
+ );
33204
+ manifoldInstancesForCleanup.push(innerDrillOp);
33205
+ let finalPlatedPartOp = outerCopperOp.subtract(innerDrillOp);
33206
+ manifoldInstancesForCleanup.push(finalPlatedPartOp);
33207
+ if (ph.ccw_rotation) {
33208
+ const rotatedOp = finalPlatedPartOp.rotate([0, 0, ph.ccw_rotation]);
33209
+ manifoldInstancesForCleanup.push(rotatedOp);
33210
+ finalPlatedPartOp = rotatedOp;
33211
+ }
33212
+ const translatedPlatedPart = finalPlatedPartOp.translate([ph.x, ph.y, 0]);
33213
+ manifoldInstancesForCleanup.push(translatedPlatedPart);
33214
+ let finalCopperOp = translatedPlatedPart;
33215
+ if (boardClipVolume) {
33216
+ const clipped = Manifold.intersection([
33217
+ translatedPlatedPart,
33218
+ boardClipVolume
33219
+ ]);
33220
+ manifoldInstancesForCleanup.push(clipped);
33221
+ finalCopperOp = clipped;
33222
+ }
33223
+ platedHoleCopperOpsForSubtract.push(finalCopperOp);
33224
+ const threeGeom = manifoldMeshToThreeGeometry(finalCopperOp.getMesh());
33225
+ platedHoleCopperGeoms.push({
33226
+ key: `ph-${ph.pcb_plated_hole_id || index2}`,
33227
+ geometry: threeGeom,
33228
+ color: COPPER_COLOR
33229
+ });
33091
33230
  } else if (ph.shape === "circular_hole_with_rect_pad") {
33092
33231
  const holeOffsetX = ph.hole_offset_x || 0;
33093
33232
  const holeOffsetY = ph.hole_offset_y || 0;
@@ -36676,21 +36815,21 @@ function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetPar
36676
36815
  }
36677
36816
  const clientRect = element.getBoundingClientRect();
36678
36817
  const domElement = unwrapElement(element);
36679
- let scale2 = createCoords(1);
36818
+ let scale3 = createCoords(1);
36680
36819
  if (includeScale) {
36681
36820
  if (offsetParent) {
36682
36821
  if (isElement(offsetParent)) {
36683
- scale2 = getScale(offsetParent);
36822
+ scale3 = getScale(offsetParent);
36684
36823
  }
36685
36824
  } else {
36686
- scale2 = getScale(element);
36825
+ scale3 = getScale(element);
36687
36826
  }
36688
36827
  }
36689
36828
  const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0);
36690
- let x = (clientRect.left + visualOffsets.x) / scale2.x;
36691
- let y = (clientRect.top + visualOffsets.y) / scale2.y;
36692
- let width10 = clientRect.width / scale2.x;
36693
- let height10 = clientRect.height / scale2.y;
36829
+ let x = (clientRect.left + visualOffsets.x) / scale3.x;
36830
+ let y = (clientRect.top + visualOffsets.y) / scale3.y;
36831
+ let width10 = clientRect.width / scale3.x;
36832
+ let height10 = clientRect.height / scale3.y;
36694
36833
  if (domElement) {
36695
36834
  const win = getWindow(domElement);
36696
36835
  const offsetWin = offsetParent && isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;
@@ -36752,7 +36891,7 @@ function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
36752
36891
  scrollLeft: 0,
36753
36892
  scrollTop: 0
36754
36893
  };
36755
- let scale2 = createCoords(1);
36894
+ let scale3 = createCoords(1);
36756
36895
  const offsets = createCoords(0);
36757
36896
  const isOffsetParentAnElement = isHTMLElement(offsetParent);
36758
36897
  if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
@@ -36761,17 +36900,17 @@ function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
36761
36900
  }
36762
36901
  if (isHTMLElement(offsetParent)) {
36763
36902
  const offsetRect = getBoundingClientRect(offsetParent);
36764
- scale2 = getScale(offsetParent);
36903
+ scale3 = getScale(offsetParent);
36765
36904
  offsets.x = offsetRect.x + offsetParent.clientLeft;
36766
36905
  offsets.y = offsetRect.y + offsetParent.clientTop;
36767
36906
  }
36768
36907
  }
36769
36908
  const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);
36770
36909
  return {
36771
- width: rect.width * scale2.x,
36772
- height: rect.height * scale2.y,
36773
- x: rect.x * scale2.x - scroll.scrollLeft * scale2.x + offsets.x + htmlOffset.x,
36774
- y: rect.y * scale2.y - scroll.scrollTop * scale2.y + offsets.y + htmlOffset.y
36910
+ width: rect.width * scale3.x,
36911
+ height: rect.height * scale3.y,
36912
+ x: rect.x * scale3.x - scroll.scrollLeft * scale3.x + offsets.x + htmlOffset.x,
36913
+ y: rect.y * scale3.y - scroll.scrollTop * scale3.y + offsets.y + htmlOffset.y
36775
36914
  };
36776
36915
  }
36777
36916
  function getClientRects(element) {
@@ -36838,11 +36977,11 @@ function getInnerBoundingClientRect(element, strategy) {
36838
36977
  const clientRect = getBoundingClientRect(element, true, strategy === "fixed");
36839
36978
  const top = clientRect.top + element.clientTop;
36840
36979
  const left = clientRect.left + element.clientLeft;
36841
- const scale2 = isHTMLElement(element) ? getScale(element) : createCoords(1);
36842
- const width10 = element.clientWidth * scale2.x;
36843
- const height10 = element.clientHeight * scale2.y;
36844
- const x = left * scale2.x;
36845
- const y = top * scale2.y;
36980
+ const scale3 = isHTMLElement(element) ? getScale(element) : createCoords(1);
36981
+ const width10 = element.clientWidth * scale3.x;
36982
+ const height10 = element.clientHeight * scale3.y;
36983
+ const x = left * scale3.x;
36984
+ const y = top * scale3.y;
36846
36985
  return {
36847
36986
  width: width10,
36848
36987
  height: height10,
@@ -41440,8 +41579,8 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
41440
41579
  scene.position.sub(center);
41441
41580
  const maxDim = Math.max(size5.x, size5.y, size5.z);
41442
41581
  if (maxDim > 0) {
41443
- const scale2 = (1 - padding / 100) / maxDim;
41444
- scene.scale.multiplyScalar(scale2 * 100);
41582
+ const scale3 = (1 - padding / 100) / maxDim;
41583
+ scene.scale.multiplyScalar(scale3 * 100);
41445
41584
  }
41446
41585
  camera.updateProjectionMatrix();
41447
41586
  renderer.render(scene, camera);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/3d-viewer",
3
- "version": "0.0.443",
3
+ "version": "0.0.445",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "type": "module",