circuit-json-to-lbrn 0.0.44 → 0.0.46
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 +32 -2
- package/lib/ConvertContext.ts +5 -0
- package/lib/createCopperCutFillForLayer.ts +11 -17
- package/lib/index.ts +28 -0
- package/package.json +2 -2
- package/tests/examples/example05/__snapshots__/example05.snap.svg +1 -1
- package/tests/examples/example05/example05.test.ts +57 -5
package/dist/index.js
CHANGED
|
@@ -2577,7 +2577,8 @@ var createCopperCutFillForLayer = async ({
|
|
|
2577
2577
|
bottomCutNetGeoms,
|
|
2578
2578
|
topCopperCutFillCutSetting,
|
|
2579
2579
|
bottomCopperCutFillCutSetting,
|
|
2580
|
-
copperCutFillMargin
|
|
2580
|
+
copperCutFillMargin,
|
|
2581
|
+
boardOutlineContour
|
|
2581
2582
|
} = ctx;
|
|
2582
2583
|
const cutSetting = layer === "top" ? topCopperCutFillCutSetting : bottomCopperCutFillCutSetting;
|
|
2583
2584
|
if (!cutSetting) {
|
|
@@ -2615,7 +2616,14 @@ var createCopperCutFillForLayer = async ({
|
|
|
2615
2616
|
32
|
|
2616
2617
|
// circularSegments for round corners
|
|
2617
2618
|
);
|
|
2618
|
-
|
|
2619
|
+
let cutFillArea = outerBoundary.subtract(copperInside);
|
|
2620
|
+
if (boardOutlineContour && boardOutlineContour.length >= 3) {
|
|
2621
|
+
const boardOutline = new CrossSection([boardOutlineContour], "Positive");
|
|
2622
|
+
const clippedArea = cutFillArea.intersect(boardOutline);
|
|
2623
|
+
cutFillArea.delete();
|
|
2624
|
+
cutFillArea = clippedArea;
|
|
2625
|
+
boardOutline.delete();
|
|
2626
|
+
}
|
|
2619
2627
|
const simplifiedArea = cutFillArea.simplify(1e-3);
|
|
2620
2628
|
const resultContours = simplifiedArea.toPolygons();
|
|
2621
2629
|
if (resultContours.length === 0) {
|
|
@@ -2835,6 +2843,28 @@ var convertCircuitJsonToLbrn = async (circuitJson, options = {}) => {
|
|
|
2835
2843
|
ctx.topScanNetGeoms.set(net, []);
|
|
2836
2844
|
ctx.bottomScanNetGeoms.set(net, []);
|
|
2837
2845
|
}
|
|
2846
|
+
for (const board of db.pcb_board.list()) {
|
|
2847
|
+
if (board.outline?.length) {
|
|
2848
|
+
ctx.boardOutlineContour = board.outline.map((outlinePoint) => [
|
|
2849
|
+
outlinePoint.x + origin.x,
|
|
2850
|
+
outlinePoint.y + origin.y
|
|
2851
|
+
]);
|
|
2852
|
+
} else if (typeof board.width === "number" && typeof board.height === "number" && board.center) {
|
|
2853
|
+
const halfWidth = board.width / 2;
|
|
2854
|
+
const halfHeight = board.height / 2;
|
|
2855
|
+
const minX = board.center.x - halfWidth + origin.x;
|
|
2856
|
+
const minY = board.center.y - halfHeight + origin.y;
|
|
2857
|
+
const maxX = board.center.x + halfWidth + origin.x;
|
|
2858
|
+
const maxY = board.center.y + halfHeight + origin.y;
|
|
2859
|
+
ctx.boardOutlineContour = [
|
|
2860
|
+
[minX, minY],
|
|
2861
|
+
[maxX, minY],
|
|
2862
|
+
[maxX, maxY],
|
|
2863
|
+
[minX, maxY]
|
|
2864
|
+
];
|
|
2865
|
+
}
|
|
2866
|
+
break;
|
|
2867
|
+
}
|
|
2838
2868
|
for (const smtpad of db.pcb_smtpad.list()) {
|
|
2839
2869
|
addSmtPad(smtpad, ctx);
|
|
2840
2870
|
}
|
package/lib/ConvertContext.ts
CHANGED
|
@@ -3,6 +3,8 @@ import type { CutSetting, LightBurnProject } from "lbrnts"
|
|
|
3
3
|
import type { Box, Polygon } from "@flatten-js/core"
|
|
4
4
|
import type { ConnectivityMap } from "circuit-json-to-connectivity-map"
|
|
5
5
|
|
|
6
|
+
type Contour = Array<[number, number]>
|
|
7
|
+
|
|
6
8
|
export type ConnectivityMapKey = string
|
|
7
9
|
|
|
8
10
|
export interface ConvertContext {
|
|
@@ -58,4 +60,7 @@ export interface ConvertContext {
|
|
|
58
60
|
// Key is "x,y" rounded to 6 decimal places
|
|
59
61
|
topTraceEndpoints: Set<string>
|
|
60
62
|
bottomTraceEndpoints: Set<string>
|
|
63
|
+
|
|
64
|
+
// Board outline as a contour for clipping copper cut fill
|
|
65
|
+
boardOutlineContour?: Contour
|
|
61
66
|
}
|
|
@@ -6,22 +6,6 @@ import { getManifold } from "./getManifold"
|
|
|
6
6
|
|
|
7
7
|
type Contour = Array<[number, number]>
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
* Calculates the signed area of a contour.
|
|
11
|
-
* Positive area = counter-clockwise winding (outer boundary)
|
|
12
|
-
* Negative area = clockwise winding (hole)
|
|
13
|
-
*/
|
|
14
|
-
const getSignedArea = (contour: Contour): number => {
|
|
15
|
-
let area = 0
|
|
16
|
-
const n = contour.length
|
|
17
|
-
for (let i = 0; i < n; i++) {
|
|
18
|
-
const j = (i + 1) % n
|
|
19
|
-
area += contour[i]![0] * contour[j]![1]
|
|
20
|
-
area -= contour[j]![0] * contour[i]![1]
|
|
21
|
-
}
|
|
22
|
-
return area / 2
|
|
23
|
-
}
|
|
24
|
-
|
|
25
9
|
/**
|
|
26
10
|
* Converts a flatten-js Polygon to an array of contours for manifold CrossSection
|
|
27
11
|
* Each contour is an array of [x, y] coordinates
|
|
@@ -100,6 +84,7 @@ export const createCopperCutFillForLayer = async ({
|
|
|
100
84
|
topCopperCutFillCutSetting,
|
|
101
85
|
bottomCopperCutFillCutSetting,
|
|
102
86
|
copperCutFillMargin,
|
|
87
|
+
boardOutlineContour,
|
|
103
88
|
} = ctx
|
|
104
89
|
|
|
105
90
|
// Get the appropriate cut setting for this layer
|
|
@@ -157,7 +142,16 @@ export const createCopperCutFillForLayer = async ({
|
|
|
157
142
|
|
|
158
143
|
// Subtract the inside (original copper) from the outer boundary (expanded copper)
|
|
159
144
|
// This gives us the ring/band area to laser cut
|
|
160
|
-
|
|
145
|
+
let cutFillArea = outerBoundary.subtract(copperInside)
|
|
146
|
+
|
|
147
|
+
// Clip to board outline if available
|
|
148
|
+
if (boardOutlineContour && boardOutlineContour.length >= 3) {
|
|
149
|
+
const boardOutline = new CrossSection([boardOutlineContour], "Positive")
|
|
150
|
+
const clippedArea = cutFillArea.intersect(boardOutline)
|
|
151
|
+
cutFillArea.delete()
|
|
152
|
+
cutFillArea = clippedArea
|
|
153
|
+
boardOutline.delete()
|
|
154
|
+
}
|
|
161
155
|
|
|
162
156
|
// Simplify to clean up any spurious tiny segments
|
|
163
157
|
const simplifiedArea = cutFillArea.simplify(0.001)
|
package/lib/index.ts
CHANGED
|
@@ -269,6 +269,34 @@ export const convertCircuitJsonToLbrn = async (
|
|
|
269
269
|
ctx.bottomScanNetGeoms.set(net, [])
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
+
// Extract board outline for clipping copper cut fill
|
|
273
|
+
for (const board of db.pcb_board.list()) {
|
|
274
|
+
if (board.outline?.length) {
|
|
275
|
+
ctx.boardOutlineContour = board.outline.map((outlinePoint) => [
|
|
276
|
+
outlinePoint.x + origin.x,
|
|
277
|
+
outlinePoint.y + origin.y,
|
|
278
|
+
])
|
|
279
|
+
} else if (
|
|
280
|
+
typeof board.width === "number" &&
|
|
281
|
+
typeof board.height === "number" &&
|
|
282
|
+
board.center
|
|
283
|
+
) {
|
|
284
|
+
const halfWidth = board.width / 2
|
|
285
|
+
const halfHeight = board.height / 2
|
|
286
|
+
const minX = board.center.x - halfWidth + origin.x
|
|
287
|
+
const minY = board.center.y - halfHeight + origin.y
|
|
288
|
+
const maxX = board.center.x + halfWidth + origin.x
|
|
289
|
+
const maxY = board.center.y + halfHeight + origin.y
|
|
290
|
+
ctx.boardOutlineContour = [
|
|
291
|
+
[minX, minY],
|
|
292
|
+
[maxX, minY],
|
|
293
|
+
[maxX, maxY],
|
|
294
|
+
[minX, maxY],
|
|
295
|
+
]
|
|
296
|
+
}
|
|
297
|
+
break // Only use the first board
|
|
298
|
+
}
|
|
299
|
+
|
|
272
300
|
// Process all PCB elements
|
|
273
301
|
for (const smtpad of db.pcb_smtpad.list()) {
|
|
274
302
|
addSmtPad(smtpad, ctx)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "circuit-json-to-lbrn",
|
|
3
3
|
"main": "dist/index.js",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.46",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"start": "bun run site/index.html",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"typescript": "^5"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"lbrnts": "^0.0.
|
|
31
|
+
"lbrnts": "^0.0.14",
|
|
32
32
|
"manifold-3d": "^3.3.2"
|
|
33
33
|
}
|
|
34
34
|
}
|