@tscircuit/3d-viewer 0.0.406 → 0.0.408
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 +1 -0
- package/dist/index.js +204 -125
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -26100,7 +26100,7 @@ import * as THREE13 from "three";
|
|
|
26100
26100
|
// package.json
|
|
26101
26101
|
var package_default = {
|
|
26102
26102
|
name: "@tscircuit/3d-viewer",
|
|
26103
|
-
version: "0.0.
|
|
26103
|
+
version: "0.0.407",
|
|
26104
26104
|
main: "./dist/index.js",
|
|
26105
26105
|
module: "./dist/index.js",
|
|
26106
26106
|
type: "module",
|
|
@@ -26879,7 +26879,7 @@ import { su as su2 } from "@tscircuit/circuit-json-util";
|
|
|
26879
26879
|
var M = 0.01;
|
|
26880
26880
|
var colors = {
|
|
26881
26881
|
copper: [0.9, 0.6, 0.2],
|
|
26882
|
-
fr4Green: [
|
|
26882
|
+
fr4Green: [0.04, 0.16, 0.08],
|
|
26883
26883
|
fr4GreenSolderWithMask: [0 / 255, 152 / 255, 19 / 255],
|
|
26884
26884
|
fr1Copper: [0.8, 0.4, 0.2],
|
|
26885
26885
|
fr1CopperSolderWithMask: [0.9, 0.6, 0.2]
|
|
@@ -28930,6 +28930,20 @@ function createPadManifoldOp({
|
|
|
28930
28930
|
thickness: padBaseThickness,
|
|
28931
28931
|
borderRadius: rectBorderRadius
|
|
28932
28932
|
});
|
|
28933
|
+
} else if (pad2.shape === "rotated_rect") {
|
|
28934
|
+
const rectBorderRadius = extractRectBorderRadius(pad2);
|
|
28935
|
+
let padOp = createRoundedRectPrism({
|
|
28936
|
+
Manifold,
|
|
28937
|
+
width: pad2.width,
|
|
28938
|
+
height: pad2.height,
|
|
28939
|
+
thickness: padBaseThickness,
|
|
28940
|
+
borderRadius: rectBorderRadius
|
|
28941
|
+
});
|
|
28942
|
+
const rotation2 = pad2.ccw_rotation ?? 0;
|
|
28943
|
+
if (rotation2) {
|
|
28944
|
+
padOp = padOp.rotate([0, 0, rotation2]);
|
|
28945
|
+
}
|
|
28946
|
+
return padOp;
|
|
28933
28947
|
} else if (pad2.shape === "circle" && pad2.radius) {
|
|
28934
28948
|
return Manifold.cylinder(padBaseThickness, pad2.radius, -1, 32, true);
|
|
28935
28949
|
}
|
|
@@ -28938,10 +28952,22 @@ function createPadManifoldOp({
|
|
|
28938
28952
|
|
|
28939
28953
|
// src/utils/manifold/process-plated-holes.ts
|
|
28940
28954
|
var COPPER_COLOR = new THREE19.Color(...colors.copper);
|
|
28955
|
+
var PLATED_HOLE_LIP_HEIGHT = 0.05;
|
|
28941
28956
|
function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup) {
|
|
28942
28957
|
const platedHoleBoardDrills = [];
|
|
28943
28958
|
const pcbPlatedHoles = su8(circuitJson).pcb_plated_hole.list();
|
|
28944
28959
|
const platedHoleCopperGeoms = [];
|
|
28960
|
+
const createPillOp = (width10, height10, depth) => {
|
|
28961
|
+
const pillOp = createRoundedRectPrism({
|
|
28962
|
+
Manifold,
|
|
28963
|
+
width: width10,
|
|
28964
|
+
height: height10,
|
|
28965
|
+
thickness: depth,
|
|
28966
|
+
borderRadius: Math.min(width10, height10) / 2
|
|
28967
|
+
});
|
|
28968
|
+
manifoldInstancesForCleanup.push(pillOp);
|
|
28969
|
+
return pillOp;
|
|
28970
|
+
};
|
|
28945
28971
|
pcbPlatedHoles.forEach((ph, index) => {
|
|
28946
28972
|
if (ph.shape === "circle") {
|
|
28947
28973
|
const translatedDrill = createPlatedHoleDrill({
|
|
@@ -28987,60 +29013,15 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
|
|
|
28987
29013
|
color: COPPER_COLOR
|
|
28988
29014
|
});
|
|
28989
29015
|
} else if (ph.shape === "pill") {
|
|
28990
|
-
const
|
|
28991
|
-
const
|
|
28992
|
-
const shouldRotate = holeHeightRaw > holeWidthRaw;
|
|
28993
|
-
const holeW = shouldRotate ? holeHeightRaw : holeWidthRaw;
|
|
28994
|
-
const holeH = shouldRotate ? holeWidthRaw : holeHeightRaw;
|
|
29016
|
+
const holeW = ph.hole_width;
|
|
29017
|
+
const holeH = ph.hole_height;
|
|
28995
29018
|
const defaultPadExtension = 0.4;
|
|
28996
|
-
const outerW =
|
|
28997
|
-
const outerH =
|
|
28998
|
-
const createPill = (width10, height10, depth) => {
|
|
28999
|
-
const radius = height10 / 2;
|
|
29000
|
-
const rectLength = width10 - height10;
|
|
29001
|
-
let pillOp;
|
|
29002
|
-
if (rectLength < 1e-9) {
|
|
29003
|
-
pillOp = Manifold.cylinder(
|
|
29004
|
-
depth,
|
|
29005
|
-
radius,
|
|
29006
|
-
radius,
|
|
29007
|
-
SMOOTH_CIRCLE_SEGMENTS,
|
|
29008
|
-
true
|
|
29009
|
-
);
|
|
29010
|
-
} else {
|
|
29011
|
-
const rect = Manifold.cube(
|
|
29012
|
-
[Math.max(0, rectLength), height10, depth],
|
|
29013
|
-
true
|
|
29014
|
-
);
|
|
29015
|
-
const cap1 = Manifold.cylinder(
|
|
29016
|
-
depth,
|
|
29017
|
-
radius,
|
|
29018
|
-
radius,
|
|
29019
|
-
SMOOTH_CIRCLE_SEGMENTS,
|
|
29020
|
-
true
|
|
29021
|
-
).translate([-rectLength / 2, 0, 0]);
|
|
29022
|
-
const cap2 = Manifold.cylinder(
|
|
29023
|
-
depth,
|
|
29024
|
-
radius,
|
|
29025
|
-
radius,
|
|
29026
|
-
SMOOTH_CIRCLE_SEGMENTS,
|
|
29027
|
-
true
|
|
29028
|
-
).translate([rectLength / 2, 0, 0]);
|
|
29029
|
-
pillOp = Manifold.union([rect, cap1, cap2]);
|
|
29030
|
-
manifoldInstancesForCleanup.push(rect, cap1, cap2);
|
|
29031
|
-
}
|
|
29032
|
-
manifoldInstancesForCleanup.push(pillOp);
|
|
29033
|
-
return pillOp;
|
|
29034
|
-
};
|
|
29019
|
+
const outerW = ph.outer_width ?? holeW + defaultPadExtension;
|
|
29020
|
+
const outerH = ph.outer_height ?? holeH + defaultPadExtension;
|
|
29035
29021
|
const drillW = holeW + 2 * MANIFOLD_Z_OFFSET;
|
|
29036
29022
|
const drillH = holeH + 2 * MANIFOLD_Z_OFFSET;
|
|
29037
29023
|
const drillDepth = pcbThickness * 1.2;
|
|
29038
|
-
let boardPillDrillOp =
|
|
29039
|
-
if (shouldRotate) {
|
|
29040
|
-
const rotatedOp = boardPillDrillOp.rotate([0, 0, 90]);
|
|
29041
|
-
manifoldInstancesForCleanup.push(rotatedOp);
|
|
29042
|
-
boardPillDrillOp = rotatedOp;
|
|
29043
|
-
}
|
|
29024
|
+
let boardPillDrillOp = createPillOp(drillW, drillH, drillDepth);
|
|
29044
29025
|
if (ph.ccw_rotation) {
|
|
29045
29026
|
const rotatedOp = boardPillDrillOp.rotate([0, 0, ph.ccw_rotation]);
|
|
29046
29027
|
manifoldInstancesForCleanup.push(rotatedOp);
|
|
@@ -29054,12 +29035,12 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
|
|
|
29054
29035
|
manifoldInstancesForCleanup.push(translatedBoardPillDrill);
|
|
29055
29036
|
platedHoleBoardDrills.push(translatedBoardPillDrill);
|
|
29056
29037
|
const copperPartThickness = pcbThickness + 2 * MANIFOLD_Z_OFFSET;
|
|
29057
|
-
const outerCopperOpUnrotated =
|
|
29038
|
+
const outerCopperOpUnrotated = createPillOp(
|
|
29058
29039
|
outerW,
|
|
29059
29040
|
outerH,
|
|
29060
29041
|
copperPartThickness
|
|
29061
29042
|
);
|
|
29062
|
-
const innerDrillOpUnrotated =
|
|
29043
|
+
const innerDrillOpUnrotated = createPillOp(
|
|
29063
29044
|
holeW,
|
|
29064
29045
|
holeH,
|
|
29065
29046
|
copperPartThickness * 1.05
|
|
@@ -29069,11 +29050,6 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
|
|
|
29069
29050
|
innerDrillOpUnrotated
|
|
29070
29051
|
);
|
|
29071
29052
|
manifoldInstancesForCleanup.push(finalPlatedPartOp);
|
|
29072
|
-
if (shouldRotate) {
|
|
29073
|
-
const rotatedOp = finalPlatedPartOp.rotate([0, 0, 90]);
|
|
29074
|
-
manifoldInstancesForCleanup.push(rotatedOp);
|
|
29075
|
-
finalPlatedPartOp = rotatedOp;
|
|
29076
|
-
}
|
|
29077
29053
|
if (ph.ccw_rotation) {
|
|
29078
29054
|
const rotatedOp = finalPlatedPartOp.rotate([0, 0, ph.ccw_rotation]);
|
|
29079
29055
|
manifoldInstancesForCleanup.push(rotatedOp);
|
|
@@ -29089,6 +29065,73 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
|
|
|
29089
29065
|
geometry: threeGeom,
|
|
29090
29066
|
color: COPPER_COLOR
|
|
29091
29067
|
});
|
|
29068
|
+
} else if (ph.shape === "pill_hole_with_rect_pad") {
|
|
29069
|
+
const holeW = ph.hole_width;
|
|
29070
|
+
const holeH = ph.hole_height;
|
|
29071
|
+
const padWidth = ph.rect_pad_width;
|
|
29072
|
+
const padHeight = ph.rect_pad_height;
|
|
29073
|
+
const rectBorderRadius = extractRectBorderRadius(ph);
|
|
29074
|
+
const padThickness = DEFAULT_SMT_PAD_THICKNESS;
|
|
29075
|
+
const drillW = holeW + 2 * MANIFOLD_Z_OFFSET;
|
|
29076
|
+
const drillH = holeH + 2 * MANIFOLD_Z_OFFSET;
|
|
29077
|
+
const drillDepth = pcbThickness * 1.2;
|
|
29078
|
+
let boardPillDrillOp = createPillOp(drillW, drillH, drillDepth);
|
|
29079
|
+
const translatedBoardPillDrill = boardPillDrillOp.translate([
|
|
29080
|
+
ph.x,
|
|
29081
|
+
ph.y,
|
|
29082
|
+
0
|
|
29083
|
+
]);
|
|
29084
|
+
manifoldInstancesForCleanup.push(translatedBoardPillDrill);
|
|
29085
|
+
platedHoleBoardDrills.push(translatedBoardPillDrill);
|
|
29086
|
+
let copperBarrelOp = createPillOp(
|
|
29087
|
+
holeW,
|
|
29088
|
+
holeH,
|
|
29089
|
+
pcbThickness + 2 * MANIFOLD_Z_OFFSET
|
|
29090
|
+
);
|
|
29091
|
+
let topPadOp = createRoundedRectPrism({
|
|
29092
|
+
Manifold,
|
|
29093
|
+
width: padWidth,
|
|
29094
|
+
height: padHeight,
|
|
29095
|
+
thickness: padThickness,
|
|
29096
|
+
borderRadius: rectBorderRadius
|
|
29097
|
+
});
|
|
29098
|
+
manifoldInstancesForCleanup.push(topPadOp);
|
|
29099
|
+
let bottomPadOp = createRoundedRectPrism({
|
|
29100
|
+
Manifold,
|
|
29101
|
+
width: padWidth,
|
|
29102
|
+
height: padHeight,
|
|
29103
|
+
thickness: padThickness,
|
|
29104
|
+
borderRadius: rectBorderRadius
|
|
29105
|
+
});
|
|
29106
|
+
manifoldInstancesForCleanup.push(bottomPadOp);
|
|
29107
|
+
const topPadZ = pcbThickness / 2 + padThickness / 2 + MANIFOLD_Z_OFFSET;
|
|
29108
|
+
const bottomPadZ = -pcbThickness / 2 - padThickness / 2 - MANIFOLD_Z_OFFSET;
|
|
29109
|
+
topPadOp = topPadOp.translate([0, 0, topPadZ]);
|
|
29110
|
+
manifoldInstancesForCleanup.push(topPadOp);
|
|
29111
|
+
bottomPadOp = bottomPadOp.translate([0, 0, bottomPadZ]);
|
|
29112
|
+
manifoldInstancesForCleanup.push(bottomPadOp);
|
|
29113
|
+
const copperUnionBeforeCut = Manifold.union([
|
|
29114
|
+
copperBarrelOp,
|
|
29115
|
+
topPadOp,
|
|
29116
|
+
bottomPadOp
|
|
29117
|
+
]);
|
|
29118
|
+
manifoldInstancesForCleanup.push(copperUnionBeforeCut);
|
|
29119
|
+
const holeCutWidth = Math.max(holeW - 2 * PLATED_HOLE_LIP_HEIGHT, 0.01);
|
|
29120
|
+
const holeCutHeight = Math.max(holeH - 2 * PLATED_HOLE_LIP_HEIGHT, 0.01);
|
|
29121
|
+
const holeCutDepth = pcbThickness + 2 * padThickness + 4 * MANIFOLD_Z_OFFSET;
|
|
29122
|
+
let holeCutOp = createPillOp(holeCutWidth, holeCutHeight, holeCutDepth);
|
|
29123
|
+
const finalPlatedPartOp = copperUnionBeforeCut.subtract(holeCutOp);
|
|
29124
|
+
manifoldInstancesForCleanup.push(finalPlatedPartOp);
|
|
29125
|
+
const translatedPlatedPart = finalPlatedPartOp.translate([ph.x, ph.y, 0]);
|
|
29126
|
+
manifoldInstancesForCleanup.push(translatedPlatedPart);
|
|
29127
|
+
const threeGeom = manifoldMeshToThreeGeometry(
|
|
29128
|
+
translatedPlatedPart.getMesh()
|
|
29129
|
+
);
|
|
29130
|
+
platedHoleCopperGeoms.push({
|
|
29131
|
+
key: `ph-${ph.pcb_plated_hole_id || index}`,
|
|
29132
|
+
geometry: threeGeom,
|
|
29133
|
+
color: COPPER_COLOR
|
|
29134
|
+
});
|
|
29092
29135
|
} else if (ph.shape === "circular_hole_with_rect_pad") {
|
|
29093
29136
|
const translatedDrill = createCircleHoleDrill({
|
|
29094
29137
|
Manifold,
|
|
@@ -29708,7 +29751,8 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
29708
29751
|
matColorArray[0],
|
|
29709
29752
|
matColorArray[1],
|
|
29710
29753
|
matColorArray[2]
|
|
29711
|
-
)
|
|
29754
|
+
),
|
|
29755
|
+
material: boardData.material
|
|
29712
29756
|
};
|
|
29713
29757
|
}
|
|
29714
29758
|
const { smtPadGeoms } = processSmtPadsForManifold(
|
|
@@ -29787,17 +29831,53 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
29787
29831
|
};
|
|
29788
29832
|
|
|
29789
29833
|
// src/utils/manifold/create-three-geometry-meshes.ts
|
|
29834
|
+
import * as THREE25 from "three";
|
|
29835
|
+
|
|
29836
|
+
// src/utils/create-board-material.ts
|
|
29790
29837
|
import * as THREE24 from "three";
|
|
29838
|
+
var DEFAULT_SIDE = THREE24.DoubleSide;
|
|
29839
|
+
var createBoardMaterial = ({
|
|
29840
|
+
material,
|
|
29841
|
+
color,
|
|
29842
|
+
side = DEFAULT_SIDE
|
|
29843
|
+
}) => {
|
|
29844
|
+
if (material === "fr4") {
|
|
29845
|
+
return new THREE24.MeshPhysicalMaterial({
|
|
29846
|
+
color,
|
|
29847
|
+
side,
|
|
29848
|
+
metalness: 0,
|
|
29849
|
+
roughness: 0.8,
|
|
29850
|
+
specularIntensity: 0.2,
|
|
29851
|
+
ior: 1.45,
|
|
29852
|
+
sheen: 0,
|
|
29853
|
+
clearcoat: 0,
|
|
29854
|
+
transparent: false,
|
|
29855
|
+
opacity: 1,
|
|
29856
|
+
flatShading: true
|
|
29857
|
+
});
|
|
29858
|
+
}
|
|
29859
|
+
return new THREE24.MeshStandardMaterial({
|
|
29860
|
+
color,
|
|
29861
|
+
side,
|
|
29862
|
+
flatShading: true,
|
|
29863
|
+
metalness: 0.1,
|
|
29864
|
+
roughness: 0.8,
|
|
29865
|
+
transparent: true,
|
|
29866
|
+
opacity: 0.9
|
|
29867
|
+
});
|
|
29868
|
+
};
|
|
29869
|
+
|
|
29870
|
+
// src/utils/manifold/create-three-geometry-meshes.ts
|
|
29791
29871
|
function createGeometryMeshes(geoms) {
|
|
29792
29872
|
const meshes = [];
|
|
29793
29873
|
if (!geoms) return meshes;
|
|
29794
29874
|
if (geoms.board && geoms.board.geometry) {
|
|
29795
|
-
const mesh = new
|
|
29875
|
+
const mesh = new THREE25.Mesh(
|
|
29796
29876
|
geoms.board.geometry,
|
|
29797
|
-
|
|
29877
|
+
createBoardMaterial({
|
|
29878
|
+
material: geoms.board.material,
|
|
29798
29879
|
color: geoms.board.color,
|
|
29799
|
-
side:
|
|
29800
|
-
flatShading: true
|
|
29880
|
+
side: THREE25.DoubleSide
|
|
29801
29881
|
})
|
|
29802
29882
|
);
|
|
29803
29883
|
mesh.name = "board-geom";
|
|
@@ -29806,11 +29886,11 @@ function createGeometryMeshes(geoms) {
|
|
|
29806
29886
|
const createMeshesFromArray = (geomArray) => {
|
|
29807
29887
|
if (geomArray) {
|
|
29808
29888
|
geomArray.forEach((comp) => {
|
|
29809
|
-
const mesh = new
|
|
29889
|
+
const mesh = new THREE25.Mesh(
|
|
29810
29890
|
comp.geometry,
|
|
29811
|
-
new
|
|
29891
|
+
new THREE25.MeshStandardMaterial({
|
|
29812
29892
|
color: comp.color,
|
|
29813
|
-
side:
|
|
29893
|
+
side: THREE25.DoubleSide,
|
|
29814
29894
|
flatShading: true
|
|
29815
29895
|
// Consistent with board
|
|
29816
29896
|
})
|
|
@@ -29828,21 +29908,21 @@ function createGeometryMeshes(geoms) {
|
|
|
29828
29908
|
}
|
|
29829
29909
|
|
|
29830
29910
|
// src/utils/manifold/create-three-texture-meshes.ts
|
|
29831
|
-
import * as
|
|
29911
|
+
import * as THREE26 from "three";
|
|
29832
29912
|
function createTextureMeshes(textures, boardData, pcbThickness) {
|
|
29833
29913
|
const meshes = [];
|
|
29834
29914
|
if (!textures || !boardData || pcbThickness === null) return meshes;
|
|
29835
29915
|
const createTexturePlane = (texture, yOffset, isBottomLayer, keySuffix) => {
|
|
29836
29916
|
if (!texture) return null;
|
|
29837
|
-
const planeGeom = new
|
|
29838
|
-
const material = new
|
|
29917
|
+
const planeGeom = new THREE26.PlaneGeometry(boardData.width, boardData.height);
|
|
29918
|
+
const material = new THREE26.MeshBasicMaterial({
|
|
29839
29919
|
map: texture,
|
|
29840
29920
|
transparent: true,
|
|
29841
|
-
side:
|
|
29921
|
+
side: THREE26.DoubleSide,
|
|
29842
29922
|
depthWrite: false
|
|
29843
29923
|
// Important for layers to avoid z-fighting issues with board itself
|
|
29844
29924
|
});
|
|
29845
|
-
const mesh = new
|
|
29925
|
+
const mesh = new THREE26.Mesh(planeGeom, material);
|
|
29846
29926
|
mesh.position.set(boardData.center.x, boardData.center.y, yOffset);
|
|
29847
29927
|
if (isBottomLayer) {
|
|
29848
29928
|
mesh.rotation.set(Math.PI, 0, 0);
|
|
@@ -30498,11 +30578,11 @@ var CadViewer = (props) => {
|
|
|
30498
30578
|
// src/convert-circuit-json-to-3d-svg.ts
|
|
30499
30579
|
var import_debug = __toESM(require_browser(), 1);
|
|
30500
30580
|
import { su as su14 } from "@tscircuit/circuit-json-util";
|
|
30501
|
-
import * as
|
|
30581
|
+
import * as THREE30 from "three";
|
|
30502
30582
|
import { SVGRenderer } from "three/examples/jsm/renderers/SVGRenderer.js";
|
|
30503
30583
|
|
|
30504
30584
|
// src/utils/create-geometry-from-polygons.ts
|
|
30505
|
-
import * as
|
|
30585
|
+
import * as THREE27 from "three";
|
|
30506
30586
|
import { BufferGeometry as BufferGeometry3, Float32BufferAttribute as Float32BufferAttribute2 } from "three";
|
|
30507
30587
|
function createGeometryFromPolygons(polygons) {
|
|
30508
30588
|
const geometry = new BufferGeometry3();
|
|
@@ -30516,12 +30596,12 @@ function createGeometryFromPolygons(polygons) {
|
|
|
30516
30596
|
...polygon3.vertices[i + 1]
|
|
30517
30597
|
// Third vertex
|
|
30518
30598
|
);
|
|
30519
|
-
const v1 = new
|
|
30520
|
-
const v2 = new
|
|
30521
|
-
const v3 = new
|
|
30522
|
-
const normal = new
|
|
30523
|
-
new
|
|
30524
|
-
new
|
|
30599
|
+
const v1 = new THREE27.Vector3(...polygon3.vertices[0]);
|
|
30600
|
+
const v2 = new THREE27.Vector3(...polygon3.vertices[i]);
|
|
30601
|
+
const v3 = new THREE27.Vector3(...polygon3.vertices[i + 1]);
|
|
30602
|
+
const normal = new THREE27.Vector3().crossVectors(
|
|
30603
|
+
new THREE27.Vector3().subVectors(v2, v1),
|
|
30604
|
+
new THREE27.Vector3().subVectors(v3, v1)
|
|
30525
30605
|
).normalize();
|
|
30526
30606
|
normals.push(
|
|
30527
30607
|
normal.x,
|
|
@@ -30544,10 +30624,10 @@ function createGeometryFromPolygons(polygons) {
|
|
|
30544
30624
|
// src/utils/render-component.tsx
|
|
30545
30625
|
var import_modeling3 = __toESM(require_src(), 1);
|
|
30546
30626
|
var import_jscad_planner2 = __toESM(require_dist(), 1);
|
|
30547
|
-
import * as
|
|
30627
|
+
import * as THREE29 from "three";
|
|
30548
30628
|
|
|
30549
30629
|
// src/utils/load-model.ts
|
|
30550
|
-
import * as
|
|
30630
|
+
import * as THREE28 from "three";
|
|
30551
30631
|
import { GLTFLoader as GLTFLoader2 } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
30552
30632
|
import { OBJLoader as OBJLoader2 } from "three/examples/jsm/loaders/OBJLoader.js";
|
|
30553
30633
|
import { STLLoader as STLLoader2 } from "three/examples/jsm/loaders/STLLoader.js";
|
|
@@ -30555,12 +30635,12 @@ async function load3DModel(url) {
|
|
|
30555
30635
|
if (url.endsWith(".stl")) {
|
|
30556
30636
|
const loader = new STLLoader2();
|
|
30557
30637
|
const geometry = await loader.loadAsync(url);
|
|
30558
|
-
const material = new
|
|
30638
|
+
const material = new THREE28.MeshStandardMaterial({
|
|
30559
30639
|
color: 8947848,
|
|
30560
30640
|
metalness: 0.5,
|
|
30561
30641
|
roughness: 0.5
|
|
30562
30642
|
});
|
|
30563
|
-
return new
|
|
30643
|
+
return new THREE28.Mesh(geometry, material);
|
|
30564
30644
|
}
|
|
30565
30645
|
if (url.endsWith(".obj")) {
|
|
30566
30646
|
const loader = new OBJLoader2();
|
|
@@ -30593,9 +30673,9 @@ async function renderComponent(component, scene) {
|
|
|
30593
30673
|
}
|
|
30594
30674
|
if (component.rotation) {
|
|
30595
30675
|
model.rotation.set(
|
|
30596
|
-
|
|
30597
|
-
|
|
30598
|
-
|
|
30676
|
+
THREE29.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
30677
|
+
THREE29.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
30678
|
+
THREE29.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
30599
30679
|
);
|
|
30600
30680
|
}
|
|
30601
30681
|
scene.add(model);
|
|
@@ -30609,13 +30689,13 @@ async function renderComponent(component, scene) {
|
|
|
30609
30689
|
);
|
|
30610
30690
|
if (jscadObject && (jscadObject.polygons || jscadObject.sides)) {
|
|
30611
30691
|
const threeGeom = convertCSGToThreeGeom(jscadObject);
|
|
30612
|
-
const material2 = new
|
|
30692
|
+
const material2 = new THREE29.MeshStandardMaterial({
|
|
30613
30693
|
color: 8947848,
|
|
30614
30694
|
metalness: 0.5,
|
|
30615
30695
|
roughness: 0.5,
|
|
30616
|
-
side:
|
|
30696
|
+
side: THREE29.DoubleSide
|
|
30617
30697
|
});
|
|
30618
|
-
const mesh2 = new
|
|
30698
|
+
const mesh2 = new THREE29.Mesh(threeGeom, material2);
|
|
30619
30699
|
if (component.position) {
|
|
30620
30700
|
mesh2.position.set(
|
|
30621
30701
|
component.position.x ?? 0,
|
|
@@ -30625,9 +30705,9 @@ async function renderComponent(component, scene) {
|
|
|
30625
30705
|
}
|
|
30626
30706
|
if (component.rotation) {
|
|
30627
30707
|
mesh2.rotation.set(
|
|
30628
|
-
|
|
30629
|
-
|
|
30630
|
-
|
|
30708
|
+
THREE29.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
30709
|
+
THREE29.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
30710
|
+
THREE29.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
30631
30711
|
);
|
|
30632
30712
|
}
|
|
30633
30713
|
scene.add(mesh2);
|
|
@@ -30643,17 +30723,17 @@ async function renderComponent(component, scene) {
|
|
|
30643
30723
|
if (!geom || !geom.polygons && !geom.sides) {
|
|
30644
30724
|
continue;
|
|
30645
30725
|
}
|
|
30646
|
-
const color = new
|
|
30726
|
+
const color = new THREE29.Color(geomInfo.color);
|
|
30647
30727
|
color.convertLinearToSRGB();
|
|
30648
30728
|
const geomWithColor = { ...geom, color: [color.r, color.g, color.b] };
|
|
30649
30729
|
const threeGeom = convertCSGToThreeGeom(geomWithColor);
|
|
30650
|
-
const material2 = new
|
|
30730
|
+
const material2 = new THREE29.MeshStandardMaterial({
|
|
30651
30731
|
vertexColors: true,
|
|
30652
30732
|
metalness: 0.2,
|
|
30653
30733
|
roughness: 0.8,
|
|
30654
|
-
side:
|
|
30734
|
+
side: THREE29.DoubleSide
|
|
30655
30735
|
});
|
|
30656
|
-
const mesh2 = new
|
|
30736
|
+
const mesh2 = new THREE29.Mesh(threeGeom, material2);
|
|
30657
30737
|
if (component.position) {
|
|
30658
30738
|
mesh2.position.set(
|
|
30659
30739
|
component.position.x ?? 0,
|
|
@@ -30663,22 +30743,22 @@ async function renderComponent(component, scene) {
|
|
|
30663
30743
|
}
|
|
30664
30744
|
if (component.rotation) {
|
|
30665
30745
|
mesh2.rotation.set(
|
|
30666
|
-
|
|
30667
|
-
|
|
30668
|
-
|
|
30746
|
+
THREE29.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
30747
|
+
THREE29.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
30748
|
+
THREE29.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
30669
30749
|
);
|
|
30670
30750
|
}
|
|
30671
30751
|
scene.add(mesh2);
|
|
30672
30752
|
}
|
|
30673
30753
|
return;
|
|
30674
30754
|
}
|
|
30675
|
-
const geometry = new
|
|
30676
|
-
const material = new
|
|
30755
|
+
const geometry = new THREE29.BoxGeometry(0.5, 0.5, 0.5);
|
|
30756
|
+
const material = new THREE29.MeshStandardMaterial({
|
|
30677
30757
|
color: 16711680,
|
|
30678
30758
|
transparent: true,
|
|
30679
30759
|
opacity: 0.25
|
|
30680
30760
|
});
|
|
30681
|
-
const mesh = new
|
|
30761
|
+
const mesh = new THREE29.Mesh(geometry, material);
|
|
30682
30762
|
if (component.position) {
|
|
30683
30763
|
mesh.position.set(
|
|
30684
30764
|
component.position.x ?? 0,
|
|
@@ -30699,11 +30779,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
30699
30779
|
padding = 20,
|
|
30700
30780
|
zoom = 1.5
|
|
30701
30781
|
} = options;
|
|
30702
|
-
const scene = new
|
|
30782
|
+
const scene = new THREE30.Scene();
|
|
30703
30783
|
const renderer = new SVGRenderer();
|
|
30704
30784
|
renderer.setSize(width10, height10);
|
|
30705
|
-
renderer.setClearColor(new
|
|
30706
|
-
const camera = new
|
|
30785
|
+
renderer.setClearColor(new THREE30.Color(backgroundColor), 1);
|
|
30786
|
+
const camera = new THREE30.OrthographicCamera();
|
|
30707
30787
|
const aspect = width10 / height10;
|
|
30708
30788
|
const frustumSize = 100;
|
|
30709
30789
|
const halfFrustumSize = frustumSize / 2 / zoom;
|
|
@@ -30717,45 +30797,44 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
30717
30797
|
camera.position.set(position.x, position.y, position.z);
|
|
30718
30798
|
camera.up.set(0, 1, 0);
|
|
30719
30799
|
const lookAt = options.camera?.lookAt ?? { x: 0, y: 0, z: 0 };
|
|
30720
|
-
camera.lookAt(new
|
|
30800
|
+
camera.lookAt(new THREE30.Vector3(lookAt.x, lookAt.y, lookAt.z));
|
|
30721
30801
|
camera.updateProjectionMatrix();
|
|
30722
|
-
const ambientLight = new
|
|
30802
|
+
const ambientLight = new THREE30.AmbientLight(16777215, Math.PI / 2);
|
|
30723
30803
|
scene.add(ambientLight);
|
|
30724
|
-
const pointLight = new
|
|
30804
|
+
const pointLight = new THREE30.PointLight(16777215, Math.PI / 4);
|
|
30725
30805
|
pointLight.position.set(-10, -10, 10);
|
|
30726
30806
|
scene.add(pointLight);
|
|
30727
30807
|
const components = su14(circuitJson).cad_component.list();
|
|
30728
30808
|
for (const component of components) {
|
|
30729
30809
|
await renderComponent(component, scene);
|
|
30730
30810
|
}
|
|
30811
|
+
const boardData = su14(circuitJson).pcb_board.list()[0];
|
|
30731
30812
|
const boardGeom = createBoardGeomFromCircuitJson(circuitJson);
|
|
30732
30813
|
if (boardGeom) {
|
|
30733
30814
|
for (const geom of boardGeom) {
|
|
30734
30815
|
const g = geom;
|
|
30735
30816
|
if (!g.polygons || g.polygons.length === 0) continue;
|
|
30736
30817
|
const geometry = createGeometryFromPolygons(g.polygons);
|
|
30737
|
-
const
|
|
30738
|
-
color
|
|
30739
|
-
|
|
30740
|
-
|
|
30741
|
-
|
|
30742
|
-
|
|
30743
|
-
|
|
30744
|
-
|
|
30745
|
-
|
|
30746
|
-
transparent: true,
|
|
30747
|
-
side: THREE29.DoubleSide
|
|
30818
|
+
const baseColor = new THREE30.Color(
|
|
30819
|
+
g.color?.[0] ?? 0,
|
|
30820
|
+
g.color?.[1] ?? 0,
|
|
30821
|
+
g.color?.[2] ?? 0
|
|
30822
|
+
);
|
|
30823
|
+
const material = createBoardMaterial({
|
|
30824
|
+
material: boardData?.material,
|
|
30825
|
+
color: baseColor,
|
|
30826
|
+
side: THREE30.DoubleSide
|
|
30748
30827
|
});
|
|
30749
|
-
const mesh = new
|
|
30828
|
+
const mesh = new THREE30.Mesh(geometry, material);
|
|
30750
30829
|
scene.add(mesh);
|
|
30751
30830
|
}
|
|
30752
30831
|
}
|
|
30753
|
-
const gridHelper = new
|
|
30832
|
+
const gridHelper = new THREE30.GridHelper(100, 100);
|
|
30754
30833
|
gridHelper.rotation.x = Math.PI / 2;
|
|
30755
30834
|
scene.add(gridHelper);
|
|
30756
|
-
const box = new
|
|
30757
|
-
const center = box.getCenter(new
|
|
30758
|
-
const size2 = box.getSize(new
|
|
30835
|
+
const box = new THREE30.Box3().setFromObject(scene);
|
|
30836
|
+
const center = box.getCenter(new THREE30.Vector3());
|
|
30837
|
+
const size2 = box.getSize(new THREE30.Vector3());
|
|
30759
30838
|
scene.position.sub(center);
|
|
30760
30839
|
const maxDim = Math.max(size2.x, size2.y, size2.z);
|
|
30761
30840
|
if (maxDim > 0) {
|