circuit-json-to-lbrn 0.0.21 → 0.0.22
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 +489 -182
- package/lib/ConvertContext.ts +6 -2
- package/lib/element-handlers/addPcbTrace/index.ts +145 -61
- package/lib/element-handlers/addPcbVia/index.ts +34 -12
- package/lib/element-handlers/addPlatedHole/addCirclePlatedHole.ts +34 -12
- package/lib/element-handlers/addPlatedHole/addCircularHoleWithRectPad.ts +24 -9
- package/lib/element-handlers/addPlatedHole/addHoleWithPolygonPad.ts +24 -9
- package/lib/element-handlers/addPlatedHole/addOvalPlatedHole.ts +24 -9
- package/lib/element-handlers/addPlatedHole/addPillHoleWithRectPad.ts +24 -9
- package/lib/element-handlers/addPlatedHole/addPillPlatedHole.ts +24 -9
- package/lib/element-handlers/addPlatedHole/addRotatedPillHoleWithRectPad.ts +24 -9
- package/lib/element-handlers/addSmtPad/addCircleSmtPad.ts +21 -2
- package/lib/element-handlers/addSmtPad/addPillSmtPad.ts +21 -2
- package/lib/element-handlers/addSmtPad/addPolygonSmtPad.ts +20 -2
- package/lib/element-handlers/addSmtPad/addRectSmtPad.ts +20 -3
- package/lib/element-handlers/addSmtPad/addRotatedPillSmtPad.ts +21 -2
- package/lib/element-handlers/addSmtPad/addRotatedRectSmtPad.ts +21 -2
- package/lib/index.ts +92 -41
- package/package.json +1 -1
- package/tests/assets/keyboard-default60.json +92565 -0
- package/tests/examples/__snapshots__/board-outline-soldermask-preset.snap.svg +1 -1
- package/tests/examples/__snapshots__/board-outline.snap.svg +1 -1
- package/tests/examples/__snapshots__/lga-interconnect.snap.svg +1 -1
- package/tests/examples/__snapshots__/single-trace.snap.svg +1 -1
- package/tests/examples/addPcbCutout/__snapshots__/pcb-cutout-circle.snap.svg +1 -1
- package/tests/examples/addPcbCutout/__snapshots__/pcb-cutout-path.snap.svg +1 -1
- package/tests/examples/addPcbCutout/__snapshots__/pcb-cutout-polygon.snap.svg +1 -1
- package/tests/examples/addPcbCutout/__snapshots__/pcb-cutout-rect.snap.svg +1 -1
- package/tests/examples/addPcbHole/__snapshots__/pcb-hole-circle.snap.svg +1 -1
- package/tests/examples/addPcbHole/__snapshots__/pcb-hole-oval.snap.svg +1 -1
- package/tests/examples/addPcbHole/__snapshots__/pcb-hole-pill.snap.svg +1 -1
- package/tests/examples/addPcbHole/__snapshots__/pcb-hole-rect.snap.svg +1 -1
- package/tests/examples/addPcbHole/__snapshots__/pcb-hole-rotated-pill.snap.svg +2 -2
- package/tests/examples/addPcbHole/__snapshots__/pcb-hole-with-soldermask.snap.svg +1 -1
- package/tests/examples/addPcbVia/__snapshots__/pcb-via-basic.snap.svg +1 -1
- package/tests/examples/addPcbVia/__snapshots__/pcb-via-with-net.snap.svg +1 -1
- package/tests/examples/addPcbVia/__snapshots__/pcb-via-with-soldermask.snap.svg +1 -1
- package/tests/examples/addPlatedHole/__snapshots__/pcb-plated-hole-circle.snap.svg +1 -1
- package/tests/examples/addPlatedHole/__snapshots__/pcb-plated-hole-circular-hole-with-rect-pad.snap.svg +1 -1
- package/tests/examples/addPlatedHole/__snapshots__/pcb-plated-hole-oval.snap.svg +1 -1
- package/tests/examples/addPlatedHole/__snapshots__/pcb-plated-hole-pill-with-rect-pad.snap.svg +1 -1
- package/tests/examples/addPlatedHole/__snapshots__/pcb-plated-hole-pill.snap.svg +1 -1
- package/tests/examples/addPlatedHole/__snapshots__/pcb-plated-hole-polygon.snap.svg +1 -1
- package/tests/examples/addPlatedHole/__snapshots__/pcb-plated-hole-rotated-pill-with-rect-pad.snap.svg +1 -1
- package/tests/examples/addSmtPad/__snapshots__/circleSmtPad.snap.svg +1 -1
- package/tests/examples/addSmtPad/__snapshots__/pillSmtPad.snap.svg +1 -1
- package/tests/examples/addSmtPad/__snapshots__/polygonSmtPad.snap.svg +1 -1
- package/tests/examples/addSmtPad/__snapshots__/rotatedPillSmtPad.snap.svg +1 -1
- package/tests/examples/addSmtPad/__snapshots__/rotatedRectSmtPad.snap.svg +1 -1
- package/tests/examples/keyboard-defaul60/__snapshots__/keyboard-both-layer-includeSoldermask.snap.svg +8 -0
- package/tests/examples/keyboard-defaul60/__snapshots__/keyboard-both-layers.snap.svg +8 -0
- package/tests/examples/keyboard-defaul60/__snapshots__/keyboard-bottom-layer.snap.svg +8 -0
- package/tests/examples/keyboard-defaul60/__snapshots__/keyboard-top-layer.snap.svg +8 -0
- package/tests/examples/keyboard-defaul60/keyboard-both-layer-includeSoldermask.test.ts +27 -0
- package/tests/examples/keyboard-defaul60/keyboard-both-layers.test.ts +26 -0
- package/tests/examples/keyboard-defaul60/keyboard-bottom-layer.test.ts +26 -0
- package/tests/examples/keyboard-defaul60/keyboard-top-layer.test.ts +26 -0
- package/tests/examples/lga-interconnect.test.ts +3 -2
- package/tests/examples/soldermask/__snapshots__/copper-and-soldermask.snap.svg +1 -1
- package/tests/examples/soldermask/__snapshots__/copper-only.snap.svg +1 -1
- package/tests/examples/soldermask/__snapshots__/soldermask-only.snap.svg +1 -1
- package/tests/examples/soldermask/copper-and-soldermask.test.ts +18 -10
- package/tests/examples/soldermask/soldermask-only.test.ts +3 -3
- package/tests/examples/soldermask-margin/__snapshots__/negative-soldermask-margin.snap.svg +1 -1
- package/tests/examples/soldermask-margin/__snapshots__/positive-soldermask-margin.snap.svg +1 -1
- package/tsconfig.json +2 -1
|
@@ -9,19 +9,22 @@ export const addPcbPlatedHolePill = (
|
|
|
9
9
|
): void => {
|
|
10
10
|
const {
|
|
11
11
|
project,
|
|
12
|
-
|
|
12
|
+
topCopperCutSetting,
|
|
13
|
+
bottomCopperCutSetting,
|
|
13
14
|
soldermaskCutSetting,
|
|
14
15
|
throughBoardCutSetting,
|
|
15
16
|
origin,
|
|
16
17
|
includeCopper,
|
|
17
18
|
includeSoldermask,
|
|
18
19
|
soldermaskMargin,
|
|
20
|
+
includeLayers,
|
|
19
21
|
} = ctx
|
|
20
22
|
const centerX = platedHole.x + origin.x
|
|
21
23
|
const centerY = platedHole.y + origin.y
|
|
22
24
|
const rotation = (platedHole.ccw_rotation || 0) * (Math.PI / 180) // Convert degrees to radians
|
|
23
25
|
|
|
24
26
|
// Add outer pill shape (copper) if drawing copper
|
|
27
|
+
// Plated holes go through all layers, so add to both top and bottom
|
|
25
28
|
if (
|
|
26
29
|
platedHole.outer_width > 0 &&
|
|
27
30
|
platedHole.outer_height > 0 &&
|
|
@@ -34,14 +37,26 @@ export const addPcbPlatedHolePill = (
|
|
|
34
37
|
height: platedHole.outer_height,
|
|
35
38
|
rotation,
|
|
36
39
|
})
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
if (includeLayers.includes("top")) {
|
|
41
|
+
project.children.push(
|
|
42
|
+
new ShapePath({
|
|
43
|
+
cutIndex: topCopperCutSetting.index,
|
|
44
|
+
verts: outer.verts,
|
|
45
|
+
prims: outer.prims,
|
|
46
|
+
isClosed: true,
|
|
47
|
+
}),
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
if (includeLayers.includes("bottom")) {
|
|
51
|
+
project.children.push(
|
|
52
|
+
new ShapePath({
|
|
53
|
+
cutIndex: bottomCopperCutSetting.index,
|
|
54
|
+
verts: outer.verts,
|
|
55
|
+
prims: outer.prims,
|
|
56
|
+
isClosed: true,
|
|
57
|
+
}),
|
|
58
|
+
)
|
|
59
|
+
}
|
|
45
60
|
}
|
|
46
61
|
|
|
47
62
|
// Add soldermask opening if drawing soldermask
|
|
@@ -10,13 +10,15 @@ export const addRotatedPillHoleWithRectPad = (
|
|
|
10
10
|
): void => {
|
|
11
11
|
const {
|
|
12
12
|
project,
|
|
13
|
-
|
|
13
|
+
topCopperCutSetting,
|
|
14
|
+
bottomCopperCutSetting,
|
|
14
15
|
soldermaskCutSetting,
|
|
15
16
|
throughBoardCutSetting,
|
|
16
17
|
origin,
|
|
17
18
|
includeCopper,
|
|
18
19
|
includeSoldermask,
|
|
19
20
|
soldermaskMargin,
|
|
21
|
+
includeLayers,
|
|
20
22
|
} = ctx
|
|
21
23
|
const centerX = platedHole.x + origin.x
|
|
22
24
|
const centerY = platedHole.y + origin.y
|
|
@@ -38,15 +40,28 @@ export const addRotatedPillHoleWithRectPad = (
|
|
|
38
40
|
})
|
|
39
41
|
|
|
40
42
|
// Add the rectangular pad if drawing copper
|
|
43
|
+
// Plated holes go through all layers, so add to both top and bottom
|
|
41
44
|
if (includeCopper) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
if (includeLayers.includes("top")) {
|
|
46
|
+
project.children.push(
|
|
47
|
+
new ShapePath({
|
|
48
|
+
cutIndex: topCopperCutSetting.index,
|
|
49
|
+
verts: padPath.verts,
|
|
50
|
+
prims: padPath.prims,
|
|
51
|
+
isClosed: true,
|
|
52
|
+
}),
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
if (includeLayers.includes("bottom")) {
|
|
56
|
+
project.children.push(
|
|
57
|
+
new ShapePath({
|
|
58
|
+
cutIndex: bottomCopperCutSetting.index,
|
|
59
|
+
verts: padPath.verts,
|
|
60
|
+
prims: padPath.prims,
|
|
61
|
+
isClosed: true,
|
|
62
|
+
}),
|
|
63
|
+
)
|
|
64
|
+
}
|
|
50
65
|
}
|
|
51
66
|
|
|
52
67
|
// Add soldermask opening if drawing soldermask
|
|
@@ -11,14 +11,33 @@ export const addCircleSmtPad = (
|
|
|
11
11
|
): void => {
|
|
12
12
|
const {
|
|
13
13
|
project,
|
|
14
|
-
|
|
14
|
+
topCopperCutSetting,
|
|
15
|
+
bottomCopperCutSetting,
|
|
15
16
|
soldermaskCutSetting,
|
|
17
|
+
topNetGeoms,
|
|
18
|
+
bottomNetGeoms,
|
|
16
19
|
origin,
|
|
17
20
|
includeCopper,
|
|
18
21
|
includeSoldermask,
|
|
19
22
|
connMap,
|
|
20
23
|
soldermaskMargin,
|
|
24
|
+
includeLayers,
|
|
21
25
|
} = ctx
|
|
26
|
+
|
|
27
|
+
// Filter by layer - only process top and bottom layers
|
|
28
|
+
const padLayer = smtPad.layer || "top"
|
|
29
|
+
if (padLayer !== "top" && padLayer !== "bottom") {
|
|
30
|
+
return // Skip inner layers
|
|
31
|
+
}
|
|
32
|
+
if (!includeLayers.includes(padLayer)) {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Select the correct cut setting and net geoms based on layer
|
|
37
|
+
const copperCutSetting =
|
|
38
|
+
padLayer === "top" ? topCopperCutSetting : bottomCopperCutSetting
|
|
39
|
+
const netGeoms = padLayer === "top" ? topNetGeoms : bottomNetGeoms
|
|
40
|
+
|
|
22
41
|
const centerX = smtPad.x + origin.x
|
|
23
42
|
const centerY = smtPad.y + origin.y
|
|
24
43
|
|
|
@@ -33,7 +52,7 @@ export const addCircleSmtPad = (
|
|
|
33
52
|
|
|
34
53
|
if (netId) {
|
|
35
54
|
// Add to netGeoms to be merged with other elements on the same net
|
|
36
|
-
|
|
55
|
+
netGeoms.get(netId)?.push(polygon)
|
|
37
56
|
} else {
|
|
38
57
|
// No net connection - draw directly
|
|
39
58
|
const outer = createCirclePath({
|
|
@@ -10,14 +10,33 @@ export const addPillSmtPad = (
|
|
|
10
10
|
): void => {
|
|
11
11
|
const {
|
|
12
12
|
project,
|
|
13
|
-
|
|
13
|
+
topCopperCutSetting,
|
|
14
|
+
bottomCopperCutSetting,
|
|
14
15
|
soldermaskCutSetting,
|
|
16
|
+
topNetGeoms,
|
|
17
|
+
bottomNetGeoms,
|
|
15
18
|
origin,
|
|
16
19
|
includeCopper,
|
|
17
20
|
includeSoldermask,
|
|
18
21
|
connMap,
|
|
19
22
|
soldermaskMargin,
|
|
23
|
+
includeLayers,
|
|
20
24
|
} = ctx
|
|
25
|
+
|
|
26
|
+
// Filter by layer - only process top and bottom layers
|
|
27
|
+
const padLayer = smtPad.layer || "top"
|
|
28
|
+
if (padLayer !== "top" && padLayer !== "bottom") {
|
|
29
|
+
return // Skip inner layers
|
|
30
|
+
}
|
|
31
|
+
if (!includeLayers.includes(padLayer)) {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Select the correct cut setting and net geoms based on layer
|
|
36
|
+
const copperCutSetting =
|
|
37
|
+
padLayer === "top" ? topCopperCutSetting : bottomCopperCutSetting
|
|
38
|
+
const netGeoms = padLayer === "top" ? topNetGeoms : bottomNetGeoms
|
|
39
|
+
|
|
21
40
|
const centerX = smtPad.x + origin.x
|
|
22
41
|
const centerY = smtPad.y + origin.y
|
|
23
42
|
|
|
@@ -36,7 +55,7 @@ export const addPillSmtPad = (
|
|
|
36
55
|
|
|
37
56
|
if (netId) {
|
|
38
57
|
// Add to netGeoms to be merged with other elements on the same net
|
|
39
|
-
|
|
58
|
+
netGeoms.get(netId)?.push(polygon)
|
|
40
59
|
} else {
|
|
41
60
|
// No net connection - draw directly
|
|
42
61
|
project.children.push(
|
|
@@ -11,15 +11,33 @@ export const addPolygonSmtPad = (
|
|
|
11
11
|
): void => {
|
|
12
12
|
const {
|
|
13
13
|
project,
|
|
14
|
-
|
|
14
|
+
topCopperCutSetting,
|
|
15
|
+
bottomCopperCutSetting,
|
|
15
16
|
soldermaskCutSetting,
|
|
17
|
+
topNetGeoms,
|
|
18
|
+
bottomNetGeoms,
|
|
16
19
|
origin,
|
|
17
20
|
includeCopper,
|
|
18
21
|
includeSoldermask,
|
|
19
22
|
connMap,
|
|
20
23
|
soldermaskMargin,
|
|
24
|
+
includeLayers,
|
|
21
25
|
} = ctx
|
|
22
26
|
|
|
27
|
+
// Filter by layer - only process top and bottom layers
|
|
28
|
+
const padLayer = smtPad.layer || "top"
|
|
29
|
+
if (padLayer !== "top" && padLayer !== "bottom") {
|
|
30
|
+
return // Skip inner layers
|
|
31
|
+
}
|
|
32
|
+
if (!includeLayers.includes(padLayer)) {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Select the correct cut setting and net geoms based on layer
|
|
37
|
+
const copperCutSetting =
|
|
38
|
+
padLayer === "top" ? topCopperCutSetting : bottomCopperCutSetting
|
|
39
|
+
const netGeoms = padLayer === "top" ? topNetGeoms : bottomNetGeoms
|
|
40
|
+
|
|
23
41
|
// Create the polygon pad
|
|
24
42
|
if (smtPad.points.length >= 3) {
|
|
25
43
|
const pad = createPolygonPathFromOutline({
|
|
@@ -35,7 +53,7 @@ export const addPolygonSmtPad = (
|
|
|
35
53
|
|
|
36
54
|
if (netId) {
|
|
37
55
|
// Add to netGeoms to be merged with other elements on the same net
|
|
38
|
-
|
|
56
|
+
netGeoms.get(netId)?.push(polygon)
|
|
39
57
|
} else {
|
|
40
58
|
// No net connection - draw directly
|
|
41
59
|
project.children.push(
|
|
@@ -6,16 +6,28 @@ import { ShapePath } from "lbrnts"
|
|
|
6
6
|
export const addRectSmtPad = (smtPad: PcbSmtPadRect, ctx: ConvertContext) => {
|
|
7
7
|
const {
|
|
8
8
|
project,
|
|
9
|
-
|
|
9
|
+
topCopperCutSetting,
|
|
10
|
+
bottomCopperCutSetting,
|
|
10
11
|
soldermaskCutSetting,
|
|
11
12
|
connMap,
|
|
12
|
-
|
|
13
|
+
topNetGeoms,
|
|
14
|
+
bottomNetGeoms,
|
|
13
15
|
origin,
|
|
14
16
|
includeCopper,
|
|
15
17
|
includeSoldermask,
|
|
16
18
|
soldermaskMargin,
|
|
19
|
+
includeLayers,
|
|
17
20
|
} = ctx
|
|
18
21
|
|
|
22
|
+
// Filter by layer - only process top and bottom layers
|
|
23
|
+
const padLayer = smtPad.layer || "top"
|
|
24
|
+
if (padLayer !== "top" && padLayer !== "bottom") {
|
|
25
|
+
return // Skip inner layers
|
|
26
|
+
}
|
|
27
|
+
if (!includeLayers.includes(padLayer)) {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
|
|
19
31
|
const centerX = smtPad.x + origin.x
|
|
20
32
|
const centerY = smtPad.y + origin.y
|
|
21
33
|
const halfWidth = smtPad.width / 2
|
|
@@ -23,11 +35,16 @@ export const addRectSmtPad = (smtPad: PcbSmtPadRect, ctx: ConvertContext) => {
|
|
|
23
35
|
|
|
24
36
|
const netId = connMap.getNetConnectedToId(smtPad.pcb_smtpad_id)
|
|
25
37
|
|
|
38
|
+
// Select the correct cut setting and net geoms based on layer
|
|
39
|
+
const copperCutSetting =
|
|
40
|
+
padLayer === "top" ? topCopperCutSetting : bottomCopperCutSetting
|
|
41
|
+
const netGeoms = padLayer === "top" ? topNetGeoms : bottomNetGeoms
|
|
42
|
+
|
|
26
43
|
// Only add to netGeoms if drawing copper
|
|
27
44
|
if (includeCopper) {
|
|
28
45
|
if (netId) {
|
|
29
46
|
// Add to netGeoms to be merged with other elements on the same net
|
|
30
|
-
|
|
47
|
+
netGeoms
|
|
31
48
|
.get(netId)
|
|
32
49
|
?.push(
|
|
33
50
|
new Box(
|
|
@@ -10,14 +10,33 @@ export const addRotatedPillSmtPad = (
|
|
|
10
10
|
): void => {
|
|
11
11
|
const {
|
|
12
12
|
project,
|
|
13
|
-
|
|
13
|
+
topCopperCutSetting,
|
|
14
|
+
bottomCopperCutSetting,
|
|
14
15
|
soldermaskCutSetting,
|
|
16
|
+
topNetGeoms,
|
|
17
|
+
bottomNetGeoms,
|
|
15
18
|
origin,
|
|
16
19
|
includeCopper,
|
|
17
20
|
includeSoldermask,
|
|
18
21
|
connMap,
|
|
19
22
|
soldermaskMargin,
|
|
23
|
+
includeLayers,
|
|
20
24
|
} = ctx
|
|
25
|
+
|
|
26
|
+
// Filter by layer - only process top and bottom layers
|
|
27
|
+
const padLayer = smtPad.layer || "top"
|
|
28
|
+
if (padLayer !== "top" && padLayer !== "bottom") {
|
|
29
|
+
return // Skip inner layers
|
|
30
|
+
}
|
|
31
|
+
if (!includeLayers.includes(padLayer)) {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Select the correct cut setting and net geoms based on layer
|
|
36
|
+
const copperCutSetting =
|
|
37
|
+
padLayer === "top" ? topCopperCutSetting : bottomCopperCutSetting
|
|
38
|
+
const netGeoms = padLayer === "top" ? topNetGeoms : bottomNetGeoms
|
|
39
|
+
|
|
21
40
|
const centerX = smtPad.x + origin.x
|
|
22
41
|
const centerY = smtPad.y + origin.y
|
|
23
42
|
|
|
@@ -37,7 +56,7 @@ export const addRotatedPillSmtPad = (
|
|
|
37
56
|
|
|
38
57
|
if (netId) {
|
|
39
58
|
// Add to netGeoms to be merged with other elements on the same net
|
|
40
|
-
|
|
59
|
+
netGeoms.get(netId)?.push(polygon)
|
|
41
60
|
} else {
|
|
42
61
|
// No net connection - draw directly
|
|
43
62
|
project.children.push(
|
|
@@ -10,14 +10,33 @@ export const addRotatedRectSmtPad = (
|
|
|
10
10
|
): void => {
|
|
11
11
|
const {
|
|
12
12
|
project,
|
|
13
|
-
|
|
13
|
+
topCopperCutSetting,
|
|
14
|
+
bottomCopperCutSetting,
|
|
14
15
|
soldermaskCutSetting,
|
|
16
|
+
topNetGeoms,
|
|
17
|
+
bottomNetGeoms,
|
|
15
18
|
origin,
|
|
16
19
|
includeCopper,
|
|
17
20
|
includeSoldermask,
|
|
18
21
|
connMap,
|
|
19
22
|
soldermaskMargin,
|
|
23
|
+
includeLayers,
|
|
20
24
|
} = ctx
|
|
25
|
+
|
|
26
|
+
// Filter by layer - only process top and bottom layers
|
|
27
|
+
const padLayer = smtPad.layer || "top"
|
|
28
|
+
if (padLayer !== "top" && padLayer !== "bottom") {
|
|
29
|
+
return // Skip inner layers
|
|
30
|
+
}
|
|
31
|
+
if (!includeLayers.includes(padLayer)) {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Select the correct cut setting and net geoms based on layer
|
|
36
|
+
const copperCutSetting =
|
|
37
|
+
padLayer === "top" ? topCopperCutSetting : bottomCopperCutSetting
|
|
38
|
+
const netGeoms = padLayer === "top" ? topNetGeoms : bottomNetGeoms
|
|
39
|
+
|
|
21
40
|
const centerX = smtPad.x + origin.x
|
|
22
41
|
const centerY = smtPad.y + origin.y
|
|
23
42
|
const rotation = (smtPad.ccw_rotation ?? 0) * (Math.PI / 180)
|
|
@@ -41,7 +60,7 @@ export const addRotatedRectSmtPad = (
|
|
|
41
60
|
|
|
42
61
|
if (netId) {
|
|
43
62
|
// Add to netGeoms to be merged with other elements on the same net
|
|
44
|
-
|
|
63
|
+
netGeoms.get(netId)?.push(polygon)
|
|
45
64
|
} else {
|
|
46
65
|
// No net connection - draw directly
|
|
47
66
|
project.children.push(
|
package/lib/index.ts
CHANGED
|
@@ -27,6 +27,7 @@ export const convertCircuitJsonToLbrn = (
|
|
|
27
27
|
includeCopper?: boolean
|
|
28
28
|
includeSoldermask?: boolean
|
|
29
29
|
soldermaskMargin?: number
|
|
30
|
+
includeLayers?: Array<"top" | "bottom">
|
|
30
31
|
} = {},
|
|
31
32
|
): LightBurnProject => {
|
|
32
33
|
const db = cju(circuitJson)
|
|
@@ -35,16 +36,27 @@ export const convertCircuitJsonToLbrn = (
|
|
|
35
36
|
formatVersion: "1",
|
|
36
37
|
})
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
// Default to all layers if not specified
|
|
40
|
+
const includeLayers = options.includeLayers ?? ["top", "bottom"]
|
|
41
|
+
|
|
42
|
+
const topCopperCutSetting = new CutSetting({
|
|
39
43
|
index: 0,
|
|
40
|
-
name: "Cut Copper",
|
|
44
|
+
name: "Cut Top Copper",
|
|
41
45
|
numPasses: 12,
|
|
42
46
|
speed: 100,
|
|
43
47
|
})
|
|
44
|
-
project.children.push(
|
|
48
|
+
project.children.push(topCopperCutSetting)
|
|
45
49
|
|
|
46
|
-
const
|
|
50
|
+
const bottomCopperCutSetting = new CutSetting({
|
|
47
51
|
index: 1,
|
|
52
|
+
name: "Cut Bottom Copper",
|
|
53
|
+
numPasses: 12,
|
|
54
|
+
speed: 100,
|
|
55
|
+
})
|
|
56
|
+
project.children.push(bottomCopperCutSetting)
|
|
57
|
+
|
|
58
|
+
const throughBoardCutSetting = new CutSetting({
|
|
59
|
+
index: 2,
|
|
48
60
|
name: "Cut Through Board",
|
|
49
61
|
numPasses: 3,
|
|
50
62
|
speed: 50,
|
|
@@ -52,14 +64,14 @@ export const convertCircuitJsonToLbrn = (
|
|
|
52
64
|
project.children.push(throughBoardCutSetting)
|
|
53
65
|
|
|
54
66
|
const soldermaskCutSetting = new CutSetting({
|
|
55
|
-
type: "Scan", // Use Scan mode to fill
|
|
56
|
-
index:
|
|
67
|
+
type: "Scan", // Use Scan mode to fill pad shapes for Kapton tape cutting
|
|
68
|
+
index: 3,
|
|
57
69
|
name: "Cut Soldermask",
|
|
58
70
|
numPasses: 1,
|
|
59
71
|
speed: 150,
|
|
60
72
|
scanOpt: "individual", // Scan each shape individually
|
|
61
73
|
interval: 0.18, // Distance between cross-hatch lines
|
|
62
|
-
angle: 45, // Angle of
|
|
74
|
+
angle: 45, // Angle of cross-hatch lines
|
|
63
75
|
crossHatch: true,
|
|
64
76
|
})
|
|
65
77
|
project.children.push(soldermaskCutSetting)
|
|
@@ -76,19 +88,23 @@ export const convertCircuitJsonToLbrn = (
|
|
|
76
88
|
const ctx: ConvertContext = {
|
|
77
89
|
db,
|
|
78
90
|
project,
|
|
79
|
-
|
|
91
|
+
topCopperCutSetting,
|
|
92
|
+
bottomCopperCutSetting,
|
|
80
93
|
throughBoardCutSetting,
|
|
81
94
|
soldermaskCutSetting,
|
|
82
95
|
connMap,
|
|
83
|
-
|
|
96
|
+
topNetGeoms: new Map(),
|
|
97
|
+
bottomNetGeoms: new Map(),
|
|
84
98
|
origin,
|
|
85
99
|
includeCopper: options.includeCopper ?? true,
|
|
86
100
|
includeSoldermask: options.includeSoldermask ?? false,
|
|
87
101
|
soldermaskMargin: options.soldermaskMargin ?? 0,
|
|
102
|
+
includeLayers,
|
|
88
103
|
}
|
|
89
104
|
|
|
90
105
|
for (const net of Object.keys(connMap.netMap)) {
|
|
91
|
-
ctx.
|
|
106
|
+
ctx.topNetGeoms.set(net, [])
|
|
107
|
+
ctx.bottomNetGeoms.set(net, [])
|
|
92
108
|
}
|
|
93
109
|
|
|
94
110
|
for (const smtpad of db.pcb_smtpad.list()) {
|
|
@@ -149,42 +165,77 @@ export const convertCircuitJsonToLbrn = (
|
|
|
149
165
|
// Create a union of all the net geoms, and add to project
|
|
150
166
|
// Only do this when including copper
|
|
151
167
|
if (ctx.includeCopper) {
|
|
152
|
-
|
|
153
|
-
|
|
168
|
+
// Process top layer
|
|
169
|
+
if (includeLayers.includes("top")) {
|
|
170
|
+
for (const net of Object.keys(connMap.netMap)) {
|
|
171
|
+
const netGeoms = ctx.topNetGeoms.get(net)!
|
|
154
172
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
173
|
+
if (netGeoms.length === 0) {
|
|
174
|
+
continue
|
|
175
|
+
}
|
|
158
176
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
177
|
+
let union = netGeoms[0]!
|
|
178
|
+
if (union instanceof Box) {
|
|
179
|
+
union = new Polygon(union)
|
|
180
|
+
}
|
|
181
|
+
for (const geom of netGeoms.slice(1)) {
|
|
182
|
+
if (geom instanceof Polygon) {
|
|
183
|
+
union = BooleanOperations.unify(union, geom)
|
|
184
|
+
} else if (geom instanceof Box) {
|
|
185
|
+
union = BooleanOperations.unify(union, new Polygon(geom))
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
for (const island of union.splitToIslands()) {
|
|
190
|
+
// Convert the polygon to verts and prims
|
|
191
|
+
const { verts, prims } = polygonToShapePathData(island)
|
|
192
|
+
|
|
193
|
+
project.children.push(
|
|
194
|
+
new ShapePath({
|
|
195
|
+
cutIndex: topCopperCutSetting.index,
|
|
196
|
+
verts,
|
|
197
|
+
prims,
|
|
198
|
+
isClosed: false,
|
|
199
|
+
}),
|
|
200
|
+
)
|
|
168
201
|
}
|
|
169
202
|
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Process bottom layer
|
|
206
|
+
if (includeLayers.includes("bottom")) {
|
|
207
|
+
for (const net of Object.keys(connMap.netMap)) {
|
|
208
|
+
const netGeoms = ctx.bottomNetGeoms.get(net)!
|
|
170
209
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
)
|
|
210
|
+
if (netGeoms.length === 0) {
|
|
211
|
+
continue
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
let union = netGeoms[0]!
|
|
215
|
+
if (union instanceof Box) {
|
|
216
|
+
union = new Polygon(union)
|
|
217
|
+
}
|
|
218
|
+
for (const geom of netGeoms.slice(1)) {
|
|
219
|
+
if (geom instanceof Polygon) {
|
|
220
|
+
union = BooleanOperations.unify(union, geom)
|
|
221
|
+
} else if (geom instanceof Box) {
|
|
222
|
+
union = BooleanOperations.unify(union, new Polygon(geom))
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
for (const island of union.splitToIslands()) {
|
|
227
|
+
// Convert the polygon to verts and prims
|
|
228
|
+
const { verts, prims } = polygonToShapePathData(island)
|
|
229
|
+
|
|
230
|
+
project.children.push(
|
|
231
|
+
new ShapePath({
|
|
232
|
+
cutIndex: bottomCopperCutSetting.index,
|
|
233
|
+
verts,
|
|
234
|
+
prims,
|
|
235
|
+
isClosed: false,
|
|
236
|
+
}),
|
|
237
|
+
)
|
|
238
|
+
}
|
|
188
239
|
}
|
|
189
240
|
}
|
|
190
241
|
}
|