circuit-json-to-gltf 0.0.75 → 0.0.76

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -65,6 +65,7 @@ convertCircuitJsonToGltf(circuitJson: CircuitJson, options?: ConversionOptions):
65
65
 
66
66
  - `format`: "gltf" (JSON) or "glb" (binary) - default: "gltf"
67
67
  - `boardTextureResolution`: Resolution for board texture rendering - default: 1024
68
+ - `boardDrillQuality`: Drill geometry detail level, "high" or "fast" - default: "fast"
68
69
  - `drawFauxBoard`: Draw a fallback board if no `pcb_board` or `pcb_panel` is present - default: false
69
70
  - `includeModels`: Whether to load external 3D models - default: true
70
71
  - `modelCache`: Map for caching loaded models
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@ interface AuthHeaders extends Record<string, string> {
6
6
  interface ConversionOptions {
7
7
  format?: "gltf" | "glb";
8
8
  boardTextureResolution?: number;
9
+ boardDrillQuality?: "high" | "fast";
9
10
  drawFauxBoard?: boolean;
10
11
  includeModels?: boolean;
11
12
  modelCache?: Map<string, STLMesh | OBJMesh>;
@@ -122,6 +123,7 @@ interface CircuitTo3DOptions {
122
123
  componentColor?: Color;
123
124
  copperColor?: Color;
124
125
  boardThickness?: number;
126
+ boardDrillQuality?: "high" | "fast";
125
127
  drawFauxBoard?: boolean;
126
128
  defaultComponentHeight?: number;
127
129
  renderBoardTextures?: boolean;
@@ -175,27 +177,6 @@ declare function loadSTL({ url, transform, projectBaseUrl, authHeaders, }: {
175
177
  }): Promise<STLMesh>;
176
178
  declare function clearSTLCache(): void;
177
179
 
178
- declare function applyCoordinateTransform(point: Point3, config: CoordinateTransformConfig): Point3;
179
- declare function transformTriangles(triangles: Triangle[], config: CoordinateTransformConfig): Triangle[];
180
- declare const COORDINATE_TRANSFORMS: {
181
- readonly Z_UP_TO_Y_UP: CoordinateTransformConfig;
182
- readonly Z_OUT_OF_TOP: CoordinateTransformConfig;
183
- readonly STEP_INVERTED: CoordinateTransformConfig;
184
- readonly USB_PORT_FIX: CoordinateTransformConfig;
185
- readonly Z_UP_TO_Y_UP_USB_FIX: CoordinateTransformConfig;
186
- readonly IDENTITY: CoordinateTransformConfig;
187
- readonly TEST_ROTATE_X_90: CoordinateTransformConfig;
188
- readonly TEST_ROTATE_X_270: CoordinateTransformConfig;
189
- readonly TEST_ROTATE_Y_90: CoordinateTransformConfig;
190
- readonly TEST_ROTATE_Y_270: CoordinateTransformConfig;
191
- readonly TEST_ROTATE_Z_90: CoordinateTransformConfig;
192
- readonly TEST_ROTATE_Z_270: CoordinateTransformConfig;
193
- readonly TEST_FLIP_X: CoordinateTransformConfig;
194
- readonly TEST_FLIP_Z: CoordinateTransformConfig;
195
- readonly FOOTPRINTER_MODEL_TRANSFORM: CoordinateTransformConfig;
196
- readonly OBJ_Z_UP_TO_Y_UP: CoordinateTransformConfig;
197
- };
198
-
199
180
  interface CameraFitOptions {
200
181
  /**
201
182
  * Target-to-camera direction vector used for solved camera position.
@@ -228,6 +209,27 @@ declare function getBestCameraPosition(circuitJson: CircuitJson): {
228
209
  fov: number;
229
210
  };
230
211
 
212
+ declare function applyCoordinateTransform(point: Point3, config: CoordinateTransformConfig): Point3;
213
+ declare function transformTriangles(triangles: Triangle[], config: CoordinateTransformConfig): Triangle[];
214
+ declare const COORDINATE_TRANSFORMS: {
215
+ readonly Z_UP_TO_Y_UP: CoordinateTransformConfig;
216
+ readonly Z_OUT_OF_TOP: CoordinateTransformConfig;
217
+ readonly STEP_INVERTED: CoordinateTransformConfig;
218
+ readonly USB_PORT_FIX: CoordinateTransformConfig;
219
+ readonly Z_UP_TO_Y_UP_USB_FIX: CoordinateTransformConfig;
220
+ readonly IDENTITY: CoordinateTransformConfig;
221
+ readonly TEST_ROTATE_X_90: CoordinateTransformConfig;
222
+ readonly TEST_ROTATE_X_270: CoordinateTransformConfig;
223
+ readonly TEST_ROTATE_Y_90: CoordinateTransformConfig;
224
+ readonly TEST_ROTATE_Y_270: CoordinateTransformConfig;
225
+ readonly TEST_ROTATE_Z_90: CoordinateTransformConfig;
226
+ readonly TEST_ROTATE_Z_270: CoordinateTransformConfig;
227
+ readonly TEST_FLIP_X: CoordinateTransformConfig;
228
+ readonly TEST_FLIP_Z: CoordinateTransformConfig;
229
+ readonly FOOTPRINTER_MODEL_TRANSFORM: CoordinateTransformConfig;
230
+ readonly OBJ_Z_UP_TO_Y_UP: CoordinateTransformConfig;
231
+ };
232
+
231
233
  declare function convertCircuitJsonToGltf(circuitJson: CircuitJson, options?: ConversionOptions): Promise<ArrayBuffer | object>;
232
234
 
233
235
  interface Point {
package/dist/index.js CHANGED
@@ -14855,8 +14855,10 @@ function convertOcctResultToMesh(result, transform) {
14855
14855
  const normals = mesh.attributes?.normal?.array;
14856
14856
  const indices = mesh.index.array;
14857
14857
  const brepFaces = mesh.brep_faces ?? [];
14858
+ const sortedBrepFaces = brepFaces.length > 1 ? [...brepFaces].sort((a, b) => a.first - b.first) : brepFaces;
14858
14859
  const meshColor = mesh.color ? [mesh.color[0], mesh.color[1], mesh.color[2]] : void 0;
14859
14860
  const numTriangles = indices.length / 3;
14861
+ let brepFaceIndex = 0;
14860
14862
  for (let t = 0; t < numTriangles; t++) {
14861
14863
  const i0 = indices[t * 3];
14862
14864
  const i1 = indices[t * 3 + 1];
@@ -14888,17 +14890,18 @@ function convertOcctResultToMesh(result, transform) {
14888
14890
  }
14889
14891
  let triangleColor;
14890
14892
  let foundFaceColor = false;
14891
- for (const face of brepFaces) {
14892
- if (t >= face.first && t <= face.last && face.color) {
14893
- triangleColor = [
14894
- Math.round(face.color[0] * 255),
14895
- Math.round(face.color[1] * 255),
14896
- Math.round(face.color[2] * 255),
14897
- 1
14898
- ];
14899
- foundFaceColor = true;
14900
- break;
14901
- }
14893
+ while (brepFaceIndex < sortedBrepFaces.length && t > sortedBrepFaces[brepFaceIndex].last) {
14894
+ brepFaceIndex++;
14895
+ }
14896
+ const currentBrepFace = sortedBrepFaces[brepFaceIndex];
14897
+ if (currentBrepFace && t >= currentBrepFace.first && t <= currentBrepFace.last && currentBrepFace.color) {
14898
+ triangleColor = [
14899
+ Math.round(currentBrepFace.color[0] * 255),
14900
+ Math.round(currentBrepFace.color[1] * 255),
14901
+ Math.round(currentBrepFace.color[2] * 255),
14902
+ 1
14903
+ ];
14904
+ foundFaceColor = true;
14902
14905
  }
14903
14906
  if (!foundFaceColor && meshColor) {
14904
14907
  triangleColor = [
@@ -15201,8 +15204,10 @@ function scaleMesh(mesh, scale) {
15201
15204
  var import_extrusions = __toESM(require_extrusions(), 1);
15202
15205
  var import_transforms = __toESM(require_transforms(), 1);
15203
15206
  var import_primitives = __toESM(require_primitives(), 1);
15204
- var DEFAULT_SEGMENTS = 64;
15205
- var REDUCED_SEGMENTS = 16;
15207
+ var DEFAULT_QUALITY_MODE_SEGMENTS = 24;
15208
+ var REDUCED_QUALITY_MODE_SEGMENTS = 8;
15209
+ var HIGH_QUALITY_MODE_SEGMENTS = 64;
15210
+ var HIGH_QUALITY_MODE_REDUCED_SEGMENTS = 16;
15206
15211
  var HOLE_COUNT_THRESHOLD = 50;
15207
15212
  var toBoardSpaceVec2 = (point, center) => [point.x - center.x, -(point.y - center.y)];
15208
15213
  var isFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value);
@@ -15216,13 +15221,13 @@ var arePointsClockwise = (points) => {
15216
15221
  const signedArea = area / 2;
15217
15222
  return signedArea <= 0;
15218
15223
  };
15219
- var createCircularHole = (x, y, radius, thickness, segments = DEFAULT_SEGMENTS) => (0, import_primitives.cylinder)({
15224
+ var createCircularHole = (x, y, radius, thickness, segments = DEFAULT_QUALITY_MODE_SEGMENTS) => (0, import_primitives.cylinder)({
15220
15225
  center: [x, y, 0],
15221
15226
  height: thickness + 1,
15222
15227
  radius,
15223
15228
  segments
15224
15229
  });
15225
- var createCutoutGeoms = (boardCenter, thickness, cutouts = [], segments = DEFAULT_SEGMENTS) => {
15230
+ var createCutoutGeoms = (boardCenter, thickness, cutouts = [], segments = DEFAULT_QUALITY_MODE_SEGMENTS) => {
15226
15231
  const geoms = [];
15227
15232
  for (const cutout of cutouts) {
15228
15233
  if (!cutout) continue;
@@ -15363,6 +15368,12 @@ var batchedUnion = (geoms, batchSize = 50) => {
15363
15368
 
15364
15369
  // lib/utils/pcb-board-geometry.ts
15365
15370
  var RADIUS_EPSILON = 1e-4;
15371
+ var getHoleSegments = (totalHoleCount, drillQuality) => {
15372
+ if (drillQuality === "high") {
15373
+ return totalHoleCount > HOLE_COUNT_THRESHOLD ? HIGH_QUALITY_MODE_REDUCED_SEGMENTS : HIGH_QUALITY_MODE_SEGMENTS;
15374
+ }
15375
+ return totalHoleCount > HOLE_COUNT_THRESHOLD ? REDUCED_QUALITY_MODE_SEGMENTS : DEFAULT_QUALITY_MODE_SEGMENTS;
15376
+ };
15366
15377
  var getNumberProperty = (obj, key) => {
15367
15378
  const value = obj[key];
15368
15379
  return typeof value === "number" ? value : void 0;
@@ -15387,7 +15398,7 @@ var createBoardOutlineGeom = (board, center, thickness) => {
15387
15398
  geom = (0, import_transforms2.translate)([0, 0, -thickness / 2], geom);
15388
15399
  return geom;
15389
15400
  };
15390
- var createPillHoleWithSegments = (x, y, width, height, thickness, rotate, segments = DEFAULT_SEGMENTS) => {
15401
+ var createPillHoleWithSegments = (x, y, width, height, thickness, rotate, segments = DEFAULT_QUALITY_MODE_SEGMENTS) => {
15391
15402
  const minDimension = Math.min(width, height);
15392
15403
  const maxAllowedRadius = Math.max(0, minDimension / 2 - RADIUS_EPSILON);
15393
15404
  const roundRadius = maxAllowedRadius <= 0 ? 0 : Math.min(height / 2, maxAllowedRadius);
@@ -15403,7 +15414,7 @@ var createPillHoleWithSegments = (x, y, width, height, thickness, rotate, segmen
15403
15414
  }
15404
15415
  return (0, import_transforms2.translate)([x, y, 0], hole3d);
15405
15416
  };
15406
- var createHoleGeoms = (boardCenter, thickness, holes = [], platedHoles = [], segments = DEFAULT_SEGMENTS) => {
15417
+ var createHoleGeoms = (boardCenter, thickness, holes = [], platedHoles = [], segments = DEFAULT_QUALITY_MODE_SEGMENTS) => {
15407
15418
  const holeGeoms = [];
15408
15419
  for (const hole of holes) {
15409
15420
  const holeRecord = hole;
@@ -15540,12 +15551,17 @@ var createBoundingBox = (bbox) => {
15540
15551
  };
15541
15552
  };
15542
15553
  var createBoardMesh = (board, options) => {
15543
- const { thickness, holes = [], platedHoles = [], cutouts = [] } = options;
15554
+ const {
15555
+ thickness,
15556
+ holes = [],
15557
+ platedHoles = [],
15558
+ cutouts = [],
15559
+ drillQuality = "fast"
15560
+ } = options;
15544
15561
  const center = board.center ?? { x: 0, y: 0 };
15545
15562
  let boardGeom = createBoardOutlineGeom(board, center, thickness);
15546
15563
  const totalHoleCount = holes.length + platedHoles.length;
15547
- const useReducedSegments = totalHoleCount > HOLE_COUNT_THRESHOLD;
15548
- const segments = useReducedSegments ? REDUCED_SEGMENTS : DEFAULT_SEGMENTS;
15564
+ const segments = getHoleSegments(totalHoleCount, drillQuality);
15549
15565
  const holeGeoms = createHoleGeoms(
15550
15566
  center,
15551
15567
  thickness,
@@ -15577,11 +15593,11 @@ var import_booleans3 = __toESM(require_booleans(), 1);
15577
15593
  var import_transforms3 = __toESM(require_transforms(), 1);
15578
15594
  var createPanelMesh = (panel, options) => {
15579
15595
  const { thickness, holes = [], platedHoles = [], cutouts = [] } = options;
15596
+ const drillQuality = options.drillQuality ?? "fast";
15580
15597
  const center = panel.center ?? { x: 0, y: 0 };
15581
15598
  let panelGeom = createBoardOutlineGeom(panel, center, thickness);
15582
15599
  const totalHoleCount = holes.length + platedHoles.length;
15583
- const useReducedSegments = totalHoleCount > HOLE_COUNT_THRESHOLD;
15584
- const segments = useReducedSegments ? REDUCED_SEGMENTS : DEFAULT_SEGMENTS;
15600
+ const segments = drillQuality === "high" ? totalHoleCount > HOLE_COUNT_THRESHOLD ? HIGH_QUALITY_MODE_REDUCED_SEGMENTS : HIGH_QUALITY_MODE_SEGMENTS : totalHoleCount > HOLE_COUNT_THRESHOLD ? REDUCED_QUALITY_MODE_SEGMENTS : DEFAULT_QUALITY_MODE_SEGMENTS;
15585
15601
  const holeGeoms = createHoleGeoms(
15586
15602
  center,
15587
15603
  thickness,
@@ -15724,6 +15740,7 @@ async function convertCircuitJsonTo3D(circuitJson, options = {}) {
15724
15740
  componentColor = "rgba(128,128,128,0.5)",
15725
15741
  copperColor = "#C87B4B",
15726
15742
  boardThickness = DEFAULT_BOARD_THICKNESS,
15743
+ boardDrillQuality = "fast",
15727
15744
  drawFauxBoard = false,
15728
15745
  defaultComponentHeight = DEFAULT_COMPONENT_HEIGHT,
15729
15746
  renderBoardTextures: shouldRenderTextures = true,
@@ -15748,7 +15765,8 @@ async function convertCircuitJsonTo3D(circuitJson, options = {}) {
15748
15765
  thickness: effectiveBoardThickness,
15749
15766
  holes: pcbHoles,
15750
15767
  platedHoles: pcbPlatedHoles,
15751
- cutouts: panelCutouts
15768
+ cutouts: panelCutouts,
15769
+ drillQuality: boardDrillQuality
15752
15770
  });
15753
15771
  const meshWidth = panelMesh.boundingBox.max.x - panelMesh.boundingBox.min.x;
15754
15772
  const meshHeight = panelMesh.boundingBox.max.z - panelMesh.boundingBox.min.z;
@@ -15793,7 +15811,8 @@ async function convertCircuitJsonTo3D(circuitJson, options = {}) {
15793
15811
  thickness: effectiveBoardThickness,
15794
15812
  holes: pcbHoles,
15795
15813
  platedHoles: pcbPlatedHoles,
15796
- cutouts: boardCutouts
15814
+ cutouts: boardCutouts,
15815
+ drillQuality: boardDrillQuality
15797
15816
  });
15798
15817
  const meshWidth = boardMesh.boundingBox.max.x - boardMesh.boundingBox.min.x;
15799
15818
  const meshHeight = boardMesh.boundingBox.max.z - boardMesh.boundingBox.min.z;
@@ -17580,6 +17599,7 @@ async function convertCircuitJsonToGltf(circuitJson, options = {}) {
17580
17599
  const {
17581
17600
  format = "gltf",
17582
17601
  boardTextureResolution = 1024,
17602
+ boardDrillQuality = "fast",
17583
17603
  drawFauxBoard = false,
17584
17604
  includeModels = true,
17585
17605
  modelCache,
@@ -17589,6 +17609,7 @@ async function convertCircuitJsonToGltf(circuitJson, options = {}) {
17589
17609
  const scene3D = await convertCircuitJsonTo3D(circuitJson, {
17590
17610
  renderBoardTextures: true,
17591
17611
  textureResolution: boardTextureResolution,
17612
+ boardDrillQuality,
17592
17613
  drawFauxBoard,
17593
17614
  coordinateTransform: options.coordinateTransform,
17594
17615
  showBoundingBoxes,
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "circuit-json-to-gltf",
3
3
  "main": "dist/index.js",
4
4
  "type": "module",
5
- "version": "0.0.75",
5
+ "version": "0.0.76",
6
6
  "scripts": {
7
7
  "test": "bun test tests/",
8
8
  "test:playwright": "playwright test",