@tscircuit/3d-viewer 0.0.470 → 0.0.472
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -0
- package/dist/index.js +340 -134
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -83,6 +83,8 @@ interface ManifoldTextures {
|
|
|
83
83
|
bottomSoldermask?: THREE.CanvasTexture | null;
|
|
84
84
|
topCopperText?: THREE.CanvasTexture | null;
|
|
85
85
|
bottomCopperText?: THREE.CanvasTexture | null;
|
|
86
|
+
topPanelOutlines?: THREE.CanvasTexture | null;
|
|
87
|
+
bottomPanelOutlines?: THREE.CanvasTexture | null;
|
|
86
88
|
}
|
|
87
89
|
interface UseManifoldBoardBuilderResult {
|
|
88
90
|
geoms: ManifoldGeoms | null;
|
package/dist/index.js
CHANGED
|
@@ -14229,10 +14229,10 @@ var require_browser = __commonJS({
|
|
|
14229
14229
|
|
|
14230
14230
|
// src/CadViewer.tsx
|
|
14231
14231
|
import { useState as useState35, useCallback as useCallback21, useRef as useRef26, useEffect as useEffect43 } from "react";
|
|
14232
|
-
import * as
|
|
14232
|
+
import * as THREE33 from "three";
|
|
14233
14233
|
|
|
14234
14234
|
// src/CadViewerJscad.tsx
|
|
14235
|
-
import { su as
|
|
14235
|
+
import { su as su12 } from "@tscircuit/circuit-json-util";
|
|
14236
14236
|
import { forwardRef as forwardRef3, useMemo as useMemo20 } from "react";
|
|
14237
14237
|
|
|
14238
14238
|
// src/AnyCadComponent.tsx
|
|
@@ -28509,7 +28509,7 @@ import * as THREE15 from "three";
|
|
|
28509
28509
|
// package.json
|
|
28510
28510
|
var package_default = {
|
|
28511
28511
|
name: "@tscircuit/3d-viewer",
|
|
28512
|
-
version: "0.0.
|
|
28512
|
+
version: "0.0.471",
|
|
28513
28513
|
main: "./dist/index.js",
|
|
28514
28514
|
module: "./dist/index.js",
|
|
28515
28515
|
type: "module",
|
|
@@ -29782,6 +29782,10 @@ var createSimplifiedBoardGeom = (circuitJson) => {
|
|
|
29782
29782
|
let pcbThickness = 1.2;
|
|
29783
29783
|
if (panels.length > 0) {
|
|
29784
29784
|
boardOrPanel = panels[0];
|
|
29785
|
+
const firstBoardInPanel = boards.find(
|
|
29786
|
+
(b) => b.pcb_panel_id === boardOrPanel.pcb_panel_id
|
|
29787
|
+
);
|
|
29788
|
+
pcbThickness = firstBoardInPanel?.thickness ?? 1.2;
|
|
29785
29789
|
} else {
|
|
29786
29790
|
const boardsNotInPanel = boards.filter(
|
|
29787
29791
|
(b) => !b.pcb_panel_id
|
|
@@ -29807,7 +29811,10 @@ var createSimplifiedBoardGeom = (circuitJson) => {
|
|
|
29807
29811
|
center: [boardOrPanel.center.x, boardOrPanel.center.y, 0]
|
|
29808
29812
|
});
|
|
29809
29813
|
}
|
|
29810
|
-
const
|
|
29814
|
+
const materialName = "material" in boardOrPanel && boardOrPanel.material ? boardOrPanel.material : panels.length > 0 ? boards.find(
|
|
29815
|
+
(b) => b.pcb_panel_id === boardOrPanel.pcb_panel_id
|
|
29816
|
+
)?.material ?? "fr4" : "fr4";
|
|
29817
|
+
const material = boardMaterialColors[materialName] ?? colors.fr4Tan;
|
|
29811
29818
|
return [(0, import_colors.colorize)(material, boardGeom)];
|
|
29812
29819
|
};
|
|
29813
29820
|
var createBoardGeomFromCircuitJson = (circuitJson, opts = {}) => {
|
|
@@ -30612,16 +30619,18 @@ var BoardGeomBuilder = class {
|
|
|
30612
30619
|
const boards = su3(circuitJson).pcb_board.list();
|
|
30613
30620
|
if (panels.length > 0) {
|
|
30614
30621
|
const panel = panels[0];
|
|
30622
|
+
const firstBoardInPanel = boards.find(
|
|
30623
|
+
(b) => b.pcb_panel_id === panel.pcb_panel_id
|
|
30624
|
+
);
|
|
30615
30625
|
this.board = {
|
|
30616
30626
|
type: "pcb_board",
|
|
30617
30627
|
pcb_board_id: panel.pcb_panel_id,
|
|
30618
30628
|
center: panel.center,
|
|
30619
30629
|
width: panel.width,
|
|
30620
30630
|
height: panel.height,
|
|
30621
|
-
thickness: 1.6,
|
|
30622
|
-
|
|
30623
|
-
|
|
30624
|
-
num_layers: 2
|
|
30631
|
+
thickness: firstBoardInPanel?.thickness ?? 1.6,
|
|
30632
|
+
material: firstBoardInPanel?.material ?? "fr4",
|
|
30633
|
+
num_layers: firstBoardInPanel?.num_layers ?? 2
|
|
30625
30634
|
};
|
|
30626
30635
|
} else {
|
|
30627
30636
|
const boardsNotInPanel = boards.filter((b) => !b.pcb_panel_id);
|
|
@@ -31618,8 +31627,8 @@ var ThreeErrorBoundary = class extends React11.Component {
|
|
|
31618
31627
|
|
|
31619
31628
|
// src/three-components/JscadBoardTextures.tsx
|
|
31620
31629
|
import { useEffect as useEffect22, useMemo as useMemo19 } from "react";
|
|
31621
|
-
import * as
|
|
31622
|
-
import { su as
|
|
31630
|
+
import * as THREE23 from "three";
|
|
31631
|
+
import { su as su9 } from "@tscircuit/circuit-json-util";
|
|
31623
31632
|
|
|
31624
31633
|
// src/utils/soldermask-texture.ts
|
|
31625
31634
|
import * as THREE18 from "three";
|
|
@@ -32411,6 +32420,7 @@ function createSilkscreenTextureForLayer({
|
|
|
32411
32420
|
const pcbSilkscreenRects = su6(circuitJson).pcb_silkscreen_rect.list();
|
|
32412
32421
|
const pcbSilkscreenCircles = su6(circuitJson).pcb_silkscreen_circle.list();
|
|
32413
32422
|
const pcbFabricationNoteRects = su6(circuitJson).pcb_fabrication_note_rect.list();
|
|
32423
|
+
const pcbNoteLines = su6(circuitJson).pcb_note_line.list();
|
|
32414
32424
|
const textsOnLayer = pcbSilkscreenTexts.filter((t) => t.layer === layer);
|
|
32415
32425
|
const pathsOnLayer = pcbSilkscreenPaths.filter((p) => p.layer === layer);
|
|
32416
32426
|
const linesOnLayer = pcbSilkscreenLines.filter((l) => l.layer === layer);
|
|
@@ -32419,7 +32429,10 @@ function createSilkscreenTextureForLayer({
|
|
|
32419
32429
|
const fabricationNoteRectsOnLayer = pcbFabricationNoteRects.filter(
|
|
32420
32430
|
(r) => r.layer === layer
|
|
32421
32431
|
);
|
|
32422
|
-
|
|
32432
|
+
const noteLinesOnLayer = pcbNoteLines.filter(
|
|
32433
|
+
(l) => l.layer === layer
|
|
32434
|
+
);
|
|
32435
|
+
if (textsOnLayer.length === 0 && pathsOnLayer.length === 0 && linesOnLayer.length === 0 && rectsOnLayer.length === 0 && circlesOnLayer.length === 0 && fabricationNoteRectsOnLayer.length === 0 && noteLinesOnLayer.length === 0) {
|
|
32423
32436
|
return null;
|
|
32424
32437
|
}
|
|
32425
32438
|
const canvas = document.createElement("canvas");
|
|
@@ -32450,6 +32463,36 @@ function createSilkscreenTextureForLayer({
|
|
|
32450
32463
|
ctx.lineTo(canvasXFromPcb(endXmm), canvasYFromPcb(endYmm));
|
|
32451
32464
|
ctx.stroke();
|
|
32452
32465
|
});
|
|
32466
|
+
noteLinesOnLayer.forEach((lineEl) => {
|
|
32467
|
+
const startXmm = parseDimensionToMm(lineEl.x1) ?? 0;
|
|
32468
|
+
const startYmm = parseDimensionToMm(lineEl.y1) ?? 0;
|
|
32469
|
+
const endXmm = parseDimensionToMm(lineEl.x2) ?? 0;
|
|
32470
|
+
const endYmm = parseDimensionToMm(lineEl.y2) ?? 0;
|
|
32471
|
+
if (startXmm === endXmm && startYmm === endYmm) return;
|
|
32472
|
+
ctx.save();
|
|
32473
|
+
let strokeColor = silkscreenColor;
|
|
32474
|
+
if (lineEl.color) {
|
|
32475
|
+
strokeColor = parseFabricationNoteColor(lineEl.color);
|
|
32476
|
+
} else {
|
|
32477
|
+
strokeColor = "rgb(255, 243, 204)";
|
|
32478
|
+
}
|
|
32479
|
+
ctx.strokeStyle = strokeColor;
|
|
32480
|
+
ctx.beginPath();
|
|
32481
|
+
ctx.lineWidth = coerceDimensionToMm(lineEl.stroke_width, 0.1) * traceTextureResolution;
|
|
32482
|
+
ctx.lineCap = "round";
|
|
32483
|
+
const isDashed = lineEl.is_dashed ?? false;
|
|
32484
|
+
if (isDashed) {
|
|
32485
|
+
const dashLength = Math.max(ctx.lineWidth * 2, 1);
|
|
32486
|
+
ctx.setLineDash([dashLength, dashLength]);
|
|
32487
|
+
}
|
|
32488
|
+
ctx.moveTo(canvasXFromPcb(startXmm), canvasYFromPcb(startYmm));
|
|
32489
|
+
ctx.lineTo(canvasXFromPcb(endXmm), canvasYFromPcb(endYmm));
|
|
32490
|
+
ctx.stroke();
|
|
32491
|
+
if (isDashed) {
|
|
32492
|
+
ctx.setLineDash([]);
|
|
32493
|
+
}
|
|
32494
|
+
ctx.restore();
|
|
32495
|
+
});
|
|
32453
32496
|
pathsOnLayer.forEach((path) => {
|
|
32454
32497
|
if (path.route.length < 2) return;
|
|
32455
32498
|
ctx.beginPath();
|
|
@@ -33088,6 +33131,72 @@ function createCopperTextTextureForLayer({
|
|
|
33088
33131
|
return texture;
|
|
33089
33132
|
}
|
|
33090
33133
|
|
|
33134
|
+
// src/utils/panel-outline-texture.ts
|
|
33135
|
+
import * as THREE22 from "three";
|
|
33136
|
+
import { su as su8 } from "@tscircuit/circuit-json-util";
|
|
33137
|
+
function createPanelOutlineTextureForLayer({
|
|
33138
|
+
layer,
|
|
33139
|
+
circuitJson,
|
|
33140
|
+
panelData,
|
|
33141
|
+
outlineColor = "black",
|
|
33142
|
+
traceTextureResolution
|
|
33143
|
+
}) {
|
|
33144
|
+
const boardsInPanel = su8(circuitJson).pcb_board.list().filter((b) => b.pcb_panel_id === panelData.pcb_board_id);
|
|
33145
|
+
if (boardsInPanel.length === 0) {
|
|
33146
|
+
return null;
|
|
33147
|
+
}
|
|
33148
|
+
const canvas = document.createElement("canvas");
|
|
33149
|
+
const canvasWidth = Math.floor(panelData.width * traceTextureResolution);
|
|
33150
|
+
const canvasHeight = Math.floor(panelData.height * traceTextureResolution);
|
|
33151
|
+
canvas.width = canvasWidth;
|
|
33152
|
+
canvas.height = canvasHeight;
|
|
33153
|
+
const ctx = canvas.getContext("2d");
|
|
33154
|
+
if (!ctx) return null;
|
|
33155
|
+
if (layer === "bottom") {
|
|
33156
|
+
ctx.translate(0, canvasHeight);
|
|
33157
|
+
ctx.scale(1, -1);
|
|
33158
|
+
}
|
|
33159
|
+
ctx.strokeStyle = outlineColor;
|
|
33160
|
+
ctx.lineWidth = 0.05 * traceTextureResolution;
|
|
33161
|
+
const canvasXFromPcb = (pcbX) => (pcbX - panelData.center.x + panelData.width / 2) * traceTextureResolution;
|
|
33162
|
+
const canvasYFromPcb = (pcbY) => (-(pcbY - panelData.center.y) + panelData.height / 2) * traceTextureResolution;
|
|
33163
|
+
boardsInPanel.forEach((board) => {
|
|
33164
|
+
if (board.outline && board.outline.length >= 2) {
|
|
33165
|
+
ctx.beginPath();
|
|
33166
|
+
board.outline.forEach((point2, index2) => {
|
|
33167
|
+
const x = canvasXFromPcb(point2.x);
|
|
33168
|
+
const y = canvasYFromPcb(point2.y);
|
|
33169
|
+
if (index2 === 0) {
|
|
33170
|
+
ctx.moveTo(x, y);
|
|
33171
|
+
} else {
|
|
33172
|
+
ctx.lineTo(x, y);
|
|
33173
|
+
}
|
|
33174
|
+
});
|
|
33175
|
+
ctx.closePath();
|
|
33176
|
+
ctx.stroke();
|
|
33177
|
+
} else {
|
|
33178
|
+
const width10 = board.width;
|
|
33179
|
+
const height10 = board.height;
|
|
33180
|
+
const { x: centerX, y: centerY } = board.center;
|
|
33181
|
+
const x = canvasXFromPcb(centerX - width10 / 2);
|
|
33182
|
+
const y = canvasYFromPcb(centerY + height10 / 2);
|
|
33183
|
+
ctx.strokeRect(
|
|
33184
|
+
x,
|
|
33185
|
+
y,
|
|
33186
|
+
width10 * traceTextureResolution,
|
|
33187
|
+
height10 * traceTextureResolution
|
|
33188
|
+
);
|
|
33189
|
+
}
|
|
33190
|
+
});
|
|
33191
|
+
const texture = new THREE22.CanvasTexture(canvas);
|
|
33192
|
+
texture.generateMipmaps = true;
|
|
33193
|
+
texture.minFilter = THREE22.LinearMipmapLinearFilter;
|
|
33194
|
+
texture.magFilter = THREE22.LinearFilter;
|
|
33195
|
+
texture.anisotropy = 16;
|
|
33196
|
+
texture.needsUpdate = true;
|
|
33197
|
+
return texture;
|
|
33198
|
+
}
|
|
33199
|
+
|
|
33091
33200
|
// src/three-components/JscadBoardTextures.tsx
|
|
33092
33201
|
function JscadBoardTextures({
|
|
33093
33202
|
circuitJson,
|
|
@@ -33096,8 +33205,30 @@ function JscadBoardTextures({
|
|
|
33096
33205
|
const { rootObject } = useThree();
|
|
33097
33206
|
const { visibility } = useLayerVisibility();
|
|
33098
33207
|
const boardData = useMemo19(() => {
|
|
33099
|
-
const
|
|
33100
|
-
|
|
33208
|
+
const panels = circuitJson.filter(
|
|
33209
|
+
(e) => e.type === "pcb_panel"
|
|
33210
|
+
);
|
|
33211
|
+
const boards = su9(circuitJson).pcb_board.list();
|
|
33212
|
+
if (panels.length > 0) {
|
|
33213
|
+
const panel = panels[0];
|
|
33214
|
+
const firstBoardInPanel = boards.find(
|
|
33215
|
+
(b) => b.pcb_panel_id === panel.pcb_panel_id
|
|
33216
|
+
);
|
|
33217
|
+
return {
|
|
33218
|
+
type: "pcb_board",
|
|
33219
|
+
pcb_board_id: panel.pcb_panel_id,
|
|
33220
|
+
center: panel.center,
|
|
33221
|
+
width: panel.width,
|
|
33222
|
+
height: panel.height,
|
|
33223
|
+
thickness: firstBoardInPanel?.thickness ?? 1.6,
|
|
33224
|
+
material: firstBoardInPanel?.material ?? "fr4",
|
|
33225
|
+
num_layers: firstBoardInPanel?.num_layers ?? 2
|
|
33226
|
+
};
|
|
33227
|
+
}
|
|
33228
|
+
const boardsNotInPanel = boards.filter(
|
|
33229
|
+
(b) => !b.pcb_panel_id
|
|
33230
|
+
);
|
|
33231
|
+
return boardsNotInPanel.length > 0 ? boardsNotInPanel[0] : null;
|
|
33101
33232
|
}, [circuitJson]);
|
|
33102
33233
|
const textures = useMemo19(() => {
|
|
33103
33234
|
if (!boardData || !boardData.width || !boardData.height) return null;
|
|
@@ -33162,28 +33293,40 @@ function JscadBoardTextures({
|
|
|
33162
33293
|
boardData,
|
|
33163
33294
|
copperColor: `rgb(${Math.round(colors.copper[0] * 255)}, ${Math.round(colors.copper[1] * 255)}, ${Math.round(colors.copper[2] * 255)})`,
|
|
33164
33295
|
traceTextureResolution: TRACE_TEXTURE_RESOLUTION
|
|
33296
|
+
}),
|
|
33297
|
+
topPanelOutlines: createPanelOutlineTextureForLayer({
|
|
33298
|
+
layer: "top",
|
|
33299
|
+
circuitJson,
|
|
33300
|
+
panelData: boardData,
|
|
33301
|
+
traceTextureResolution: TRACE_TEXTURE_RESOLUTION
|
|
33302
|
+
}),
|
|
33303
|
+
bottomPanelOutlines: createPanelOutlineTextureForLayer({
|
|
33304
|
+
layer: "bottom",
|
|
33305
|
+
circuitJson,
|
|
33306
|
+
panelData: boardData,
|
|
33307
|
+
traceTextureResolution: TRACE_TEXTURE_RESOLUTION
|
|
33165
33308
|
})
|
|
33166
33309
|
};
|
|
33167
33310
|
}, [circuitJson, boardData]);
|
|
33168
33311
|
useEffect22(() => {
|
|
33169
33312
|
if (!rootObject || !boardData || !textures) return;
|
|
33170
33313
|
const meshes = [];
|
|
33171
|
-
const createTexturePlane = (texture, zOffset, isBottomLayer, name, usePolygonOffset = false) => {
|
|
33314
|
+
const createTexturePlane = (texture, zOffset, isBottomLayer, name, usePolygonOffset = false, depthWrite = false) => {
|
|
33172
33315
|
if (!texture) return null;
|
|
33173
|
-
const planeGeom = new
|
|
33316
|
+
const planeGeom = new THREE23.PlaneGeometry(
|
|
33174
33317
|
boardData.width,
|
|
33175
33318
|
boardData.height
|
|
33176
33319
|
);
|
|
33177
|
-
const material = new
|
|
33320
|
+
const material = new THREE23.MeshBasicMaterial({
|
|
33178
33321
|
map: texture,
|
|
33179
33322
|
transparent: true,
|
|
33180
|
-
side:
|
|
33181
|
-
depthWrite
|
|
33323
|
+
side: THREE23.DoubleSide,
|
|
33324
|
+
depthWrite,
|
|
33182
33325
|
polygonOffset: usePolygonOffset,
|
|
33183
33326
|
polygonOffsetFactor: usePolygonOffset ? -1 : 0,
|
|
33184
33327
|
polygonOffsetUnits: usePolygonOffset ? -1 : 0
|
|
33185
33328
|
});
|
|
33186
|
-
const mesh = new
|
|
33329
|
+
const mesh = new THREE23.Mesh(planeGeom, material);
|
|
33187
33330
|
mesh.position.set(boardData.center.x, boardData.center.y, zOffset);
|
|
33188
33331
|
if (isBottomLayer) {
|
|
33189
33332
|
mesh.rotation.set(Math.PI, 0, 0);
|
|
@@ -33290,13 +33433,41 @@ function JscadBoardTextures({
|
|
|
33290
33433
|
rootObject.add(bottomCopperTextMesh);
|
|
33291
33434
|
}
|
|
33292
33435
|
}
|
|
33436
|
+
if (visibility.boardBody) {
|
|
33437
|
+
const topPanelOutlinesMesh = createTexturePlane(
|
|
33438
|
+
textures.topPanelOutlines,
|
|
33439
|
+
pcbThickness / 2 + SURFACE_OFFSET + 3e-3,
|
|
33440
|
+
// Above silkscreen
|
|
33441
|
+
false,
|
|
33442
|
+
"jscad-top-panel-outlines",
|
|
33443
|
+
false,
|
|
33444
|
+
true
|
|
33445
|
+
);
|
|
33446
|
+
if (topPanelOutlinesMesh) {
|
|
33447
|
+
meshes.push(topPanelOutlinesMesh);
|
|
33448
|
+
rootObject.add(topPanelOutlinesMesh);
|
|
33449
|
+
}
|
|
33450
|
+
const bottomPanelOutlinesMesh = createTexturePlane(
|
|
33451
|
+
textures.bottomPanelOutlines,
|
|
33452
|
+
-pcbThickness / 2 - SURFACE_OFFSET - 3e-3,
|
|
33453
|
+
// Below bottom silkscreen
|
|
33454
|
+
true,
|
|
33455
|
+
"jscad-bottom-panel-outlines",
|
|
33456
|
+
false,
|
|
33457
|
+
true
|
|
33458
|
+
);
|
|
33459
|
+
if (bottomPanelOutlinesMesh) {
|
|
33460
|
+
meshes.push(bottomPanelOutlinesMesh);
|
|
33461
|
+
rootObject.add(bottomPanelOutlinesMesh);
|
|
33462
|
+
}
|
|
33463
|
+
}
|
|
33293
33464
|
return () => {
|
|
33294
33465
|
meshes.forEach((mesh) => {
|
|
33295
33466
|
if (mesh.parent === rootObject) {
|
|
33296
33467
|
rootObject.remove(mesh);
|
|
33297
33468
|
}
|
|
33298
33469
|
mesh.geometry.dispose();
|
|
33299
|
-
if (mesh.material instanceof
|
|
33470
|
+
if (mesh.material instanceof THREE23.Material) {
|
|
33300
33471
|
mesh.material.dispose();
|
|
33301
33472
|
}
|
|
33302
33473
|
});
|
|
@@ -33306,16 +33477,16 @@ function JscadBoardTextures({
|
|
|
33306
33477
|
}
|
|
33307
33478
|
|
|
33308
33479
|
// src/utils/preprocess-circuit-json.ts
|
|
33309
|
-
import { su as
|
|
33480
|
+
import { su as su11 } from "@tscircuit/circuit-json-util";
|
|
33310
33481
|
|
|
33311
33482
|
// src/utils/create-faux-board.ts
|
|
33312
|
-
import { su as
|
|
33483
|
+
import { su as su10, getBoundsOfPcbElements } from "@tscircuit/circuit-json-util";
|
|
33313
33484
|
function createFauxBoard(circuitJson) {
|
|
33314
|
-
const cadComponents =
|
|
33315
|
-
const pads =
|
|
33316
|
-
const holes =
|
|
33317
|
-
const platedHoles =
|
|
33318
|
-
const vias =
|
|
33485
|
+
const cadComponents = su10(circuitJson).cad_component.list();
|
|
33486
|
+
const pads = su10(circuitJson).pcb_smtpad.list();
|
|
33487
|
+
const holes = su10(circuitJson).pcb_hole.list();
|
|
33488
|
+
const platedHoles = su10(circuitJson).pcb_plated_hole.list();
|
|
33489
|
+
const vias = su10(circuitJson).pcb_via.list();
|
|
33319
33490
|
if (cadComponents.length === 0 && pads.length === 0 && holes.length === 0 && platedHoles.length === 0 && vias.length === 0) {
|
|
33320
33491
|
return null;
|
|
33321
33492
|
}
|
|
@@ -33364,7 +33535,7 @@ function createFauxBoard(circuitJson) {
|
|
|
33364
33535
|
|
|
33365
33536
|
// src/utils/preprocess-circuit-json.ts
|
|
33366
33537
|
function addFauxBoardIfNeeded(circuitJson) {
|
|
33367
|
-
const boards =
|
|
33538
|
+
const boards = su11(circuitJson).pcb_board.list();
|
|
33368
33539
|
if (boards.length > 0) {
|
|
33369
33540
|
return circuitJson;
|
|
33370
33541
|
}
|
|
@@ -33414,7 +33585,7 @@ var CadViewerJscad = forwardRef3(
|
|
|
33414
33585
|
const initialCameraPosition = useMemo20(() => {
|
|
33415
33586
|
if (!internalCircuitJson) return [5, -5, 5];
|
|
33416
33587
|
try {
|
|
33417
|
-
const board =
|
|
33588
|
+
const board = su12(internalCircuitJson).pcb_board.list()[0];
|
|
33418
33589
|
if (!board) return [5, -5, 5];
|
|
33419
33590
|
const { width: width10, height: height10 } = board;
|
|
33420
33591
|
if (!width10 && !height10) {
|
|
@@ -33440,7 +33611,7 @@ var CadViewerJscad = forwardRef3(
|
|
|
33440
33611
|
const isFauxBoard = useMemo20(() => {
|
|
33441
33612
|
if (!internalCircuitJson) return false;
|
|
33442
33613
|
try {
|
|
33443
|
-
const board =
|
|
33614
|
+
const board = su12(internalCircuitJson).pcb_board.list()[0];
|
|
33444
33615
|
return !!board && board.pcb_board_id === "faux-board";
|
|
33445
33616
|
} catch (e) {
|
|
33446
33617
|
return false;
|
|
@@ -33449,7 +33620,7 @@ var CadViewerJscad = forwardRef3(
|
|
|
33449
33620
|
const boardDimensions = useMemo20(() => {
|
|
33450
33621
|
if (!internalCircuitJson) return void 0;
|
|
33451
33622
|
try {
|
|
33452
|
-
const board =
|
|
33623
|
+
const board = su12(internalCircuitJson).pcb_board.list()[0];
|
|
33453
33624
|
if (!board) return void 0;
|
|
33454
33625
|
return { width: board.width ?? 0, height: board.height ?? 0 };
|
|
33455
33626
|
} catch (e) {
|
|
@@ -33460,7 +33631,7 @@ var CadViewerJscad = forwardRef3(
|
|
|
33460
33631
|
const boardCenter = useMemo20(() => {
|
|
33461
33632
|
if (!internalCircuitJson) return void 0;
|
|
33462
33633
|
try {
|
|
33463
|
-
const board =
|
|
33634
|
+
const board = su12(internalCircuitJson).pcb_board.list()[0];
|
|
33464
33635
|
if (!board || !board.center) return void 0;
|
|
33465
33636
|
return { x: board.center.x, y: board.center.y };
|
|
33466
33637
|
} catch (e) {
|
|
@@ -33470,7 +33641,7 @@ var CadViewerJscad = forwardRef3(
|
|
|
33470
33641
|
}, [internalCircuitJson]);
|
|
33471
33642
|
const pcbThickness = usePcbThickness(internalCircuitJson);
|
|
33472
33643
|
const { stls: boardStls, loading } = useStlsFromGeom(boardGeom);
|
|
33473
|
-
const cad_components =
|
|
33644
|
+
const cad_components = su12(internalCircuitJson).cad_component.list();
|
|
33474
33645
|
return /* @__PURE__ */ jsxs5(
|
|
33475
33646
|
CadViewerContainer,
|
|
33476
33647
|
{
|
|
@@ -33522,13 +33693,13 @@ var CadViewerJscad = forwardRef3(
|
|
|
33522
33693
|
);
|
|
33523
33694
|
|
|
33524
33695
|
// src/CadViewerManifold.tsx
|
|
33525
|
-
import { su as
|
|
33696
|
+
import { su as su19 } from "@tscircuit/circuit-json-util";
|
|
33526
33697
|
import { useEffect as useEffect24, useMemo as useMemo22, useState as useState15 } from "react";
|
|
33527
33698
|
|
|
33528
33699
|
// src/hooks/useManifoldBoardBuilder.ts
|
|
33529
33700
|
import { useState as useState14, useEffect as useEffect23, useMemo as useMemo21, useRef as useRef9 } from "react";
|
|
33530
|
-
import { su as
|
|
33531
|
-
import * as
|
|
33701
|
+
import { su as su18 } from "@tscircuit/circuit-json-util";
|
|
33702
|
+
import * as THREE29 from "three";
|
|
33532
33703
|
|
|
33533
33704
|
// src/utils/manifold/create-manifold-board.ts
|
|
33534
33705
|
var arePointsClockwise3 = (points) => {
|
|
@@ -33589,17 +33760,17 @@ function createManifoldBoard(Manifold, CrossSection, boardData, pcbThickness, ma
|
|
|
33589
33760
|
}
|
|
33590
33761
|
|
|
33591
33762
|
// src/utils/manifold/process-copper-pours.ts
|
|
33592
|
-
import * as
|
|
33763
|
+
import * as THREE25 from "three";
|
|
33593
33764
|
|
|
33594
33765
|
// src/utils/manifold-mesh-to-three-geometry.ts
|
|
33595
|
-
import * as
|
|
33766
|
+
import * as THREE24 from "three";
|
|
33596
33767
|
function manifoldMeshToThreeGeometry(manifoldMesh) {
|
|
33597
|
-
const geometry = new
|
|
33768
|
+
const geometry = new THREE24.BufferGeometry();
|
|
33598
33769
|
geometry.setAttribute(
|
|
33599
33770
|
"position",
|
|
33600
|
-
new
|
|
33771
|
+
new THREE24.Float32BufferAttribute(manifoldMesh.vertProperties, 3)
|
|
33601
33772
|
);
|
|
33602
|
-
geometry.setIndex(new
|
|
33773
|
+
geometry.setIndex(new THREE24.Uint32BufferAttribute(manifoldMesh.triVerts, 1));
|
|
33603
33774
|
if (manifoldMesh.runIndex && manifoldMesh.runIndex.length > 1 && manifoldMesh.runOriginalID) {
|
|
33604
33775
|
for (let i = 0; i < manifoldMesh.runIndex.length - 1; i++) {
|
|
33605
33776
|
const start = manifoldMesh.runIndex[i];
|
|
@@ -33772,7 +33943,7 @@ function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbT
|
|
|
33772
33943
|
}
|
|
33773
33944
|
const covered = pour.covered_with_solder_mask !== false;
|
|
33774
33945
|
const pourColorArr = covered ? tracesMaterialColors[boardMaterial] ?? colors.fr4TracesWithoutMaskTan : colors.copper;
|
|
33775
|
-
const pourColor = new
|
|
33946
|
+
const pourColor = new THREE25.Color(...pourColorArr);
|
|
33776
33947
|
const threeGeom = manifoldMeshToThreeGeometry(pourOp.getMesh());
|
|
33777
33948
|
copperPourGeoms.push({
|
|
33778
33949
|
key: `coppour-${pour.pcb_copper_pour_id}`,
|
|
@@ -33785,7 +33956,7 @@ function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbT
|
|
|
33785
33956
|
}
|
|
33786
33957
|
|
|
33787
33958
|
// src/utils/manifold/process-cutouts.ts
|
|
33788
|
-
import { su as
|
|
33959
|
+
import { su as su13 } from "@tscircuit/circuit-json-util";
|
|
33789
33960
|
|
|
33790
33961
|
// src/utils/pad-geoms.ts
|
|
33791
33962
|
var RECT_PAD_SEGMENTS2 = 64;
|
|
@@ -33877,7 +34048,7 @@ var arePointsClockwise5 = (points) => {
|
|
|
33877
34048
|
};
|
|
33878
34049
|
function processCutoutsForManifold(Manifold, CrossSection, circuitJson, pcbThickness, manifoldInstancesForCleanup) {
|
|
33879
34050
|
const cutoutOps = [];
|
|
33880
|
-
const pcbCutouts =
|
|
34051
|
+
const pcbCutouts = su13(circuitJson).pcb_cutout.list();
|
|
33881
34052
|
for (const cutout of pcbCutouts) {
|
|
33882
34053
|
let cutoutOp;
|
|
33883
34054
|
const cutoutHeight = pcbThickness * 1.5;
|
|
@@ -33972,7 +34143,7 @@ function processCutoutsForManifold(Manifold, CrossSection, circuitJson, pcbThick
|
|
|
33972
34143
|
}
|
|
33973
34144
|
|
|
33974
34145
|
// src/utils/manifold/process-non-plated-holes.ts
|
|
33975
|
-
import { su as
|
|
34146
|
+
import { su as su14 } from "@tscircuit/circuit-json-util";
|
|
33976
34147
|
|
|
33977
34148
|
// src/utils/hole-geoms.ts
|
|
33978
34149
|
function createCircleHoleDrill({
|
|
@@ -34024,7 +34195,7 @@ function isRotatedPillHole(hole) {
|
|
|
34024
34195
|
}
|
|
34025
34196
|
function processNonPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup) {
|
|
34026
34197
|
const nonPlatedHoleBoardDrills = [];
|
|
34027
|
-
const pcbHoles =
|
|
34198
|
+
const pcbHoles = su14(circuitJson).pcb_hole.list();
|
|
34028
34199
|
const createPillOp = (width10, height10, depth) => {
|
|
34029
34200
|
const pillOp = createRoundedRectPrism({
|
|
34030
34201
|
Manifold,
|
|
@@ -34073,8 +34244,8 @@ function processNonPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, m
|
|
|
34073
34244
|
}
|
|
34074
34245
|
|
|
34075
34246
|
// src/utils/manifold/process-plated-holes.ts
|
|
34076
|
-
import { su as
|
|
34077
|
-
import * as
|
|
34247
|
+
import { su as su15 } from "@tscircuit/circuit-json-util";
|
|
34248
|
+
import * as THREE26 from "three";
|
|
34078
34249
|
var arePointsClockwise6 = (points) => {
|
|
34079
34250
|
let area = 0;
|
|
34080
34251
|
for (let i = 0; i < points.length; i++) {
|
|
@@ -34095,11 +34266,11 @@ var createEllipsePoints = (width10, height10, segments) => {
|
|
|
34095
34266
|
}
|
|
34096
34267
|
return points;
|
|
34097
34268
|
};
|
|
34098
|
-
var COPPER_COLOR = new
|
|
34269
|
+
var COPPER_COLOR = new THREE26.Color(...colors.copper);
|
|
34099
34270
|
var PLATED_HOLE_LIP_HEIGHT = 0.05;
|
|
34100
34271
|
function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
|
|
34101
34272
|
const platedHoleBoardDrills = [];
|
|
34102
|
-
const pcbPlatedHoles =
|
|
34273
|
+
const pcbPlatedHoles = su15(circuitJson).pcb_plated_hole.list();
|
|
34103
34274
|
const platedHoleCopperGeoms = [];
|
|
34104
34275
|
const platedHoleCopperOpsForSubtract = [];
|
|
34105
34276
|
const createPillOp = (width10, height10, depth) => {
|
|
@@ -34668,12 +34839,12 @@ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbT
|
|
|
34668
34839
|
}
|
|
34669
34840
|
|
|
34670
34841
|
// src/utils/manifold/process-smt-pads.ts
|
|
34671
|
-
import { su as
|
|
34672
|
-
import * as
|
|
34673
|
-
var COPPER_COLOR2 = new
|
|
34842
|
+
import { su as su16 } from "@tscircuit/circuit-json-util";
|
|
34843
|
+
import * as THREE27 from "three";
|
|
34844
|
+
var COPPER_COLOR2 = new THREE27.Color(...colors.copper);
|
|
34674
34845
|
function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, holeUnion, boardClipVolume) {
|
|
34675
34846
|
const smtPadGeoms = [];
|
|
34676
|
-
const smtPads =
|
|
34847
|
+
const smtPads = su16(circuitJson).pcb_smtpad.list();
|
|
34677
34848
|
smtPads.forEach((pad2, index2) => {
|
|
34678
34849
|
const padBaseThickness = DEFAULT_SMT_PAD_THICKNESS;
|
|
34679
34850
|
const zPos = pad2.layer === "bottom" ? -pcbThickness / 2 - BOARD_SURFACE_OFFSET.copper : pcbThickness / 2 + BOARD_SURFACE_OFFSET.copper;
|
|
@@ -34708,8 +34879,8 @@ function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifold
|
|
|
34708
34879
|
}
|
|
34709
34880
|
|
|
34710
34881
|
// src/utils/manifold/process-vias.ts
|
|
34711
|
-
import { su as
|
|
34712
|
-
import * as
|
|
34882
|
+
import { su as su17 } from "@tscircuit/circuit-json-util";
|
|
34883
|
+
import * as THREE28 from "three";
|
|
34713
34884
|
|
|
34714
34885
|
// src/utils/via-geoms.ts
|
|
34715
34886
|
function createViaCopper2({
|
|
@@ -34762,10 +34933,10 @@ function createViaCopper2({
|
|
|
34762
34933
|
}
|
|
34763
34934
|
|
|
34764
34935
|
// src/utils/manifold/process-vias.ts
|
|
34765
|
-
var COPPER_COLOR3 = new
|
|
34936
|
+
var COPPER_COLOR3 = new THREE28.Color(...colors.copper);
|
|
34766
34937
|
function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
|
|
34767
34938
|
const viaBoardDrills = [];
|
|
34768
|
-
const pcbVias =
|
|
34939
|
+
const pcbVias = su17(circuitJson).pcb_via.list();
|
|
34769
34940
|
const viaCopperGeoms = [];
|
|
34770
34941
|
pcbVias.forEach((via, index2) => {
|
|
34771
34942
|
if (typeof via.hole_diameter === "number") {
|
|
@@ -34825,26 +34996,28 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
34825
34996
|
const panels = circuitJson.filter(
|
|
34826
34997
|
(e) => e.type === "pcb_panel"
|
|
34827
34998
|
);
|
|
34828
|
-
const boards =
|
|
34999
|
+
const boards = su18(circuitJson).pcb_board.list();
|
|
34829
35000
|
if (panels.length > 0) {
|
|
34830
35001
|
const panel = panels[0];
|
|
35002
|
+
const firstBoardInPanel = boards.find(
|
|
35003
|
+
(b) => b.pcb_panel_id === panel.pcb_panel_id
|
|
35004
|
+
);
|
|
34831
35005
|
return {
|
|
34832
35006
|
type: "pcb_board",
|
|
34833
35007
|
pcb_board_id: panel.pcb_panel_id,
|
|
34834
35008
|
center: panel.center,
|
|
34835
35009
|
width: panel.width,
|
|
34836
35010
|
height: panel.height,
|
|
34837
|
-
thickness: 1.6,
|
|
34838
|
-
|
|
34839
|
-
|
|
34840
|
-
num_layers: 2
|
|
35011
|
+
thickness: firstBoardInPanel?.thickness ?? 1.6,
|
|
35012
|
+
material: firstBoardInPanel?.material ?? "fr4",
|
|
35013
|
+
num_layers: firstBoardInPanel?.num_layers ?? 2
|
|
34841
35014
|
};
|
|
34842
35015
|
}
|
|
34843
35016
|
const boardsNotInPanel = boards.filter((b) => !b.pcb_panel_id);
|
|
34844
35017
|
return boardsNotInPanel.length > 0 ? boardsNotInPanel[0] : null;
|
|
34845
35018
|
}, [circuitJson]);
|
|
34846
35019
|
const isFauxBoard = useMemo21(() => {
|
|
34847
|
-
const boards =
|
|
35020
|
+
const boards = su18(circuitJson).pcb_board.list();
|
|
34848
35021
|
return boards.length > 0 && boards[0].pcb_board_id === "faux-board";
|
|
34849
35022
|
}, [circuitJson]);
|
|
34850
35023
|
useEffect23(() => {
|
|
@@ -34979,7 +35152,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
34979
35152
|
{
|
|
34980
35153
|
key: "plated-holes-union",
|
|
34981
35154
|
geometry: cutPlatedGeom,
|
|
34982
|
-
color: new
|
|
35155
|
+
color: new THREE29.Color(
|
|
34983
35156
|
colors.copper[0],
|
|
34984
35157
|
colors.copper[1],
|
|
34985
35158
|
colors.copper[2]
|
|
@@ -35009,7 +35182,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
35009
35182
|
const matColorArray = boardMaterialColors[boardData.material] ?? colors.fr4Tan;
|
|
35010
35183
|
currentGeoms.board = {
|
|
35011
35184
|
geometry: finalBoardGeom,
|
|
35012
|
-
color: new
|
|
35185
|
+
color: new THREE29.Color(
|
|
35013
35186
|
matColorArray[0],
|
|
35014
35187
|
matColorArray[1],
|
|
35015
35188
|
matColorArray[2]
|
|
@@ -35118,6 +35291,18 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
35118
35291
|
copperColor,
|
|
35119
35292
|
traceTextureResolution: TRACE_TEXTURE_RESOLUTION
|
|
35120
35293
|
});
|
|
35294
|
+
currentTextures.topPanelOutlines = createPanelOutlineTextureForLayer({
|
|
35295
|
+
layer: "top",
|
|
35296
|
+
circuitJson,
|
|
35297
|
+
panelData: boardData,
|
|
35298
|
+
traceTextureResolution: TRACE_TEXTURE_RESOLUTION
|
|
35299
|
+
});
|
|
35300
|
+
currentTextures.bottomPanelOutlines = createPanelOutlineTextureForLayer({
|
|
35301
|
+
layer: "bottom",
|
|
35302
|
+
circuitJson,
|
|
35303
|
+
panelData: boardData,
|
|
35304
|
+
traceTextureResolution: TRACE_TEXTURE_RESOLUTION
|
|
35305
|
+
});
|
|
35121
35306
|
setTextures(currentTextures);
|
|
35122
35307
|
} catch (e) {
|
|
35123
35308
|
console.error("Error processing geometry with Manifold in hook:", e);
|
|
@@ -35146,11 +35331,11 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
35146
35331
|
};
|
|
35147
35332
|
|
|
35148
35333
|
// src/utils/manifold/create-three-geometry-meshes.ts
|
|
35149
|
-
import * as
|
|
35334
|
+
import * as THREE31 from "three";
|
|
35150
35335
|
|
|
35151
35336
|
// src/utils/create-board-material.ts
|
|
35152
|
-
import * as
|
|
35153
|
-
var DEFAULT_SIDE =
|
|
35337
|
+
import * as THREE30 from "three";
|
|
35338
|
+
var DEFAULT_SIDE = THREE30.DoubleSide;
|
|
35154
35339
|
var createBoardMaterial = ({
|
|
35155
35340
|
material,
|
|
35156
35341
|
color,
|
|
@@ -35158,7 +35343,7 @@ var createBoardMaterial = ({
|
|
|
35158
35343
|
isFaux = false
|
|
35159
35344
|
}) => {
|
|
35160
35345
|
if (material === "fr4") {
|
|
35161
|
-
return new
|
|
35346
|
+
return new THREE30.MeshPhysicalMaterial({
|
|
35162
35347
|
color,
|
|
35163
35348
|
side,
|
|
35164
35349
|
metalness: 0,
|
|
@@ -35172,7 +35357,7 @@ var createBoardMaterial = ({
|
|
|
35172
35357
|
flatShading: true
|
|
35173
35358
|
});
|
|
35174
35359
|
}
|
|
35175
|
-
return new
|
|
35360
|
+
return new THREE30.MeshStandardMaterial({
|
|
35176
35361
|
color,
|
|
35177
35362
|
side,
|
|
35178
35363
|
flatShading: true,
|
|
@@ -35188,12 +35373,12 @@ function createGeometryMeshes(geoms) {
|
|
|
35188
35373
|
const meshes = [];
|
|
35189
35374
|
if (!geoms) return meshes;
|
|
35190
35375
|
if (geoms.board && geoms.board.geometry) {
|
|
35191
|
-
const mesh = new
|
|
35376
|
+
const mesh = new THREE31.Mesh(
|
|
35192
35377
|
geoms.board.geometry,
|
|
35193
35378
|
createBoardMaterial({
|
|
35194
35379
|
material: geoms.board.material,
|
|
35195
35380
|
color: geoms.board.color,
|
|
35196
|
-
side:
|
|
35381
|
+
side: THREE31.DoubleSide,
|
|
35197
35382
|
isFaux: geoms.board.isFaux
|
|
35198
35383
|
})
|
|
35199
35384
|
);
|
|
@@ -35203,11 +35388,11 @@ function createGeometryMeshes(geoms) {
|
|
|
35203
35388
|
const createMeshesFromArray = (geomArray) => {
|
|
35204
35389
|
if (geomArray) {
|
|
35205
35390
|
geomArray.forEach((comp) => {
|
|
35206
|
-
const mesh = new
|
|
35391
|
+
const mesh = new THREE31.Mesh(
|
|
35207
35392
|
comp.geometry,
|
|
35208
|
-
new
|
|
35393
|
+
new THREE31.MeshStandardMaterial({
|
|
35209
35394
|
color: comp.color,
|
|
35210
|
-
side:
|
|
35395
|
+
side: THREE31.DoubleSide,
|
|
35211
35396
|
flatShading: true,
|
|
35212
35397
|
// Consistent with board
|
|
35213
35398
|
polygonOffset: true,
|
|
@@ -35228,25 +35413,24 @@ function createGeometryMeshes(geoms) {
|
|
|
35228
35413
|
}
|
|
35229
35414
|
|
|
35230
35415
|
// src/utils/manifold/create-three-texture-meshes.ts
|
|
35231
|
-
import * as
|
|
35416
|
+
import * as THREE32 from "three";
|
|
35232
35417
|
function createTextureMeshes(textures, boardData, pcbThickness) {
|
|
35233
35418
|
const meshes = [];
|
|
35234
35419
|
if (!textures || !boardData || pcbThickness === null) return meshes;
|
|
35235
35420
|
const createTexturePlane = (texture, yOffset, isBottomLayer, keySuffix, usePolygonOffset = false, renderOrder = 0) => {
|
|
35236
35421
|
if (!texture) return null;
|
|
35237
|
-
const planeGeom = new
|
|
35238
|
-
const material = new
|
|
35422
|
+
const planeGeom = new THREE32.PlaneGeometry(boardData.width, boardData.height);
|
|
35423
|
+
const material = new THREE32.MeshBasicMaterial({
|
|
35239
35424
|
map: texture,
|
|
35240
35425
|
transparent: true,
|
|
35241
|
-
side:
|
|
35242
|
-
depthWrite:
|
|
35243
|
-
// Important for layers to avoid z-fighting issues with board itself
|
|
35426
|
+
side: THREE32.DoubleSide,
|
|
35427
|
+
depthWrite: keySuffix === "panel-outlines",
|
|
35244
35428
|
polygonOffset: usePolygonOffset,
|
|
35245
35429
|
polygonOffsetFactor: usePolygonOffset ? -4 : 0,
|
|
35246
35430
|
// Increased for better z-fighting prevention
|
|
35247
35431
|
polygonOffsetUnits: usePolygonOffset ? -4 : 0
|
|
35248
35432
|
});
|
|
35249
|
-
const mesh = new
|
|
35433
|
+
const mesh = new THREE32.Mesh(planeGeom, material);
|
|
35250
35434
|
mesh.position.set(boardData.center.x, boardData.center.y, yOffset);
|
|
35251
35435
|
if (isBottomLayer) {
|
|
35252
35436
|
mesh.rotation.set(Math.PI, 0, 0);
|
|
@@ -35362,6 +35546,26 @@ function createTextureMeshes(textures, boardData, pcbThickness) {
|
|
|
35362
35546
|
// Render after soldermask
|
|
35363
35547
|
);
|
|
35364
35548
|
if (bottomCopperTextMesh) meshes.push(bottomCopperTextMesh);
|
|
35549
|
+
const topPanelOutlinesMesh = createTexturePlane(
|
|
35550
|
+
textures.topPanelOutlines,
|
|
35551
|
+
pcbThickness / 2 + 4e-3,
|
|
35552
|
+
// Above silkscreen
|
|
35553
|
+
false,
|
|
35554
|
+
"panel-outlines",
|
|
35555
|
+
false,
|
|
35556
|
+
4
|
|
35557
|
+
);
|
|
35558
|
+
if (topPanelOutlinesMesh) meshes.push(topPanelOutlinesMesh);
|
|
35559
|
+
const bottomPanelOutlinesMesh = createTexturePlane(
|
|
35560
|
+
textures.bottomPanelOutlines,
|
|
35561
|
+
-pcbThickness / 2 - 4e-3,
|
|
35562
|
+
// Below bottom silkscreen
|
|
35563
|
+
true,
|
|
35564
|
+
"panel-outlines",
|
|
35565
|
+
false,
|
|
35566
|
+
4
|
|
35567
|
+
);
|
|
35568
|
+
if (bottomPanelOutlinesMesh) meshes.push(bottomPanelOutlinesMesh);
|
|
35365
35569
|
return meshes;
|
|
35366
35570
|
}
|
|
35367
35571
|
|
|
@@ -35418,6 +35622,8 @@ var BoardMeshes = ({
|
|
|
35418
35622
|
shouldShow = visibility.topCopper;
|
|
35419
35623
|
} else if (mesh.name.includes("bottom-copper-text")) {
|
|
35420
35624
|
shouldShow = visibility.bottomCopper;
|
|
35625
|
+
} else if (mesh.name.includes("panel-outlines")) {
|
|
35626
|
+
shouldShow = visibility.boardBody;
|
|
35421
35627
|
}
|
|
35422
35628
|
if (shouldShow) {
|
|
35423
35629
|
rootObject.add(mesh);
|
|
@@ -35530,7 +35736,7 @@ try {
|
|
|
35530
35736
|
[textures, boardData, pcbThickness]
|
|
35531
35737
|
);
|
|
35532
35738
|
const cadComponents = useMemo22(
|
|
35533
|
-
() =>
|
|
35739
|
+
() => su19(circuitJson).cad_component.list(),
|
|
35534
35740
|
[circuitJson]
|
|
35535
35741
|
);
|
|
35536
35742
|
const boardDimensions = useMemo22(() => {
|
|
@@ -42272,7 +42478,7 @@ var KeyboardShortcutsDialog = ({
|
|
|
42272
42478
|
|
|
42273
42479
|
// src/CadViewer.tsx
|
|
42274
42480
|
import { jsx as jsx37, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
42275
|
-
var DEFAULT_TARGET = new
|
|
42481
|
+
var DEFAULT_TARGET = new THREE33.Vector3(0, 0, 0);
|
|
42276
42482
|
var INITIAL_CAMERA_POSITION = [5, -5, 5];
|
|
42277
42483
|
var CadViewerInner = (props) => {
|
|
42278
42484
|
const [engine, setEngine] = useState35("manifold");
|
|
@@ -42538,12 +42744,12 @@ var CadViewer = (props) => {
|
|
|
42538
42744
|
|
|
42539
42745
|
// src/convert-circuit-json-to-3d-svg.ts
|
|
42540
42746
|
var import_debug = __toESM(require_browser(), 1);
|
|
42541
|
-
import { su as
|
|
42542
|
-
import * as
|
|
42747
|
+
import { su as su20 } from "@tscircuit/circuit-json-util";
|
|
42748
|
+
import * as THREE37 from "three";
|
|
42543
42749
|
import { SVGRenderer } from "three/examples/jsm/renderers/SVGRenderer.js";
|
|
42544
42750
|
|
|
42545
42751
|
// src/utils/create-geometry-from-polygons.ts
|
|
42546
|
-
import * as
|
|
42752
|
+
import * as THREE34 from "three";
|
|
42547
42753
|
import { BufferGeometry as BufferGeometry3, Float32BufferAttribute as Float32BufferAttribute2 } from "three";
|
|
42548
42754
|
function createGeometryFromPolygons(polygons) {
|
|
42549
42755
|
const geometry = new BufferGeometry3();
|
|
@@ -42557,12 +42763,12 @@ function createGeometryFromPolygons(polygons) {
|
|
|
42557
42763
|
...polygon3.vertices[i + 1]
|
|
42558
42764
|
// Third vertex
|
|
42559
42765
|
);
|
|
42560
|
-
const v1 = new
|
|
42561
|
-
const v2 = new
|
|
42562
|
-
const v3 = new
|
|
42563
|
-
const normal = new
|
|
42564
|
-
new
|
|
42565
|
-
new
|
|
42766
|
+
const v1 = new THREE34.Vector3(...polygon3.vertices[0]);
|
|
42767
|
+
const v2 = new THREE34.Vector3(...polygon3.vertices[i]);
|
|
42768
|
+
const v3 = new THREE34.Vector3(...polygon3.vertices[i + 1]);
|
|
42769
|
+
const normal = new THREE34.Vector3().crossVectors(
|
|
42770
|
+
new THREE34.Vector3().subVectors(v2, v1),
|
|
42771
|
+
new THREE34.Vector3().subVectors(v3, v1)
|
|
42566
42772
|
).normalize();
|
|
42567
42773
|
normals.push(
|
|
42568
42774
|
normal.x,
|
|
@@ -42586,10 +42792,10 @@ function createGeometryFromPolygons(polygons) {
|
|
|
42586
42792
|
var import_modeling2 = __toESM(require_src(), 1);
|
|
42587
42793
|
var import_jscad_planner2 = __toESM(require_dist(), 1);
|
|
42588
42794
|
var jscadModeling2 = __toESM(require_src(), 1);
|
|
42589
|
-
import * as
|
|
42795
|
+
import * as THREE36 from "three";
|
|
42590
42796
|
|
|
42591
42797
|
// src/utils/load-model.ts
|
|
42592
|
-
import * as
|
|
42798
|
+
import * as THREE35 from "three";
|
|
42593
42799
|
import { GLTFLoader as GLTFLoader2 } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
42594
42800
|
import { OBJLoader as OBJLoader2 } from "three/examples/jsm/loaders/OBJLoader.js";
|
|
42595
42801
|
import { STLLoader as STLLoader2 } from "three/examples/jsm/loaders/STLLoader.js";
|
|
@@ -42597,12 +42803,12 @@ async function load3DModel(url) {
|
|
|
42597
42803
|
if (url.endsWith(".stl")) {
|
|
42598
42804
|
const loader = new STLLoader2();
|
|
42599
42805
|
const geometry = await loader.loadAsync(url);
|
|
42600
|
-
const material = new
|
|
42806
|
+
const material = new THREE35.MeshStandardMaterial({
|
|
42601
42807
|
color: 8947848,
|
|
42602
42808
|
metalness: 0.5,
|
|
42603
42809
|
roughness: 0.5
|
|
42604
42810
|
});
|
|
42605
|
-
return new
|
|
42811
|
+
return new THREE35.Mesh(geometry, material);
|
|
42606
42812
|
}
|
|
42607
42813
|
if (url.endsWith(".obj")) {
|
|
42608
42814
|
const loader = new OBJLoader2();
|
|
@@ -42635,9 +42841,9 @@ async function renderComponent(component, scene) {
|
|
|
42635
42841
|
}
|
|
42636
42842
|
if (component.rotation) {
|
|
42637
42843
|
model.rotation.set(
|
|
42638
|
-
|
|
42639
|
-
|
|
42640
|
-
|
|
42844
|
+
THREE36.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
42845
|
+
THREE36.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
42846
|
+
THREE36.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
42641
42847
|
);
|
|
42642
42848
|
}
|
|
42643
42849
|
scene.add(model);
|
|
@@ -42651,13 +42857,13 @@ async function renderComponent(component, scene) {
|
|
|
42651
42857
|
);
|
|
42652
42858
|
if (jscadObject && (jscadObject.polygons || jscadObject.sides)) {
|
|
42653
42859
|
const threeGeom = convertCSGToThreeGeom(jscadObject);
|
|
42654
|
-
const material2 = new
|
|
42860
|
+
const material2 = new THREE36.MeshStandardMaterial({
|
|
42655
42861
|
color: 8947848,
|
|
42656
42862
|
metalness: 0.5,
|
|
42657
42863
|
roughness: 0.5,
|
|
42658
|
-
side:
|
|
42864
|
+
side: THREE36.DoubleSide
|
|
42659
42865
|
});
|
|
42660
|
-
const mesh2 = new
|
|
42866
|
+
const mesh2 = new THREE36.Mesh(threeGeom, material2);
|
|
42661
42867
|
if (component.position) {
|
|
42662
42868
|
mesh2.position.set(
|
|
42663
42869
|
component.position.x ?? 0,
|
|
@@ -42667,9 +42873,9 @@ async function renderComponent(component, scene) {
|
|
|
42667
42873
|
}
|
|
42668
42874
|
if (component.rotation) {
|
|
42669
42875
|
mesh2.rotation.set(
|
|
42670
|
-
|
|
42671
|
-
|
|
42672
|
-
|
|
42876
|
+
THREE36.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
42877
|
+
THREE36.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
42878
|
+
THREE36.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
42673
42879
|
);
|
|
42674
42880
|
}
|
|
42675
42881
|
scene.add(mesh2);
|
|
@@ -42686,17 +42892,17 @@ async function renderComponent(component, scene) {
|
|
|
42686
42892
|
if (!geom || !geom.polygons && !geom.sides) {
|
|
42687
42893
|
continue;
|
|
42688
42894
|
}
|
|
42689
|
-
const color = new
|
|
42895
|
+
const color = new THREE36.Color(geomInfo.color);
|
|
42690
42896
|
color.convertLinearToSRGB();
|
|
42691
42897
|
const geomWithColor = { ...geom, color: [color.r, color.g, color.b] };
|
|
42692
42898
|
const threeGeom = convertCSGToThreeGeom(geomWithColor);
|
|
42693
|
-
const material2 = new
|
|
42899
|
+
const material2 = new THREE36.MeshStandardMaterial({
|
|
42694
42900
|
vertexColors: true,
|
|
42695
42901
|
metalness: 0.2,
|
|
42696
42902
|
roughness: 0.8,
|
|
42697
|
-
side:
|
|
42903
|
+
side: THREE36.DoubleSide
|
|
42698
42904
|
});
|
|
42699
|
-
const mesh2 = new
|
|
42905
|
+
const mesh2 = new THREE36.Mesh(threeGeom, material2);
|
|
42700
42906
|
if (component.position) {
|
|
42701
42907
|
mesh2.position.set(
|
|
42702
42908
|
component.position.x ?? 0,
|
|
@@ -42706,22 +42912,22 @@ async function renderComponent(component, scene) {
|
|
|
42706
42912
|
}
|
|
42707
42913
|
if (component.rotation) {
|
|
42708
42914
|
mesh2.rotation.set(
|
|
42709
|
-
|
|
42710
|
-
|
|
42711
|
-
|
|
42915
|
+
THREE36.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
42916
|
+
THREE36.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
42917
|
+
THREE36.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
42712
42918
|
);
|
|
42713
42919
|
}
|
|
42714
42920
|
scene.add(mesh2);
|
|
42715
42921
|
}
|
|
42716
42922
|
return;
|
|
42717
42923
|
}
|
|
42718
|
-
const geometry = new
|
|
42719
|
-
const material = new
|
|
42924
|
+
const geometry = new THREE36.BoxGeometry(0.5, 0.5, 0.5);
|
|
42925
|
+
const material = new THREE36.MeshStandardMaterial({
|
|
42720
42926
|
color: 16711680,
|
|
42721
42927
|
transparent: true,
|
|
42722
42928
|
opacity: 0.25
|
|
42723
42929
|
});
|
|
42724
|
-
const mesh = new
|
|
42930
|
+
const mesh = new THREE36.Mesh(geometry, material);
|
|
42725
42931
|
if (component.position) {
|
|
42726
42932
|
mesh.position.set(
|
|
42727
42933
|
component.position.x ?? 0,
|
|
@@ -42742,11 +42948,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
42742
42948
|
padding = 20,
|
|
42743
42949
|
zoom = 1.5
|
|
42744
42950
|
} = options;
|
|
42745
|
-
const scene = new
|
|
42951
|
+
const scene = new THREE37.Scene();
|
|
42746
42952
|
const renderer = new SVGRenderer();
|
|
42747
42953
|
renderer.setSize(width10, height10);
|
|
42748
|
-
renderer.setClearColor(new
|
|
42749
|
-
const camera = new
|
|
42954
|
+
renderer.setClearColor(new THREE37.Color(backgroundColor), 1);
|
|
42955
|
+
const camera = new THREE37.OrthographicCamera();
|
|
42750
42956
|
const aspect = width10 / height10;
|
|
42751
42957
|
const frustumSize = 100;
|
|
42752
42958
|
const halfFrustumSize = frustumSize / 2 / zoom;
|
|
@@ -42760,22 +42966,22 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
42760
42966
|
camera.position.set(position.x, position.y, position.z);
|
|
42761
42967
|
camera.up.set(0, 1, 0);
|
|
42762
42968
|
const lookAt = options.camera?.lookAt ?? { x: 0, y: 0, z: 0 };
|
|
42763
|
-
camera.lookAt(new
|
|
42969
|
+
camera.lookAt(new THREE37.Vector3(lookAt.x, lookAt.y, lookAt.z));
|
|
42764
42970
|
camera.updateProjectionMatrix();
|
|
42765
|
-
const ambientLight = new
|
|
42971
|
+
const ambientLight = new THREE37.AmbientLight(16777215, Math.PI / 2);
|
|
42766
42972
|
scene.add(ambientLight);
|
|
42767
|
-
const pointLight = new
|
|
42973
|
+
const pointLight = new THREE37.PointLight(16777215, Math.PI / 4);
|
|
42768
42974
|
pointLight.position.set(-10, -10, 10);
|
|
42769
42975
|
scene.add(pointLight);
|
|
42770
|
-
const components =
|
|
42976
|
+
const components = su20(circuitJson).cad_component.list();
|
|
42771
42977
|
for (const component of components) {
|
|
42772
42978
|
await renderComponent(component, scene);
|
|
42773
42979
|
}
|
|
42774
|
-
const boardData =
|
|
42980
|
+
const boardData = su20(circuitJson).pcb_board.list()[0];
|
|
42775
42981
|
const boardGeom = createBoardGeomFromCircuitJson(circuitJson);
|
|
42776
42982
|
if (boardGeom) {
|
|
42777
42983
|
const solderMaskColor = colors.fr4SolderMaskGreen;
|
|
42778
|
-
const baseColor = new
|
|
42984
|
+
const baseColor = new THREE37.Color(
|
|
42779
42985
|
solderMaskColor[0],
|
|
42780
42986
|
solderMaskColor[1],
|
|
42781
42987
|
solderMaskColor[2]
|
|
@@ -42787,28 +42993,28 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
42787
42993
|
const material = createBoardMaterial({
|
|
42788
42994
|
material: boardData?.material,
|
|
42789
42995
|
color: baseColor,
|
|
42790
|
-
side:
|
|
42996
|
+
side: THREE37.DoubleSide
|
|
42791
42997
|
});
|
|
42792
|
-
const mesh = new
|
|
42998
|
+
const mesh = new THREE37.Mesh(geometry, material);
|
|
42793
42999
|
scene.add(mesh);
|
|
42794
43000
|
}
|
|
42795
43001
|
}
|
|
42796
|
-
const gridColor = new
|
|
42797
|
-
const gridHelper = new
|
|
43002
|
+
const gridColor = new THREE37.Color(8947848);
|
|
43003
|
+
const gridHelper = new THREE37.GridHelper(100, 100, gridColor, gridColor);
|
|
42798
43004
|
gridHelper.rotation.x = Math.PI / 2;
|
|
42799
43005
|
const materials = Array.isArray(gridHelper.material) ? gridHelper.material : [gridHelper.material];
|
|
42800
43006
|
for (const mat of materials) {
|
|
42801
43007
|
mat.transparent = true;
|
|
42802
43008
|
mat.opacity = 0.3;
|
|
42803
|
-
if (mat instanceof
|
|
43009
|
+
if (mat instanceof THREE37.LineBasicMaterial) {
|
|
42804
43010
|
mat.color = gridColor;
|
|
42805
43011
|
mat.vertexColors = false;
|
|
42806
43012
|
}
|
|
42807
43013
|
}
|
|
42808
43014
|
scene.add(gridHelper);
|
|
42809
|
-
const box = new
|
|
42810
|
-
const center = box.getCenter(new
|
|
42811
|
-
const size5 = box.getSize(new
|
|
43015
|
+
const box = new THREE37.Box3().setFromObject(scene);
|
|
43016
|
+
const center = box.getCenter(new THREE37.Vector3());
|
|
43017
|
+
const size5 = box.getSize(new THREE37.Vector3());
|
|
42812
43018
|
scene.position.sub(center);
|
|
42813
43019
|
const maxDim = Math.max(size5.x, size5.y, size5.z);
|
|
42814
43020
|
if (maxDim > 0) {
|