@tscircuit/3d-viewer 0.0.408 → 0.0.409
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.js +300 -195
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6436,7 +6436,7 @@ var require_interpolateBetween2DPointsForY = __commonJS({
|
|
|
6436
6436
|
var require_intersect = __commonJS({
|
|
6437
6437
|
"node_modules/@jscad/modeling/src/maths/utils/intersect.js"(exports, module) {
|
|
6438
6438
|
"use strict";
|
|
6439
|
-
var
|
|
6439
|
+
var intersect3 = (p1, p2, p3, p4) => {
|
|
6440
6440
|
if (p1[0] === p2[0] && p1[1] === p2[1] || p3[0] === p4[0] && p3[1] === p4[1]) {
|
|
6441
6441
|
return void 0;
|
|
6442
6442
|
}
|
|
@@ -6453,7 +6453,7 @@ var require_intersect = __commonJS({
|
|
|
6453
6453
|
const y = p1[1] + ua * (p2[1] - p1[1]);
|
|
6454
6454
|
return [x, y];
|
|
6455
6455
|
};
|
|
6456
|
-
module.exports =
|
|
6456
|
+
module.exports = intersect3;
|
|
6457
6457
|
}
|
|
6458
6458
|
});
|
|
6459
6459
|
|
|
@@ -11424,7 +11424,7 @@ var require_intersectGeom3 = __commonJS({
|
|
|
11424
11424
|
var flatten = require_flatten();
|
|
11425
11425
|
var retessellate = require_retessellate();
|
|
11426
11426
|
var intersectSub = require_intersectGeom3Sub();
|
|
11427
|
-
var
|
|
11427
|
+
var intersect3 = (...geometries2) => {
|
|
11428
11428
|
geometries2 = flatten(geometries2);
|
|
11429
11429
|
let newgeometry = geometries2.shift();
|
|
11430
11430
|
geometries2.forEach((geometry) => {
|
|
@@ -11433,7 +11433,7 @@ var require_intersectGeom3 = __commonJS({
|
|
|
11433
11433
|
newgeometry = retessellate(newgeometry);
|
|
11434
11434
|
return newgeometry;
|
|
11435
11435
|
};
|
|
11436
|
-
module.exports =
|
|
11436
|
+
module.exports = intersect3;
|
|
11437
11437
|
}
|
|
11438
11438
|
});
|
|
11439
11439
|
|
|
@@ -11447,14 +11447,14 @@ var require_intersectGeom2 = __commonJS({
|
|
|
11447
11447
|
var fromFakePolygons = require_fromFakePolygons();
|
|
11448
11448
|
var to3DWalls = require_to3DWalls();
|
|
11449
11449
|
var intersectGeom3 = require_intersectGeom3();
|
|
11450
|
-
var
|
|
11450
|
+
var intersect3 = (...geometries2) => {
|
|
11451
11451
|
geometries2 = flatten(geometries2);
|
|
11452
11452
|
const newgeometries = geometries2.map((geometry) => to3DWalls({ z0: -1, z1: 1 }, geometry));
|
|
11453
11453
|
const newgeom3 = intersectGeom3(newgeometries);
|
|
11454
11454
|
const epsilon = measureEpsilon(newgeom3);
|
|
11455
11455
|
return fromFakePolygons(epsilon, geom3.toPolygons(newgeom3));
|
|
11456
11456
|
};
|
|
11457
|
-
module.exports =
|
|
11457
|
+
module.exports = intersect3;
|
|
11458
11458
|
}
|
|
11459
11459
|
});
|
|
11460
11460
|
|
|
@@ -11468,7 +11468,7 @@ var require_intersect2 = __commonJS({
|
|
|
11468
11468
|
var geom3 = require_geom3();
|
|
11469
11469
|
var intersectGeom2 = require_intersectGeom2();
|
|
11470
11470
|
var intersectGeom3 = require_intersectGeom3();
|
|
11471
|
-
var
|
|
11471
|
+
var intersect3 = (...geometries2) => {
|
|
11472
11472
|
geometries2 = flatten(geometries2);
|
|
11473
11473
|
if (geometries2.length === 0) throw new Error("wrong number of arguments");
|
|
11474
11474
|
if (!areAllShapesTheSameType(geometries2)) {
|
|
@@ -11479,7 +11479,7 @@ var require_intersect2 = __commonJS({
|
|
|
11479
11479
|
if (geom3.isA(geometry)) return intersectGeom3(geometries2);
|
|
11480
11480
|
return geometry;
|
|
11481
11481
|
};
|
|
11482
|
-
module.exports =
|
|
11482
|
+
module.exports = intersect3;
|
|
11483
11483
|
}
|
|
11484
11484
|
});
|
|
11485
11485
|
|
|
@@ -11787,7 +11787,7 @@ var require_offsetFromPoints = __commonJS({
|
|
|
11787
11787
|
"node_modules/@jscad/modeling/src/operations/expansions/offsetFromPoints.js"(exports, module) {
|
|
11788
11788
|
"use strict";
|
|
11789
11789
|
var { EPS, TAU } = require_constants();
|
|
11790
|
-
var
|
|
11790
|
+
var intersect3 = require_intersect();
|
|
11791
11791
|
var line22 = require_line2();
|
|
11792
11792
|
var vec2 = require_vec2();
|
|
11793
11793
|
var area = require_area();
|
|
@@ -11822,7 +11822,7 @@ var require_offsetFromPoints = __commonJS({
|
|
|
11822
11822
|
const currentSegment = [n0, n1];
|
|
11823
11823
|
if (previousSegment != null) {
|
|
11824
11824
|
if (closed || !closed && j !== 0) {
|
|
11825
|
-
const ip =
|
|
11825
|
+
const ip = intersect3(previousSegment[0], previousSegment[1], currentSegment[0], currentSegment[1]);
|
|
11826
11826
|
if (ip) {
|
|
11827
11827
|
newPoints.pop();
|
|
11828
11828
|
currentSegment[0] = ip;
|
|
@@ -11839,7 +11839,7 @@ var require_offsetFromPoints = __commonJS({
|
|
|
11839
11839
|
if (closed && previousSegment != null) {
|
|
11840
11840
|
const n0 = newPoints[0];
|
|
11841
11841
|
const n1 = newPoints[1];
|
|
11842
|
-
const ip =
|
|
11842
|
+
const ip = intersect3(previousSegment[0], previousSegment[1], n0, n1);
|
|
11843
11843
|
if (ip) {
|
|
11844
11844
|
newPoints[0] = ip;
|
|
11845
11845
|
newPoints.pop();
|
|
@@ -12269,7 +12269,7 @@ var require_expand = __commonJS({
|
|
|
12269
12269
|
var expandGeom2 = require_expandGeom2();
|
|
12270
12270
|
var expandGeom3 = require_expandGeom3();
|
|
12271
12271
|
var expandPath2 = require_expandPath2();
|
|
12272
|
-
var
|
|
12272
|
+
var expand4 = (options, ...objects) => {
|
|
12273
12273
|
objects = flatten(objects);
|
|
12274
12274
|
if (objects.length === 0) throw new Error("wrong number of arguments");
|
|
12275
12275
|
const results = objects.map((object) => {
|
|
@@ -12280,7 +12280,7 @@ var require_expand = __commonJS({
|
|
|
12280
12280
|
});
|
|
12281
12281
|
return results.length === 1 ? results[0] : results;
|
|
12282
12282
|
};
|
|
12283
|
-
module.exports =
|
|
12283
|
+
module.exports = expand4;
|
|
12284
12284
|
}
|
|
12285
12285
|
});
|
|
12286
12286
|
|
|
@@ -12478,7 +12478,7 @@ var require_extrudeRectangularPath2 = __commonJS({
|
|
|
12478
12478
|
"node_modules/@jscad/modeling/src/operations/extrusions/extrudeRectangularPath2.js"(exports, module) {
|
|
12479
12479
|
"use strict";
|
|
12480
12480
|
var path2 = require_path2();
|
|
12481
|
-
var
|
|
12481
|
+
var expand4 = require_expand();
|
|
12482
12482
|
var extrudeLinearGeom2 = require_extrudeLinearGeom2();
|
|
12483
12483
|
var extrudeRectangularPath2 = (options, geometry) => {
|
|
12484
12484
|
const defaults = {
|
|
@@ -12490,7 +12490,7 @@ var require_extrudeRectangularPath2 = __commonJS({
|
|
|
12490
12490
|
options.offset = [0, 0, height10];
|
|
12491
12491
|
const points = path2.toPoints(geometry);
|
|
12492
12492
|
if (points.length === 0) throw new Error("the given geometry cannot be empty");
|
|
12493
|
-
const newgeometry =
|
|
12493
|
+
const newgeometry = expand4(options, geometry);
|
|
12494
12494
|
return extrudeLinearGeom2(options, newgeometry);
|
|
12495
12495
|
};
|
|
12496
12496
|
module.exports = extrudeRectangularPath2;
|
|
@@ -12504,7 +12504,7 @@ var require_extrudeRectangularGeom2 = __commonJS({
|
|
|
12504
12504
|
var { area } = require_utils();
|
|
12505
12505
|
var geom2 = require_geom2();
|
|
12506
12506
|
var path2 = require_path2();
|
|
12507
|
-
var
|
|
12507
|
+
var expand4 = require_expand();
|
|
12508
12508
|
var extrudeLinearGeom2 = require_extrudeLinearGeom2();
|
|
12509
12509
|
var extrudeRectangularGeom2 = (options, geometry) => {
|
|
12510
12510
|
const defaults = {
|
|
@@ -12518,7 +12518,7 @@ var require_extrudeRectangularGeom2 = __commonJS({
|
|
|
12518
12518
|
if (outlines.length === 0) throw new Error("the given geometry cannot be empty");
|
|
12519
12519
|
const newparts = outlines.map((outline) => {
|
|
12520
12520
|
if (area(outline) < 0) outline.reverse();
|
|
12521
|
-
return
|
|
12521
|
+
return expand4(options, path2.fromPoints({ closed: true }, outline));
|
|
12522
12522
|
});
|
|
12523
12523
|
const allsides = newparts.reduce((sides, part) => sides.concat(geom2.toSides(part)), []);
|
|
12524
12524
|
const newgeometry = geom2.create(allsides);
|
|
@@ -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.408",
|
|
26104
26104
|
main: "./dist/index.js",
|
|
26105
26105
|
module: "./dist/index.js",
|
|
26106
26106
|
type: "module",
|
|
@@ -26901,6 +26901,7 @@ var tracesMaterialColors = {
|
|
|
26901
26901
|
var import_extrusions = __toESM(require_extrusions(), 1);
|
|
26902
26902
|
var import_primitives = __toESM(require_primitives(), 1);
|
|
26903
26903
|
var import_transforms = __toESM(require_transforms(), 1);
|
|
26904
|
+
var import_expansions = __toESM(require_expansions(), 1);
|
|
26904
26905
|
var arePointsClockwise = (points) => {
|
|
26905
26906
|
let area = 0;
|
|
26906
26907
|
for (let i = 0; i < points.length; i++) {
|
|
@@ -26911,13 +26912,17 @@ var arePointsClockwise = (points) => {
|
|
|
26911
26912
|
const signedArea = area / 2;
|
|
26912
26913
|
return signedArea <= 0;
|
|
26913
26914
|
};
|
|
26914
|
-
var createBoardGeomWithOutline = (board, depth = 1.2) => {
|
|
26915
|
+
var createBoardGeomWithOutline = (board, depth = 1.2, options = {}) => {
|
|
26916
|
+
const { xyOutset = 0 } = options;
|
|
26915
26917
|
const { outline } = board;
|
|
26916
26918
|
let outlineVec2 = outline.map((point2) => [point2.x, point2.y]);
|
|
26917
26919
|
if (arePointsClockwise(outlineVec2)) {
|
|
26918
26920
|
outlineVec2 = outlineVec2.reverse();
|
|
26919
26921
|
}
|
|
26920
|
-
|
|
26922
|
+
let shape = (0, import_primitives.polygon)({ points: outlineVec2 });
|
|
26923
|
+
if (xyOutset !== 0) {
|
|
26924
|
+
shape = (0, import_expansions.expand)({ delta: xyOutset, corners: "edge" }, shape);
|
|
26925
|
+
}
|
|
26921
26926
|
let boardGeom = (0, import_extrusions.extrudeLinear)({ height: depth }, shape);
|
|
26922
26927
|
boardGeom = (0, import_transforms.translate)([0, 0, -depth / 2], boardGeom);
|
|
26923
26928
|
return boardGeom;
|
|
@@ -26992,6 +26997,7 @@ function extractRectBorderRadius(source) {
|
|
|
26992
26997
|
// src/geoms/plated-hole.ts
|
|
26993
26998
|
var platedHoleLipHeight = 0.05;
|
|
26994
26999
|
var RECT_PAD_SEGMENTS = 64;
|
|
27000
|
+
var maybeClip = (geom, clipGeom) => clipGeom ? (0, import_booleans.intersect)(clipGeom, geom) : geom;
|
|
26995
27001
|
var createRectPadGeom = ({
|
|
26996
27002
|
width: width10,
|
|
26997
27003
|
height: height10,
|
|
@@ -27012,84 +27018,71 @@ var createRectPadGeom = ({
|
|
|
27012
27018
|
const offsetZ = center[2] - thickness / 2;
|
|
27013
27019
|
return (0, import_transforms2.translate)([center[0], center[1], offsetZ], extruded);
|
|
27014
27020
|
};
|
|
27015
|
-
var platedHole = (plated_hole, ctx) => {
|
|
27021
|
+
var platedHole = (plated_hole, ctx, options = {}) => {
|
|
27022
|
+
const { clipGeom } = options;
|
|
27016
27023
|
if (!plated_hole.shape) plated_hole.shape = "circle";
|
|
27024
|
+
const throughDrillHeight = ctx.pcbThickness + 2 * platedHoleLipHeight + 4 * M;
|
|
27017
27025
|
if (plated_hole.shape === "circle") {
|
|
27018
|
-
|
|
27019
|
-
|
|
27020
|
-
|
|
27021
|
-
|
|
27022
|
-
|
|
27023
|
-
|
|
27024
|
-
|
|
27025
|
-
|
|
27026
|
-
|
|
27027
|
-
|
|
27028
|
-
|
|
27029
|
-
|
|
27030
|
-
|
|
27031
|
-
|
|
27032
|
-
],
|
|
27033
|
-
radius: plated_hole.outer_diameter / 2,
|
|
27034
|
-
height: platedHoleLipHeight
|
|
27035
|
-
}),
|
|
27036
|
-
(0, import_primitives3.cylinder)({
|
|
27037
|
-
center: [
|
|
27038
|
-
plated_hole.x,
|
|
27039
|
-
plated_hole.y,
|
|
27040
|
-
-ctx.pcbThickness / 2 - platedHoleLipHeight / 2 - M
|
|
27041
|
-
],
|
|
27042
|
-
radius: plated_hole.outer_diameter / 2,
|
|
27043
|
-
height: platedHoleLipHeight
|
|
27044
|
-
})
|
|
27045
|
-
),
|
|
27046
|
-
(0, import_primitives3.cylinder)({
|
|
27047
|
-
center: [plated_hole.x, plated_hole.y, 0],
|
|
27048
|
-
radius: plated_hole.hole_diameter / 2 - M,
|
|
27049
|
-
height: 1.5
|
|
27050
|
-
})
|
|
27051
|
-
)
|
|
27052
|
-
);
|
|
27026
|
+
const outerDiameter = plated_hole.outer_diameter ?? Math.max(plated_hole.hole_diameter, 0);
|
|
27027
|
+
const copperHeight = ctx.pcbThickness + 2 * (platedHoleLipHeight + M);
|
|
27028
|
+
const copperBody = (0, import_primitives3.cylinder)({
|
|
27029
|
+
center: [plated_hole.x, plated_hole.y, 0],
|
|
27030
|
+
radius: outerDiameter / 2,
|
|
27031
|
+
height: copperHeight
|
|
27032
|
+
});
|
|
27033
|
+
const copperSolid = maybeClip(copperBody, clipGeom);
|
|
27034
|
+
const drill = (0, import_primitives3.cylinder)({
|
|
27035
|
+
center: [plated_hole.x, plated_hole.y, 0],
|
|
27036
|
+
radius: Math.max(plated_hole.hole_diameter / 2, 0.01),
|
|
27037
|
+
height: throughDrillHeight
|
|
27038
|
+
});
|
|
27039
|
+
return (0, import_colors2.colorize)(colors.copper, (0, import_booleans.subtract)(copperSolid, drill));
|
|
27053
27040
|
}
|
|
27054
27041
|
if (plated_hole.shape === "circular_hole_with_rect_pad") {
|
|
27055
27042
|
const padWidth = plated_hole.rect_pad_width || plated_hole.hole_diameter;
|
|
27056
27043
|
const padHeight = plated_hole.rect_pad_height || plated_hole.hole_diameter;
|
|
27057
27044
|
const rectBorderRadius = extractRectBorderRadius(plated_hole);
|
|
27058
|
-
|
|
27059
|
-
|
|
27060
|
-
|
|
27061
|
-
(
|
|
27062
|
-
|
|
27063
|
-
|
|
27064
|
-
|
|
27065
|
-
|
|
27066
|
-
|
|
27067
|
-
|
|
27068
|
-
|
|
27069
|
-
|
|
27070
|
-
|
|
27071
|
-
|
|
27072
|
-
|
|
27073
|
-
|
|
27074
|
-
|
|
27075
|
-
|
|
27076
|
-
|
|
27077
|
-
|
|
27078
|
-
|
|
27079
|
-
|
|
27080
|
-
|
|
27081
|
-
|
|
27082
|
-
|
|
27083
|
-
|
|
27084
|
-
|
|
27085
|
-
// Subtract actual hole through
|
|
27045
|
+
const copperSolid = maybeClip(
|
|
27046
|
+
(0, import_booleans.union)(
|
|
27047
|
+
// Top rectangular pad
|
|
27048
|
+
createRectPadGeom({
|
|
27049
|
+
width: padWidth,
|
|
27050
|
+
height: padHeight,
|
|
27051
|
+
thickness: platedHoleLipHeight,
|
|
27052
|
+
center: [
|
|
27053
|
+
plated_hole.x,
|
|
27054
|
+
plated_hole.y,
|
|
27055
|
+
ctx.pcbThickness / 2 + platedHoleLipHeight / 2 + M
|
|
27056
|
+
],
|
|
27057
|
+
borderRadius: rectBorderRadius
|
|
27058
|
+
}),
|
|
27059
|
+
// Bottom rectangular pad
|
|
27060
|
+
createRectPadGeom({
|
|
27061
|
+
width: padWidth,
|
|
27062
|
+
height: padHeight,
|
|
27063
|
+
thickness: platedHoleLipHeight,
|
|
27064
|
+
center: [
|
|
27065
|
+
plated_hole.x,
|
|
27066
|
+
plated_hole.y,
|
|
27067
|
+
-ctx.pcbThickness / 2 - platedHoleLipHeight / 2 - M
|
|
27068
|
+
],
|
|
27069
|
+
borderRadius: rectBorderRadius
|
|
27070
|
+
}),
|
|
27071
|
+
// Plated barrel around hole
|
|
27086
27072
|
(0, import_primitives3.cylinder)({
|
|
27087
27073
|
center: [plated_hole.x, plated_hole.y, 0],
|
|
27088
|
-
radius:
|
|
27089
|
-
height:
|
|
27074
|
+
radius: plated_hole.hole_diameter / 2,
|
|
27075
|
+
height: ctx.pcbThickness
|
|
27090
27076
|
})
|
|
27091
|
-
)
|
|
27077
|
+
),
|
|
27078
|
+
clipGeom
|
|
27092
27079
|
);
|
|
27080
|
+
const drill = (0, import_primitives3.cylinder)({
|
|
27081
|
+
center: [plated_hole.x, plated_hole.y, 0],
|
|
27082
|
+
radius: Math.max(plated_hole.hole_diameter / 2 - M, 0.01),
|
|
27083
|
+
height: throughDrillHeight
|
|
27084
|
+
});
|
|
27085
|
+
return (0, import_colors2.colorize)(colors.copper, (0, import_booleans.subtract)(copperSolid, drill));
|
|
27093
27086
|
}
|
|
27094
27087
|
if (plated_hole.shape === "pill") {
|
|
27095
27088
|
const shouldRotate = plated_hole.hole_height > plated_hole.hole_width;
|
|
@@ -27101,76 +27094,56 @@ var platedHole = (plated_hole, ctx) => {
|
|
|
27101
27094
|
const outerRadius = outerPillHeight / 2;
|
|
27102
27095
|
const rectLength = Math.abs(holeWidth - holeHeight);
|
|
27103
27096
|
const outerRectLength = Math.abs(outerPillWidth - outerPillHeight);
|
|
27104
|
-
const
|
|
27105
|
-
|
|
27106
|
-
|
|
27107
|
-
|
|
27108
|
-
|
|
27109
|
-
|
|
27110
|
-
|
|
27111
|
-
|
|
27112
|
-
|
|
27113
|
-
|
|
27114
|
-
|
|
27115
|
-
|
|
27116
|
-
|
|
27117
|
-
|
|
27118
|
-
|
|
27119
|
-
|
|
27120
|
-
|
|
27121
|
-
|
|
27122
|
-
|
|
27123
|
-
|
|
27124
|
-
|
|
27125
|
-
|
|
27126
|
-
|
|
27127
|
-
|
|
27128
|
-
|
|
27129
|
-
|
|
27130
|
-
|
|
27131
|
-
|
|
27132
|
-
|
|
27133
|
-
|
|
27134
|
-
|
|
27135
|
-
const bottomLipZ = -ctx.pcbThickness / 2 - platedHoleLipHeight / 2 - M;
|
|
27136
|
-
const bottomLipRect = (0, import_primitives3.cuboid)({
|
|
27137
|
-
center: [plated_hole.x, plated_hole.y, bottomLipZ],
|
|
27138
|
-
size: shouldRotate ? [outerPillHeight, outerRectLength, platedHoleLipHeight] : [outerRectLength, outerPillHeight, platedHoleLipHeight]
|
|
27139
|
-
});
|
|
27140
|
-
const bottomLipLeftCap = (0, import_primitives3.cylinder)({
|
|
27141
|
-
center: shouldRotate ? [plated_hole.x, plated_hole.y - outerRectLength / 2, bottomLipZ] : [plated_hole.x - outerRectLength / 2, plated_hole.y, bottomLipZ],
|
|
27142
|
-
radius: outerRadius,
|
|
27143
|
-
height: platedHoleLipHeight
|
|
27144
|
-
});
|
|
27145
|
-
const bottomLipRightCap = (0, import_primitives3.cylinder)({
|
|
27146
|
-
center: shouldRotate ? [plated_hole.x, plated_hole.y + outerRectLength / 2, bottomLipZ] : [plated_hole.x + outerRectLength / 2, plated_hole.y, bottomLipZ],
|
|
27147
|
-
radius: outerRadius,
|
|
27148
|
-
height: platedHoleLipHeight
|
|
27149
|
-
});
|
|
27150
|
-
const bottomLipUnion = (0, import_booleans.union)(
|
|
27151
|
-
bottomLipRect,
|
|
27152
|
-
bottomLipLeftCap,
|
|
27153
|
-
bottomLipRightCap
|
|
27097
|
+
const copperHeight = ctx.pcbThickness + 2 * (platedHoleLipHeight + M);
|
|
27098
|
+
const createPillSection = (width10, height10, thickness) => {
|
|
27099
|
+
const radius = height10 / 2;
|
|
27100
|
+
const length2 = Math.abs(width10 - height10);
|
|
27101
|
+
if (length2 <= 1e-6) {
|
|
27102
|
+
return (0, import_primitives3.cylinder)({
|
|
27103
|
+
center: [plated_hole.x, plated_hole.y, 0],
|
|
27104
|
+
radius,
|
|
27105
|
+
height: thickness
|
|
27106
|
+
});
|
|
27107
|
+
}
|
|
27108
|
+
const rect = (0, import_primitives3.cuboid)({
|
|
27109
|
+
center: [plated_hole.x, plated_hole.y, 0],
|
|
27110
|
+
size: shouldRotate ? [height10, length2, thickness] : [length2, height10, thickness]
|
|
27111
|
+
});
|
|
27112
|
+
const leftCap = (0, import_primitives3.cylinder)({
|
|
27113
|
+
center: shouldRotate ? [plated_hole.x, plated_hole.y - length2 / 2, 0] : [plated_hole.x - length2 / 2, plated_hole.y, 0],
|
|
27114
|
+
radius,
|
|
27115
|
+
height: thickness
|
|
27116
|
+
});
|
|
27117
|
+
const rightCap = (0, import_primitives3.cylinder)({
|
|
27118
|
+
center: shouldRotate ? [plated_hole.x, plated_hole.y + length2 / 2, 0] : [plated_hole.x + length2 / 2, plated_hole.y, 0],
|
|
27119
|
+
radius,
|
|
27120
|
+
height: thickness
|
|
27121
|
+
});
|
|
27122
|
+
return (0, import_booleans.union)(rect, leftCap, rightCap);
|
|
27123
|
+
};
|
|
27124
|
+
const outerBarrel = createPillSection(
|
|
27125
|
+
outerPillWidth,
|
|
27126
|
+
outerPillHeight,
|
|
27127
|
+
copperHeight
|
|
27154
27128
|
);
|
|
27155
27129
|
const drillRect = (0, import_primitives3.cuboid)({
|
|
27156
27130
|
center: [plated_hole.x, plated_hole.y, 0],
|
|
27157
|
-
size: shouldRotate ? [holeHeight - 2 * M, rectLength,
|
|
27131
|
+
size: shouldRotate ? [holeHeight - 2 * M, rectLength, throughDrillHeight] : [rectLength, holeHeight - 2 * M, throughDrillHeight]
|
|
27158
27132
|
});
|
|
27159
27133
|
const drillLeftCap = (0, import_primitives3.cylinder)({
|
|
27160
27134
|
center: shouldRotate ? [plated_hole.x, plated_hole.y - rectLength / 2, 0] : [plated_hole.x - rectLength / 2, plated_hole.y, 0],
|
|
27161
27135
|
radius: holeRadius - M,
|
|
27162
|
-
height:
|
|
27136
|
+
height: throughDrillHeight
|
|
27163
27137
|
});
|
|
27164
27138
|
const drillRightCap = (0, import_primitives3.cylinder)({
|
|
27165
27139
|
center: shouldRotate ? [plated_hole.x, plated_hole.y + rectLength / 2, 0] : [plated_hole.x + rectLength / 2, plated_hole.y, 0],
|
|
27166
27140
|
radius: holeRadius - M,
|
|
27167
|
-
height:
|
|
27141
|
+
height: throughDrillHeight
|
|
27168
27142
|
});
|
|
27169
27143
|
const drillUnion = (0, import_booleans.union)(drillRect, drillLeftCap, drillRightCap);
|
|
27170
|
-
|
|
27171
|
-
|
|
27172
|
-
|
|
27173
|
-
);
|
|
27144
|
+
const copperSolid = maybeClip(outerBarrel, clipGeom);
|
|
27145
|
+
const drill = drillUnion;
|
|
27146
|
+
return (0, import_colors2.colorize)(colors.copper, (0, import_booleans.subtract)(copperSolid, drill));
|
|
27174
27147
|
}
|
|
27175
27148
|
if (plated_hole.shape === "pill_hole_with_rect_pad") {
|
|
27176
27149
|
const shouldRotate = plated_hole.hole_height > plated_hole.hole_width;
|
|
@@ -27183,52 +27156,62 @@ var platedHole = (plated_hole, ctx) => {
|
|
|
27183
27156
|
const rectBorderRadius = extractRectBorderRadius(plated_hole);
|
|
27184
27157
|
const mainRect = (0, import_primitives3.cuboid)({
|
|
27185
27158
|
center: [plated_hole.x, plated_hole.y, 0],
|
|
27186
|
-
size: shouldRotate ? [holeHeight, rectLength,
|
|
27159
|
+
size: shouldRotate ? [holeHeight, rectLength, ctx.pcbThickness] : [rectLength, holeHeight, ctx.pcbThickness]
|
|
27187
27160
|
});
|
|
27188
27161
|
const leftCap = (0, import_primitives3.cylinder)({
|
|
27189
27162
|
center: shouldRotate ? [plated_hole.x, plated_hole.y - rectLength / 2, 0] : [plated_hole.x - rectLength / 2, plated_hole.y, 0],
|
|
27190
27163
|
radius: holeRadius,
|
|
27191
|
-
height:
|
|
27164
|
+
height: ctx.pcbThickness
|
|
27192
27165
|
});
|
|
27193
27166
|
const rightCap = (0, import_primitives3.cylinder)({
|
|
27194
27167
|
center: shouldRotate ? [plated_hole.x, plated_hole.y + rectLength / 2, 0] : [plated_hole.x + rectLength / 2, plated_hole.y, 0],
|
|
27195
27168
|
radius: holeRadius,
|
|
27196
|
-
height:
|
|
27169
|
+
height: ctx.pcbThickness
|
|
27197
27170
|
});
|
|
27198
27171
|
const topPad = createRectPadGeom({
|
|
27199
27172
|
width: padWidth,
|
|
27200
27173
|
height: padHeight,
|
|
27201
27174
|
thickness: platedHoleLipHeight,
|
|
27202
|
-
center: [
|
|
27175
|
+
center: [
|
|
27176
|
+
plated_hole.x,
|
|
27177
|
+
plated_hole.y,
|
|
27178
|
+
ctx.pcbThickness / 2 + platedHoleLipHeight / 2 + M
|
|
27179
|
+
],
|
|
27203
27180
|
borderRadius: rectBorderRadius
|
|
27204
27181
|
});
|
|
27205
27182
|
const bottomPad = createRectPadGeom({
|
|
27206
27183
|
width: padWidth,
|
|
27207
27184
|
height: padHeight,
|
|
27208
27185
|
thickness: platedHoleLipHeight,
|
|
27209
|
-
center: [
|
|
27186
|
+
center: [
|
|
27187
|
+
plated_hole.x,
|
|
27188
|
+
plated_hole.y,
|
|
27189
|
+
-ctx.pcbThickness / 2 - platedHoleLipHeight / 2 - M
|
|
27190
|
+
],
|
|
27210
27191
|
borderRadius: rectBorderRadius
|
|
27211
27192
|
});
|
|
27212
27193
|
const holeCut = (0, import_booleans.union)(
|
|
27213
27194
|
(0, import_primitives3.cuboid)({
|
|
27214
27195
|
center: [plated_hole.x, plated_hole.y, 0],
|
|
27215
|
-
size: shouldRotate ? [holeHeight - platedHoleLipHeight, rectLength,
|
|
27196
|
+
size: shouldRotate ? [holeHeight - platedHoleLipHeight, rectLength, throughDrillHeight] : [rectLength, holeHeight - platedHoleLipHeight, throughDrillHeight]
|
|
27216
27197
|
}),
|
|
27217
27198
|
(0, import_primitives3.cylinder)({
|
|
27218
27199
|
center: shouldRotate ? [plated_hole.x, plated_hole.y - rectLength / 2, 0] : [plated_hole.x - rectLength / 2, plated_hole.y, 0],
|
|
27219
27200
|
radius: holeRadius - platedHoleLipHeight,
|
|
27220
|
-
height:
|
|
27201
|
+
height: throughDrillHeight
|
|
27221
27202
|
}),
|
|
27222
27203
|
(0, import_primitives3.cylinder)({
|
|
27223
27204
|
center: shouldRotate ? [plated_hole.x, plated_hole.y + rectLength / 2, 0] : [plated_hole.x + rectLength / 2, plated_hole.y, 0],
|
|
27224
27205
|
radius: holeRadius - platedHoleLipHeight,
|
|
27225
|
-
height:
|
|
27206
|
+
height: throughDrillHeight
|
|
27226
27207
|
})
|
|
27227
27208
|
);
|
|
27228
|
-
|
|
27229
|
-
|
|
27230
|
-
|
|
27209
|
+
const copperSolid = maybeClip(
|
|
27210
|
+
(0, import_booleans.union)(mainRect, leftCap, rightCap, topPad, bottomPad),
|
|
27211
|
+
clipGeom
|
|
27231
27212
|
);
|
|
27213
|
+
const drill = holeCut;
|
|
27214
|
+
return (0, import_colors2.colorize)(colors.copper, (0, import_booleans.subtract)(copperSolid, drill));
|
|
27232
27215
|
} else {
|
|
27233
27216
|
throw new Error(`Unsupported plated hole shape: ${plated_hole.shape}`);
|
|
27234
27217
|
}
|
|
@@ -27236,7 +27219,7 @@ var platedHole = (plated_hole, ctx) => {
|
|
|
27236
27219
|
|
|
27237
27220
|
// src/BoardGeomBuilder.ts
|
|
27238
27221
|
var import_extrusions4 = __toESM(require_extrusions(), 1);
|
|
27239
|
-
var
|
|
27222
|
+
var import_expansions3 = __toESM(require_expansions(), 1);
|
|
27240
27223
|
|
|
27241
27224
|
// src/geoms/create-geoms-for-silkscreen-text.ts
|
|
27242
27225
|
var import_text = __toESM(require_text(), 1);
|
|
@@ -27541,7 +27524,7 @@ function createSilkscreenTextGeoms(silkscreenText) {
|
|
|
27541
27524
|
|
|
27542
27525
|
// src/geoms/create-geoms-for-silkscreen-path.ts
|
|
27543
27526
|
var import_primitives4 = __toESM(require_primitives(), 1);
|
|
27544
|
-
var
|
|
27527
|
+
var import_expansions2 = __toESM(require_expansions(), 1);
|
|
27545
27528
|
var import_extrusions3 = __toESM(require_extrusions(), 1);
|
|
27546
27529
|
var import_transforms3 = __toESM(require_transforms(), 1);
|
|
27547
27530
|
var import_colors3 = __toESM(require_colors(), 1);
|
|
@@ -27550,7 +27533,7 @@ function createSilkscreenPathGeom(sp, ctx) {
|
|
|
27550
27533
|
const routePoints = sp.route.map((p) => [p.x, p.y]);
|
|
27551
27534
|
const pathLine = (0, import_primitives4.line)(routePoints);
|
|
27552
27535
|
const strokeWidth = sp.stroke_width || 0.1;
|
|
27553
|
-
const expandedPath = (0,
|
|
27536
|
+
const expandedPath = (0, import_expansions2.expand)(
|
|
27554
27537
|
{ delta: strokeWidth / 2, corners: "round" },
|
|
27555
27538
|
pathLine
|
|
27556
27539
|
);
|
|
@@ -27652,6 +27635,8 @@ function createGeom2FromBRep(brep, arcSegments = 16) {
|
|
|
27652
27635
|
|
|
27653
27636
|
// src/BoardGeomBuilder.ts
|
|
27654
27637
|
var PAD_ROUNDED_SEGMENTS = 64;
|
|
27638
|
+
var BOARD_CLIP_Z_MARGIN = 1;
|
|
27639
|
+
var BOARD_CLIP_XY_OUTSET = 0.05;
|
|
27655
27640
|
var createCenteredRectPadGeom = (width10, height10, thickness, rectBorderRadius) => {
|
|
27656
27641
|
const clampedRadius = clampRectBorderRadius(width10, height10, rectBorderRadius);
|
|
27657
27642
|
if (clampedRadius <= 0) {
|
|
@@ -27702,6 +27687,7 @@ var BoardGeomBuilder = class {
|
|
|
27702
27687
|
silkscreenTextGeoms = [];
|
|
27703
27688
|
silkscreenPathGeoms = [];
|
|
27704
27689
|
copperPourGeoms = [];
|
|
27690
|
+
boardClipGeom = null;
|
|
27705
27691
|
state = "initializing";
|
|
27706
27692
|
currentIndex = 0;
|
|
27707
27693
|
ctx;
|
|
@@ -27737,10 +27723,11 @@ var BoardGeomBuilder = class {
|
|
|
27737
27723
|
this.pcb_copper_pours = circuitJson.filter(
|
|
27738
27724
|
(e) => e.type === "pcb_copper_pour"
|
|
27739
27725
|
);
|
|
27740
|
-
this.ctx = { pcbThickness: 1.2 };
|
|
27726
|
+
this.ctx = { pcbThickness: this.board.thickness ?? 1.2 };
|
|
27741
27727
|
this.initializeBoard();
|
|
27742
27728
|
}
|
|
27743
27729
|
initializeBoard() {
|
|
27730
|
+
const clipDepth = this.ctx.pcbThickness + 2 * BOARD_CLIP_Z_MARGIN;
|
|
27744
27731
|
if (this.board.outline && this.board.outline.length > 0) {
|
|
27745
27732
|
this.boardGeom = createBoardGeomWithOutline(
|
|
27746
27733
|
{
|
|
@@ -27748,11 +27735,26 @@ var BoardGeomBuilder = class {
|
|
|
27748
27735
|
},
|
|
27749
27736
|
this.ctx.pcbThickness
|
|
27750
27737
|
);
|
|
27738
|
+
this.boardClipGeom = createBoardGeomWithOutline(
|
|
27739
|
+
{
|
|
27740
|
+
outline: this.board.outline
|
|
27741
|
+
},
|
|
27742
|
+
clipDepth,
|
|
27743
|
+
{ xyOutset: BOARD_CLIP_XY_OUTSET }
|
|
27744
|
+
);
|
|
27751
27745
|
} else {
|
|
27752
27746
|
this.boardGeom = (0, import_primitives6.cuboid)({
|
|
27753
27747
|
size: [this.board.width, this.board.height, this.ctx.pcbThickness],
|
|
27754
27748
|
center: [this.board.center.x, this.board.center.y, 0]
|
|
27755
27749
|
});
|
|
27750
|
+
this.boardClipGeom = (0, import_primitives6.cuboid)({
|
|
27751
|
+
size: [
|
|
27752
|
+
this.board.width + 2 * BOARD_CLIP_XY_OUTSET,
|
|
27753
|
+
this.board.height + 2 * BOARD_CLIP_XY_OUTSET,
|
|
27754
|
+
clipDepth
|
|
27755
|
+
],
|
|
27756
|
+
center: [this.board.center.x, this.board.center.y, 0]
|
|
27757
|
+
});
|
|
27756
27758
|
}
|
|
27757
27759
|
this.state = "processing_pads";
|
|
27758
27760
|
this.currentIndex = 0;
|
|
@@ -27929,6 +27931,9 @@ var BoardGeomBuilder = class {
|
|
|
27929
27931
|
pourGeom = (0, import_transforms4.translate)([0, 0, zPos], pourGeom);
|
|
27930
27932
|
}
|
|
27931
27933
|
if (pourGeom) {
|
|
27934
|
+
if (this.boardClipGeom) {
|
|
27935
|
+
pourGeom = (0, import_booleans3.intersect)(this.boardClipGeom, pourGeom);
|
|
27936
|
+
}
|
|
27932
27937
|
const coloredPourGeom = (0, import_colors4.colorize)(colors.copper, pourGeom);
|
|
27933
27938
|
this.copperPourGeoms.push(coloredPourGeom);
|
|
27934
27939
|
}
|
|
@@ -27949,7 +27954,9 @@ var BoardGeomBuilder = class {
|
|
|
27949
27954
|
this.padGeoms = this.padGeoms.map(
|
|
27950
27955
|
(pg) => (0, import_colors4.colorize)(colors.copper, (0, import_booleans3.subtract)(pg, cyGeom))
|
|
27951
27956
|
);
|
|
27952
|
-
const platedHoleGeom = platedHole(ph, this.ctx
|
|
27957
|
+
const platedHoleGeom = platedHole(ph, this.ctx, {
|
|
27958
|
+
clipGeom: this.boardClipGeom
|
|
27959
|
+
});
|
|
27953
27960
|
this.platedHoleGeoms.push(platedHoleGeom);
|
|
27954
27961
|
} else if (ph.shape === "pill" || ph.shape === "pill_hole_with_rect_pad") {
|
|
27955
27962
|
const shouldRotate = ph.hole_height > ph.hole_width;
|
|
@@ -27979,7 +27986,9 @@ var BoardGeomBuilder = class {
|
|
|
27979
27986
|
this.padGeoms = this.padGeoms.map(
|
|
27980
27987
|
(pg) => (0, import_colors4.colorize)(colors.copper, (0, import_booleans3.subtract)(pg, pillHole))
|
|
27981
27988
|
);
|
|
27982
|
-
const platedHoleGeom = platedHole(ph, this.ctx
|
|
27989
|
+
const platedHoleGeom = platedHole(ph, this.ctx, {
|
|
27990
|
+
clipGeom: this.boardClipGeom
|
|
27991
|
+
});
|
|
27983
27992
|
this.platedHoleGeoms.push(platedHoleGeom);
|
|
27984
27993
|
}
|
|
27985
27994
|
}
|
|
@@ -28011,8 +28020,12 @@ var BoardGeomBuilder = class {
|
|
|
28011
28020
|
rectBorderRadius
|
|
28012
28021
|
);
|
|
28013
28022
|
const positionedPadGeom = (0, import_transforms4.translate)([pad2.x, pad2.y, zPos], basePadGeom);
|
|
28014
|
-
|
|
28015
|
-
this.
|
|
28023
|
+
let finalPadGeom = positionedPadGeom;
|
|
28024
|
+
if (this.boardClipGeom) {
|
|
28025
|
+
finalPadGeom = (0, import_booleans3.intersect)(this.boardClipGeom, finalPadGeom);
|
|
28026
|
+
}
|
|
28027
|
+
finalPadGeom = (0, import_colors4.colorize)(colors.copper, finalPadGeom);
|
|
28028
|
+
this.padGeoms.push(finalPadGeom);
|
|
28016
28029
|
} else if (pad2.shape === "rotated_rect") {
|
|
28017
28030
|
let basePadGeom = createCenteredRectPadGeom(
|
|
28018
28031
|
pad2.width,
|
|
@@ -28023,17 +28036,22 @@ var BoardGeomBuilder = class {
|
|
|
28023
28036
|
const rotationRadians = pad2.ccw_rotation * Math.PI / 180;
|
|
28024
28037
|
basePadGeom = (0, import_transforms4.rotateZ)(rotationRadians, basePadGeom);
|
|
28025
28038
|
const positionedPadGeom = (0, import_transforms4.translate)([pad2.x, pad2.y, zPos], basePadGeom);
|
|
28026
|
-
|
|
28027
|
-
this.
|
|
28039
|
+
let finalPadGeom = positionedPadGeom;
|
|
28040
|
+
if (this.boardClipGeom) {
|
|
28041
|
+
finalPadGeom = (0, import_booleans3.intersect)(this.boardClipGeom, finalPadGeom);
|
|
28042
|
+
}
|
|
28043
|
+
finalPadGeom = (0, import_colors4.colorize)(colors.copper, finalPadGeom);
|
|
28044
|
+
this.padGeoms.push(finalPadGeom);
|
|
28028
28045
|
} else if (pad2.shape === "circle") {
|
|
28029
|
-
|
|
28030
|
-
|
|
28031
|
-
|
|
28032
|
-
|
|
28033
|
-
|
|
28034
|
-
|
|
28035
|
-
|
|
28036
|
-
|
|
28046
|
+
let padGeom = (0, import_primitives6.cylinder)({
|
|
28047
|
+
center: [pad2.x, pad2.y, zPos],
|
|
28048
|
+
radius: pad2.radius,
|
|
28049
|
+
height: M
|
|
28050
|
+
});
|
|
28051
|
+
if (this.boardClipGeom) {
|
|
28052
|
+
padGeom = (0, import_booleans3.intersect)(this.boardClipGeom, padGeom);
|
|
28053
|
+
}
|
|
28054
|
+
padGeom = (0, import_colors4.colorize)(colors.copper, padGeom);
|
|
28037
28055
|
this.padGeoms.push(padGeom);
|
|
28038
28056
|
}
|
|
28039
28057
|
}
|
|
@@ -28048,7 +28066,7 @@ var BoardGeomBuilder = class {
|
|
|
28048
28066
|
const layerSign = currentLayer === "bottom" ? -1 : 1;
|
|
28049
28067
|
const zPos = layerSign * this.ctx.pcbThickness / 2 + layerSign * M;
|
|
28050
28068
|
const linePath = (0, import_primitives6.line)(currentSegmentPoints);
|
|
28051
|
-
const expandedPath = (0,
|
|
28069
|
+
const expandedPath = (0, import_expansions3.expand)(
|
|
28052
28070
|
{ delta: currentWidth / 2, corners: "round" },
|
|
28053
28071
|
linePath
|
|
28054
28072
|
);
|
|
@@ -28080,6 +28098,9 @@ var BoardGeomBuilder = class {
|
|
|
28080
28098
|
traceGeom = (0, import_booleans3.subtract)(traceGeom, cuttingCylinder);
|
|
28081
28099
|
}
|
|
28082
28100
|
const tracesMaterialColor = tracesMaterialColors[this.board.material] ?? colors.fr4GreenSolderWithMask;
|
|
28101
|
+
if (this.boardClipGeom) {
|
|
28102
|
+
traceGeom = (0, import_booleans3.intersect)(this.boardClipGeom, traceGeom);
|
|
28103
|
+
}
|
|
28083
28104
|
traceGeom = (0, import_colors4.colorize)(tracesMaterialColor, traceGeom);
|
|
28084
28105
|
this.traceGeoms.push(traceGeom);
|
|
28085
28106
|
}
|
|
@@ -28153,7 +28174,7 @@ var BoardGeomBuilder = class {
|
|
|
28153
28174
|
Math.max(0.01, fontSize * 0.1),
|
|
28154
28175
|
fontSize * 0.05
|
|
28155
28176
|
);
|
|
28156
|
-
const expandedPath = (0,
|
|
28177
|
+
const expandedPath = (0, import_expansions3.expand)(
|
|
28157
28178
|
{ delta: expansionDelta, corners: "round" },
|
|
28158
28179
|
textPath
|
|
28159
28180
|
);
|
|
@@ -28953,7 +28974,7 @@ function createPadManifoldOp({
|
|
|
28953
28974
|
// src/utils/manifold/process-plated-holes.ts
|
|
28954
28975
|
var COPPER_COLOR = new THREE19.Color(...colors.copper);
|
|
28955
28976
|
var PLATED_HOLE_LIP_HEIGHT = 0.05;
|
|
28956
|
-
function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup) {
|
|
28977
|
+
function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
|
|
28957
28978
|
const platedHoleBoardDrills = [];
|
|
28958
28979
|
const pcbPlatedHoles = su8(circuitJson).pcb_plated_hole.list();
|
|
28959
28980
|
const platedHoleCopperGeoms = [];
|
|
@@ -29004,9 +29025,16 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
|
|
|
29004
29025
|
manifoldInstancesForCleanup.push(finalPlatedPartOp);
|
|
29005
29026
|
const translatedPlatedPart = finalPlatedPartOp.translate([ph.x, ph.y, 0]);
|
|
29006
29027
|
manifoldInstancesForCleanup.push(translatedPlatedPart);
|
|
29007
|
-
|
|
29008
|
-
|
|
29009
|
-
|
|
29028
|
+
let finalCopperOp = translatedPlatedPart;
|
|
29029
|
+
if (boardClipVolume) {
|
|
29030
|
+
const clipped = Manifold.intersection([
|
|
29031
|
+
translatedPlatedPart,
|
|
29032
|
+
boardClipVolume
|
|
29033
|
+
]);
|
|
29034
|
+
manifoldInstancesForCleanup.push(clipped);
|
|
29035
|
+
finalCopperOp = clipped;
|
|
29036
|
+
}
|
|
29037
|
+
const threeGeom = manifoldMeshToThreeGeometry(finalCopperOp.getMesh());
|
|
29010
29038
|
platedHoleCopperGeoms.push({
|
|
29011
29039
|
key: `ph-${ph.pcb_plated_hole_id || index}`,
|
|
29012
29040
|
geometry: threeGeom,
|
|
@@ -29124,9 +29152,16 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
|
|
|
29124
29152
|
manifoldInstancesForCleanup.push(finalPlatedPartOp);
|
|
29125
29153
|
const translatedPlatedPart = finalPlatedPartOp.translate([ph.x, ph.y, 0]);
|
|
29126
29154
|
manifoldInstancesForCleanup.push(translatedPlatedPart);
|
|
29127
|
-
|
|
29128
|
-
|
|
29129
|
-
|
|
29155
|
+
let finalCopperOp = translatedPlatedPart;
|
|
29156
|
+
if (boardClipVolume) {
|
|
29157
|
+
const clipped = Manifold.intersection([
|
|
29158
|
+
translatedPlatedPart,
|
|
29159
|
+
boardClipVolume
|
|
29160
|
+
]);
|
|
29161
|
+
manifoldInstancesForCleanup.push(clipped);
|
|
29162
|
+
finalCopperOp = clipped;
|
|
29163
|
+
}
|
|
29164
|
+
const threeGeom = manifoldMeshToThreeGeometry(finalCopperOp.getMesh());
|
|
29130
29165
|
platedHoleCopperGeoms.push({
|
|
29131
29166
|
key: `ph-${ph.pcb_plated_hole_id || index}`,
|
|
29132
29167
|
geometry: threeGeom,
|
|
@@ -29199,7 +29234,16 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
|
|
|
29199
29234
|
manifoldInstancesForCleanup.push(copperUnion);
|
|
29200
29235
|
const translatedCopper = copperUnion.translate([ph.x, ph.y, 0]);
|
|
29201
29236
|
manifoldInstancesForCleanup.push(translatedCopper);
|
|
29202
|
-
|
|
29237
|
+
let finalCopperOp = translatedCopper;
|
|
29238
|
+
if (boardClipVolume) {
|
|
29239
|
+
const clipped = Manifold.intersection([
|
|
29240
|
+
translatedCopper,
|
|
29241
|
+
boardClipVolume
|
|
29242
|
+
]);
|
|
29243
|
+
manifoldInstancesForCleanup.push(clipped);
|
|
29244
|
+
finalCopperOp = clipped;
|
|
29245
|
+
}
|
|
29246
|
+
const threeGeom = manifoldMeshToThreeGeometry(finalCopperOp.getMesh());
|
|
29203
29247
|
platedHoleCopperGeoms.push({
|
|
29204
29248
|
key: `ph-${ph.pcb_plated_hole_id || index}`,
|
|
29205
29249
|
geometry: threeGeom,
|
|
@@ -29246,7 +29290,7 @@ function createViaCopper({
|
|
|
29246
29290
|
|
|
29247
29291
|
// src/utils/manifold/process-vias.ts
|
|
29248
29292
|
var COPPER_COLOR2 = new THREE20.Color(...colors.copper);
|
|
29249
|
-
function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup) {
|
|
29293
|
+
function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
|
|
29250
29294
|
const viaBoardDrills = [];
|
|
29251
29295
|
const pcbVias = su9(circuitJson).pcb_via.list();
|
|
29252
29296
|
const viaCopperGeoms = [];
|
|
@@ -29276,9 +29320,16 @@ function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldIns
|
|
|
29276
29320
|
segments: SMOOTH_CIRCLE_SEGMENTS
|
|
29277
29321
|
});
|
|
29278
29322
|
manifoldInstancesForCleanup.push(translatedViaCopper);
|
|
29279
|
-
|
|
29280
|
-
|
|
29281
|
-
|
|
29323
|
+
let finalCopperOp = translatedViaCopper;
|
|
29324
|
+
if (boardClipVolume) {
|
|
29325
|
+
const clipped = Manifold.intersection([
|
|
29326
|
+
translatedViaCopper,
|
|
29327
|
+
boardClipVolume
|
|
29328
|
+
]);
|
|
29329
|
+
manifoldInstancesForCleanup.push(clipped);
|
|
29330
|
+
finalCopperOp = clipped;
|
|
29331
|
+
}
|
|
29332
|
+
const threeGeom = manifoldMeshToThreeGeometry(finalCopperOp.getMesh());
|
|
29282
29333
|
viaCopperGeoms.push({
|
|
29283
29334
|
key: `via-${via.pcb_via_id || index}`,
|
|
29284
29335
|
geometry: threeGeom,
|
|
@@ -29293,7 +29344,7 @@ function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldIns
|
|
|
29293
29344
|
import { su as su10 } from "@tscircuit/circuit-json-util";
|
|
29294
29345
|
import * as THREE21 from "three";
|
|
29295
29346
|
var COPPER_COLOR3 = new THREE21.Color(...colors.copper);
|
|
29296
|
-
function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, holeUnion) {
|
|
29347
|
+
function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, holeUnion, boardClipVolume) {
|
|
29297
29348
|
const smtPadGeoms = [];
|
|
29298
29349
|
const smtPads = su10(circuitJson).pcb_smtpad.list();
|
|
29299
29350
|
smtPads.forEach((pad2, index) => {
|
|
@@ -29313,6 +29364,11 @@ function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifold
|
|
|
29313
29364
|
finalPadOp = translatedPad.subtract(holeUnion);
|
|
29314
29365
|
manifoldInstancesForCleanup.push(finalPadOp);
|
|
29315
29366
|
}
|
|
29367
|
+
if (boardClipVolume) {
|
|
29368
|
+
const clipped = Manifold.intersection([finalPadOp, boardClipVolume]);
|
|
29369
|
+
manifoldInstancesForCleanup.push(clipped);
|
|
29370
|
+
finalPadOp = clipped;
|
|
29371
|
+
}
|
|
29316
29372
|
const threeGeom = manifoldMeshToThreeGeometry(finalPadOp.getMesh());
|
|
29317
29373
|
smtPadGeoms.push({
|
|
29318
29374
|
key: `pad-${pad2.pcb_smtpad_id || index}`,
|
|
@@ -29339,6 +29395,7 @@ var arePointsClockwise3 = (points) => {
|
|
|
29339
29395
|
};
|
|
29340
29396
|
function createManifoldBoard(Manifold, CrossSection, boardData, pcbThickness, manifoldInstancesForCleanup) {
|
|
29341
29397
|
let boardOp;
|
|
29398
|
+
let outlineCrossSection = null;
|
|
29342
29399
|
if (boardData.outline && boardData.outline.length >= 3) {
|
|
29343
29400
|
let outlineVec2 = boardData.outline.map((p) => [
|
|
29344
29401
|
p.x,
|
|
@@ -29349,6 +29406,7 @@ function createManifoldBoard(Manifold, CrossSection, boardData, pcbThickness, ma
|
|
|
29349
29406
|
}
|
|
29350
29407
|
const crossSection = CrossSection.ofPolygons([outlineVec2]);
|
|
29351
29408
|
manifoldInstancesForCleanup.push(crossSection);
|
|
29409
|
+
outlineCrossSection = crossSection;
|
|
29352
29410
|
boardOp = Manifold.extrude(
|
|
29353
29411
|
crossSection,
|
|
29354
29412
|
pcbThickness,
|
|
@@ -29377,7 +29435,7 @@ function createManifoldBoard(Manifold, CrossSection, boardData, pcbThickness, ma
|
|
|
29377
29435
|
boardOp = boardOp.translate([boardData.center.x, boardData.center.y, 0]);
|
|
29378
29436
|
manifoldInstancesForCleanup.push(boardOp);
|
|
29379
29437
|
}
|
|
29380
|
-
return boardOp;
|
|
29438
|
+
return { boardOp, outlineCrossSection };
|
|
29381
29439
|
}
|
|
29382
29440
|
|
|
29383
29441
|
// src/utils/manifold/process-copper-pours.ts
|
|
@@ -29448,7 +29506,7 @@ function ringToPoints2(ring2, arcSegments) {
|
|
|
29448
29506
|
}
|
|
29449
29507
|
return allPoints;
|
|
29450
29508
|
}
|
|
29451
|
-
function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbThickness, manifoldInstancesForCleanup, holeUnion) {
|
|
29509
|
+
function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbThickness, manifoldInstancesForCleanup, holeUnion, boardClipVolume) {
|
|
29452
29510
|
const copperPourGeoms = [];
|
|
29453
29511
|
const copperPours = circuitJson.filter(
|
|
29454
29512
|
(e) => e.type === "pcb_copper_pour"
|
|
@@ -29535,6 +29593,11 @@ function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbT
|
|
|
29535
29593
|
manifoldInstancesForCleanup.push(withHoles);
|
|
29536
29594
|
pourOp = withHoles;
|
|
29537
29595
|
}
|
|
29596
|
+
if (boardClipVolume) {
|
|
29597
|
+
const clipped = Manifold.intersection([pourOp, boardClipVolume]);
|
|
29598
|
+
manifoldInstancesForCleanup.push(clipped);
|
|
29599
|
+
pourOp = clipped;
|
|
29600
|
+
}
|
|
29538
29601
|
const threeGeom = manifoldMeshToThreeGeometry(pourOp.getMesh());
|
|
29539
29602
|
copperPourGeoms.push({
|
|
29540
29603
|
key: `coppour-${pour.pcb_copper_pour_id}`,
|
|
@@ -29687,13 +29750,51 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
29687
29750
|
try {
|
|
29688
29751
|
const currentPcbThickness = boardData.thickness || 1.6;
|
|
29689
29752
|
setPcbThickness(currentPcbThickness);
|
|
29690
|
-
|
|
29753
|
+
const { boardOp: initialBoardOp, outlineCrossSection } = createManifoldBoard(
|
|
29691
29754
|
Manifold,
|
|
29692
29755
|
CrossSection,
|
|
29693
29756
|
boardData,
|
|
29694
29757
|
currentPcbThickness,
|
|
29695
29758
|
manifoldInstancesForCleanup.current
|
|
29696
29759
|
);
|
|
29760
|
+
let currentBoardOp = initialBoardOp;
|
|
29761
|
+
const BOARD_CLIP_Z_MARGIN2 = 1;
|
|
29762
|
+
const clipThickness = currentPcbThickness + 2 * BOARD_CLIP_Z_MARGIN2;
|
|
29763
|
+
let boardClipVolume = null;
|
|
29764
|
+
const BOARD_CLIP_XY_OUTSET2 = 0.01;
|
|
29765
|
+
if (outlineCrossSection) {
|
|
29766
|
+
let clipCrossSection = outlineCrossSection;
|
|
29767
|
+
if (BOARD_CLIP_XY_OUTSET2 > 0) {
|
|
29768
|
+
const inflatedCrossSection = outlineCrossSection.offset(BOARD_CLIP_XY_OUTSET2);
|
|
29769
|
+
manifoldInstancesForCleanup.current.push(inflatedCrossSection);
|
|
29770
|
+
clipCrossSection = inflatedCrossSection;
|
|
29771
|
+
}
|
|
29772
|
+
const clipOp = Manifold.extrude(
|
|
29773
|
+
clipCrossSection,
|
|
29774
|
+
clipThickness,
|
|
29775
|
+
void 0,
|
|
29776
|
+
void 0,
|
|
29777
|
+
void 0,
|
|
29778
|
+
true
|
|
29779
|
+
);
|
|
29780
|
+
manifoldInstancesForCleanup.current.push(clipOp);
|
|
29781
|
+
boardClipVolume = clipOp;
|
|
29782
|
+
} else {
|
|
29783
|
+
const clipWidth = (boardData.width || 0) + 2 * BOARD_CLIP_XY_OUTSET2;
|
|
29784
|
+
const clipHeight = (boardData.height || 0) + 2 * BOARD_CLIP_XY_OUTSET2;
|
|
29785
|
+
const clipCube = Manifold.cube(
|
|
29786
|
+
[clipWidth, clipHeight, clipThickness],
|
|
29787
|
+
true
|
|
29788
|
+
);
|
|
29789
|
+
manifoldInstancesForCleanup.current.push(clipCube);
|
|
29790
|
+
const translatedClipCube = clipCube.translate([
|
|
29791
|
+
boardData.center.x,
|
|
29792
|
+
boardData.center.y,
|
|
29793
|
+
0
|
|
29794
|
+
]);
|
|
29795
|
+
manifoldInstancesForCleanup.current.push(translatedClipCube);
|
|
29796
|
+
boardClipVolume = translatedClipCube;
|
|
29797
|
+
}
|
|
29697
29798
|
const allBoardDrills = [];
|
|
29698
29799
|
let holeUnion = null;
|
|
29699
29800
|
const { nonPlatedHoleBoardDrills } = processNonPlatedHolesForManifold(
|
|
@@ -29707,7 +29808,8 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
29707
29808
|
Manifold,
|
|
29708
29809
|
circuitJson,
|
|
29709
29810
|
currentPcbThickness,
|
|
29710
|
-
manifoldInstancesForCleanup.current
|
|
29811
|
+
manifoldInstancesForCleanup.current,
|
|
29812
|
+
boardClipVolume
|
|
29711
29813
|
);
|
|
29712
29814
|
allBoardDrills.push(...platedHoleBoardDrills);
|
|
29713
29815
|
currentGeoms.platedHoles = platedHoleCopperGeoms;
|
|
@@ -29715,7 +29817,8 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
29715
29817
|
Manifold,
|
|
29716
29818
|
circuitJson,
|
|
29717
29819
|
currentPcbThickness,
|
|
29718
|
-
manifoldInstancesForCleanup.current
|
|
29820
|
+
manifoldInstancesForCleanup.current,
|
|
29821
|
+
boardClipVolume
|
|
29719
29822
|
);
|
|
29720
29823
|
allBoardDrills.push(...viaBoardDrills);
|
|
29721
29824
|
currentGeoms.vias = viaCopperGeoms;
|
|
@@ -29760,7 +29863,8 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
29760
29863
|
circuitJson,
|
|
29761
29864
|
currentPcbThickness,
|
|
29762
29865
|
manifoldInstancesForCleanup.current,
|
|
29763
|
-
holeUnion
|
|
29866
|
+
holeUnion,
|
|
29867
|
+
boardClipVolume
|
|
29764
29868
|
);
|
|
29765
29869
|
currentGeoms.smtPads = smtPadGeoms;
|
|
29766
29870
|
const { copperPourGeoms } = processCopperPoursForManifold(
|
|
@@ -29769,7 +29873,8 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
29769
29873
|
circuitJson,
|
|
29770
29874
|
currentPcbThickness,
|
|
29771
29875
|
manifoldInstancesForCleanup.current,
|
|
29772
|
-
holeUnion
|
|
29876
|
+
holeUnion,
|
|
29877
|
+
boardClipVolume
|
|
29773
29878
|
);
|
|
29774
29879
|
currentGeoms.copperPours = copperPourGeoms;
|
|
29775
29880
|
setGeoms(currentGeoms);
|