circuit-json-to-lbrn 0.0.41 → 0.0.43

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.
Files changed (91) hide show
  1. package/dist/index.d.ts +12 -1
  2. package/dist/index.js +191 -4
  3. package/lib/ConvertContext.ts +7 -0
  4. package/lib/createCopperCutFillForLayer.ts +232 -0
  5. package/lib/index.ts +70 -4
  6. package/package.json +3 -2
  7. package/site/index.html +40 -5
  8. package/site/main.tsx +13 -0
  9. package/tests/basics/__snapshots__/board-outline-does-not-appear-in soldermask.snap.svg +1 -1
  10. package/tests/basics/__snapshots__/board-outline.snap.svg +1 -1
  11. package/tests/basics/__snapshots__/mixed-soldermask-margins.snap.svg +1 -1
  12. package/tests/basics/addPcbCutout/__snapshots__/pcb-cutout-circle.snap.svg +1 -1
  13. package/tests/basics/addPcbCutout/__snapshots__/pcb-cutout-path.snap.svg +1 -1
  14. package/tests/basics/addPcbCutout/__snapshots__/pcb-cutout-polygon.snap.svg +1 -1
  15. package/tests/basics/addPcbCutout/__snapshots__/pcb-cutout-rect.snap.svg +1 -1
  16. package/tests/basics/addPcbCutout/pcb-cutout-circle.test.ts +1 -1
  17. package/tests/basics/addPcbCutout/pcb-cutout-path.test.ts +1 -1
  18. package/tests/basics/addPcbCutout/pcb-cutout-polygon.test.ts +1 -1
  19. package/tests/basics/addPcbCutout/pcb-cutout-rect.test.ts +1 -1
  20. package/tests/basics/addPcbHole/__snapshots__/pcb-hole-circle.snap.svg +1 -1
  21. package/tests/basics/addPcbHole/__snapshots__/pcb-hole-oval.snap.svg +1 -1
  22. package/tests/basics/addPcbHole/__snapshots__/pcb-hole-pill.snap.svg +1 -1
  23. package/tests/basics/addPcbHole/__snapshots__/pcb-hole-rect.snap.svg +1 -1
  24. package/tests/basics/addPcbHole/__snapshots__/pcb-hole-rotated-pill.snap.svg +1 -1
  25. package/tests/basics/addPcbHole/__snapshots__/pcb-hole-soldermask-margin.snap.svg +1 -1
  26. package/tests/basics/addPcbHole/__snapshots__/pcb-hole-with-soldermask.snap.svg +1 -1
  27. package/tests/basics/addPcbHole/pcb-hole-circle.test.ts +1 -1
  28. package/tests/basics/addPcbHole/pcb-hole-oval.test.ts +1 -1
  29. package/tests/basics/addPcbHole/pcb-hole-pill.test.ts +1 -1
  30. package/tests/basics/addPcbHole/pcb-hole-rect.test.ts +1 -1
  31. package/tests/basics/addPcbHole/pcb-hole-rotated-pill.test.ts +1 -1
  32. package/tests/basics/addPcbHole/pcb-hole-soldermask-margin.test.ts +1 -1
  33. package/tests/basics/addPcbHole/pcb-hole-with-soldermask.test.ts +1 -1
  34. package/tests/basics/addPcbVia/__snapshots__/pcb-via-basic.snap.svg +1 -1
  35. package/tests/basics/addPcbVia/__snapshots__/pcb-via-with-net.snap.svg +1 -1
  36. package/tests/basics/addPcbVia/__snapshots__/pcb-via-with-soldermask.snap.svg +1 -1
  37. package/tests/basics/addPcbVia/pcb-via-basic.test.ts +1 -1
  38. package/tests/basics/addPcbVia/pcb-via-with-net.test.ts +1 -1
  39. package/tests/basics/addPcbVia/pcb-via-with-soldermask.test.ts +1 -1
  40. package/tests/basics/addPlatedHole/__snapshots__/pcb-plated-hole-circular-hole-with-rect-pad.snap.svg +1 -1
  41. package/tests/basics/addPlatedHole/__snapshots__/pcb-plated-hole-oval.snap.svg +1 -1
  42. package/tests/basics/addPlatedHole/__snapshots__/pcb-plated-hole-pill-with-rect-pad.snap.svg +1 -1
  43. package/tests/basics/addPlatedHole/__snapshots__/pcb-plated-hole-pill.snap.svg +1 -1
  44. package/tests/basics/addPlatedHole/__snapshots__/pcb-plated-hole-polygon.snap.svg +1 -1
  45. package/tests/basics/addPlatedHole/__snapshots__/pcb-plated-hole-rotated-pill-with-rect-pad.snap.svg +1 -1
  46. package/tests/basics/addPlatedHole/pcb-plated-hole-circle.test.ts +1 -1
  47. package/tests/basics/addPlatedHole/pcb-plated-hole-circular-hole-with-rect-pad.test.ts +1 -1
  48. package/tests/basics/addPlatedHole/pcb-plated-hole-oval.test.ts +1 -1
  49. package/tests/basics/addPlatedHole/pcb-plated-hole-pill-with-rect-pad.test.ts +1 -1
  50. package/tests/basics/addPlatedHole/pcb-plated-hole-pill.test.ts +1 -1
  51. package/tests/basics/addPlatedHole/pcb-plated-hole-polygon.test.ts +1 -1
  52. package/tests/basics/addPlatedHole/pcb-plated-hole-rotated-pill-with-rect-pad.test.ts +1 -1
  53. package/tests/basics/addSmtPad/__snapshots__/circleSmtPad.snap.svg +1 -1
  54. package/tests/basics/addSmtPad/__snapshots__/pillSmtPad.snap.svg +1 -1
  55. package/tests/basics/addSmtPad/__snapshots__/polygonSmtPad.snap.svg +1 -1
  56. package/tests/basics/addSmtPad/__snapshots__/rotatedPillSmtPad.snap.svg +1 -1
  57. package/tests/basics/addSmtPad/__snapshots__/rotatedRectSmtPad.snap.svg +1 -1
  58. package/tests/basics/addSmtPad/circleSmtPad.test.ts +1 -1
  59. package/tests/basics/addSmtPad/pillSmtPad.test.ts +1 -1
  60. package/tests/basics/addSmtPad/polygonSmtPad.test.ts +1 -1
  61. package/tests/basics/addSmtPad/rotatedPillSmtPad.test.ts +1 -1
  62. package/tests/basics/addSmtPad/rotatedRectSmtPad.test.ts +1 -1
  63. package/tests/basics/board-outline-does-not-appear-in soldermask.test.ts +1 -1
  64. package/tests/basics/board-outline.test.ts +1 -1
  65. package/tests/basics/copper-cut-fill/__snapshots__/copper-cut-fill-basic.snap.svg +8 -0
  66. package/tests/basics/copper-cut-fill/__snapshots__/copper-cut-fill-with-pads.snap.svg +8 -0
  67. package/tests/basics/copper-cut-fill/copper-cut-fill-basic.test.ts +73 -0
  68. package/tests/basics/copper-cut-fill/copper-cut-fill-with-pads.test.ts +128 -0
  69. package/tests/basics/keyboard-defaul60/keyboard-both-layer-includeSoldermask.test.ts +1 -1
  70. package/tests/basics/keyboard-defaul60/keyboard-both-layers.test.ts +1 -1
  71. package/tests/basics/keyboard-defaul60/keyboard-bottom-layer.test.ts +1 -1
  72. package/tests/basics/keyboard-defaul60/keyboard-top-layer.test.ts +1 -1
  73. package/tests/basics/laser-profile.test.ts +4 -4
  74. package/tests/basics/lga-interconnect.test.ts +1 -1
  75. package/tests/basics/mixed-soldermask-margins.test.ts +1 -1
  76. package/tests/basics/single-trace.test.ts +1 -1
  77. package/tests/basics/soldermask/copper-and-soldermask.test.ts +1 -1
  78. package/tests/basics/soldermask/copper-only.test.ts +1 -1
  79. package/tests/basics/soldermask/soldermask-only.test.ts +1 -1
  80. package/tests/basics/soldermask-margin/__snapshots__/percent-soldermask-margin.snap.svg +1 -1
  81. package/tests/basics/soldermask-margin/negative-soldermask-margin.test.ts +1 -1
  82. package/tests/basics/soldermask-margin/percent-soldermask-margin.test.ts +1 -1
  83. package/tests/basics/soldermask-margin/positive-soldermask-margin.test.ts +1 -1
  84. package/tests/basics/trace-margin/pico-w-3x5-led-matrix-trace-margin.test.ts +1 -1
  85. package/tests/basics/trace-margin/trace-margin-basic.test.ts +1 -1
  86. package/tests/basics/trace-margin/trace-margin-error.test.ts +4 -4
  87. package/tests/examples/example01/__snapshots__/example01.snap.svg +1 -1
  88. package/tests/examples/example01/example01.test.ts +1 -1
  89. package/tests/examples/example02/example02.test.ts +1 -1
  90. package/tests/examples/example03/example03.test.ts +1 -1
  91. package/tests/examples/example04/example04.test.ts +1 -1
@@ -0,0 +1,73 @@
1
+ import { expect, test } from "bun:test"
2
+ import type { CircuitJson, SourceTrace } from "circuit-json"
3
+ import { convertCircuitJsonToPcbSvg } from "circuit-to-svg"
4
+ import { generateLightBurnSvg } from "lbrnts"
5
+ import { stackSvgsVertically } from "stack-svgs"
6
+ import { convertCircuitJsonToLbrn } from "../../../lib"
7
+
8
+ /**
9
+ * Test basic copper cut fill functionality with a single trace.
10
+ * The copper cut fill should create a ring/band around the trace that
11
+ * will be laser cut to remove copper, but never cuts into the trace itself.
12
+ */
13
+ test("copper-cut-fill-basic", async () => {
14
+ const circuitJson = [
15
+ {
16
+ type: "pcb_board",
17
+ pcb_board_id: "board_1",
18
+ width: 20,
19
+ height: 20,
20
+ center: { x: 0, y: 0 },
21
+ },
22
+ {
23
+ type: "pcb_trace",
24
+ pcb_trace_id: "trace_1",
25
+ source_trace_id: "trace_1",
26
+ route: [
27
+ {
28
+ x: -5,
29
+ y: 0,
30
+ width: 0.5,
31
+ layer: "top",
32
+ },
33
+ {
34
+ x: 5,
35
+ y: 0,
36
+ width: 0.5,
37
+ layer: "top",
38
+ },
39
+ ],
40
+ },
41
+ {
42
+ type: "source_trace",
43
+ source_trace_id: "trace_1",
44
+ connected_source_net_ids: ["net_1"],
45
+ connected_source_port_ids: [],
46
+ } as SourceTrace,
47
+ {
48
+ type: "source_net",
49
+ source_net_id: "net_1",
50
+ name: "NET1",
51
+ member_source_group_ids: [],
52
+ },
53
+ ] as CircuitJson
54
+
55
+ const pcbSvg = await convertCircuitJsonToPcbSvg(circuitJson)
56
+
57
+ const project = await convertCircuitJsonToLbrn(circuitJson, {
58
+ includeCopper: true,
59
+ includeCopperCutFill: true,
60
+ copperCutFillMargin: 0.5,
61
+ includeLayers: ["top"],
62
+ })
63
+
64
+ Bun.write("debug-output/copper-cut-fill-basic.lbrn2", project.getString(), {
65
+ createPath: true,
66
+ })
67
+
68
+ const lbrnSvg = await generateLightBurnSvg(project)
69
+
70
+ expect(stackSvgsVertically([pcbSvg, lbrnSvg])).toMatchSvgSnapshot(
71
+ import.meta.filename,
72
+ )
73
+ })
@@ -0,0 +1,128 @@
1
+ import { expect, test } from "bun:test"
2
+ import type { CircuitJson, SourceTrace } from "circuit-json"
3
+ import { convertCircuitJsonToPcbSvg } from "circuit-to-svg"
4
+ import { generateLightBurnSvg } from "lbrnts"
5
+ import { stackSvgsVertically } from "stack-svgs"
6
+ import { convertCircuitJsonToLbrn } from "../../../lib"
7
+
8
+ /**
9
+ * Test copper cut fill with traces and SMT pads.
10
+ * The copper cut fill should create a ring/band around both the trace and pads,
11
+ * ensuring that:
12
+ * 1. The cut fill never cuts into the traces or pads
13
+ * 2. The cut fill creates a uniform margin around all copper features
14
+ * 3. Where traces connect to pads, the cut fill is continuous around the connection
15
+ */
16
+ test("copper-cut-fill-with-pads", async () => {
17
+ const circuitJson = [
18
+ {
19
+ type: "pcb_board",
20
+ pcb_board_id: "board_1",
21
+ width: 30,
22
+ height: 20,
23
+ center: { x: 0, y: 0 },
24
+ },
25
+ // Two SMT pads connected by a trace
26
+ {
27
+ type: "pcb_smtpad",
28
+ pcb_smtpad_id: "pad_1",
29
+ shape: "rect",
30
+ x: -8,
31
+ y: 0,
32
+ width: 2,
33
+ height: 3,
34
+ layer: "top",
35
+ pcb_component_id: "comp_1",
36
+ pcb_port_id: "port_1",
37
+ },
38
+ {
39
+ type: "pcb_smtpad",
40
+ pcb_smtpad_id: "pad_2",
41
+ shape: "rect",
42
+ x: 8,
43
+ y: 0,
44
+ width: 2,
45
+ height: 3,
46
+ layer: "top",
47
+ pcb_component_id: "comp_2",
48
+ pcb_port_id: "port_2",
49
+ },
50
+ // Trace connecting the two pads
51
+ {
52
+ type: "pcb_trace",
53
+ pcb_trace_id: "trace_1",
54
+ source_trace_id: "trace_1",
55
+ route: [
56
+ { x: -7, y: 0, width: 0.5, layer: "top" },
57
+ { x: 7, y: 0, width: 0.5, layer: "top" },
58
+ ],
59
+ },
60
+ // PCB ports
61
+ {
62
+ type: "pcb_port",
63
+ pcb_port_id: "port_1",
64
+ pcb_component_id: "comp_1",
65
+ layers: ["top"],
66
+ x: -8,
67
+ y: 0,
68
+ source_port_id: "source_port_1",
69
+ },
70
+ {
71
+ type: "pcb_port",
72
+ pcb_port_id: "port_2",
73
+ pcb_component_id: "comp_2",
74
+ layers: ["top"],
75
+ x: 8,
76
+ y: 0,
77
+ source_port_id: "source_port_2",
78
+ },
79
+ // Source elements for connectivity
80
+ {
81
+ type: "source_port",
82
+ source_port_id: "source_port_1",
83
+ source_component_id: "source_comp_1",
84
+ name: "1",
85
+ },
86
+ {
87
+ type: "source_port",
88
+ source_port_id: "source_port_2",
89
+ source_component_id: "source_comp_2",
90
+ name: "1",
91
+ },
92
+ {
93
+ type: "source_trace",
94
+ source_trace_id: "trace_1",
95
+ connected_source_net_ids: ["net_1"],
96
+ connected_source_port_ids: ["source_port_1", "source_port_2"],
97
+ } as SourceTrace,
98
+ {
99
+ type: "source_net",
100
+ source_net_id: "net_1",
101
+ name: "VCC",
102
+ member_source_group_ids: [],
103
+ },
104
+ ] as CircuitJson
105
+
106
+ const pcbSvg = await convertCircuitJsonToPcbSvg(circuitJson)
107
+
108
+ const project = await convertCircuitJsonToLbrn(circuitJson, {
109
+ includeCopper: true,
110
+ includeCopperCutFill: true,
111
+ copperCutFillMargin: 0.8, // Larger margin to clearly see the cut fill
112
+ includeLayers: ["top"],
113
+ })
114
+
115
+ Bun.write(
116
+ "debug-output/copper-cut-fill-with-pads.lbrn2",
117
+ project.getString(),
118
+ {
119
+ createPath: true,
120
+ },
121
+ )
122
+
123
+ const lbrnSvg = await generateLightBurnSvg(project)
124
+
125
+ expect(stackSvgsVertically([pcbSvg, lbrnSvg])).toMatchSvgSnapshot(
126
+ import.meta.filename,
127
+ )
128
+ })
@@ -10,7 +10,7 @@ import { stackSvgsVertically } from "stack-svgs"
10
10
  test("keyboard-both-layers-includeSoldermask", async () => {
11
11
  const pcbSvg = await convertCircuitJsonToPcbSvg(circuitJson)
12
12
 
13
- const project = convertCircuitJsonToLbrn(circuitJson, {
13
+ const project = await convertCircuitJsonToLbrn(circuitJson, {
14
14
  includeLayers: ["top", "bottom"],
15
15
  includeSoldermask: true,
16
16
  })
@@ -10,7 +10,7 @@ import { stackSvgsVertically } from "stack-svgs"
10
10
  test("keyboard-both-layers", async () => {
11
11
  const pcbSvg = await convertCircuitJsonToPcbSvg(circuitJson)
12
12
 
13
- const project = convertCircuitJsonToLbrn(circuitJson, {
13
+ const project = await convertCircuitJsonToLbrn(circuitJson, {
14
14
  includeLayers: ["top", "bottom"],
15
15
  })
16
16
 
@@ -10,7 +10,7 @@ import { stackSvgsVertically } from "stack-svgs"
10
10
  test("keyboard-bottom-layer", async () => {
11
11
  const pcbSvg = await convertCircuitJsonToPcbSvg(circuitJson)
12
12
 
13
- const project = convertCircuitJsonToLbrn(circuitJson, {
13
+ const project = await convertCircuitJsonToLbrn(circuitJson, {
14
14
  includeLayers: ["bottom"],
15
15
  })
16
16
 
@@ -10,7 +10,7 @@ import { stackSvgsVertically } from "stack-svgs"
10
10
  test("keyboard-top-layer", async () => {
11
11
  const pcbSvg = await convertCircuitJsonToPcbSvg(circuitJson)
12
12
 
13
- const project = convertCircuitJsonToLbrn(circuitJson, {
13
+ const project = await convertCircuitJsonToLbrn(circuitJson, {
14
14
  includeLayers: ["top"],
15
15
  })
16
16
 
@@ -20,8 +20,8 @@ const circuitJson: CircuitJson = [
20
20
  },
21
21
  ]
22
22
 
23
- test("applies custom laserProfile settings", () => {
24
- const project = convertCircuitJsonToLbrn(circuitJson, {
23
+ test("applies custom laserProfile settings", async () => {
24
+ const project = await convertCircuitJsonToLbrn(circuitJson, {
25
25
  laserProfile: {
26
26
  copper: {
27
27
  speed: 350,
@@ -66,8 +66,8 @@ test("applies custom laserProfile settings", () => {
66
66
  expect(throughBoard.pulseWidth).toBe(1.5e-9)
67
67
  })
68
68
 
69
- test("uses default laserProfile settings when not provided", () => {
70
- const project = convertCircuitJsonToLbrn(circuitJson)
69
+ test("uses default laserProfile settings when not provided", async () => {
70
+ const project = await convertCircuitJsonToLbrn(circuitJson)
71
71
 
72
72
  expect(project).toBeDefined()
73
73
  const cutSettings = project.children.filter(
@@ -11,7 +11,7 @@ import type { CircuitJson } from "circuit-json"
11
11
  test("lga-interconnect", async () => {
12
12
  const pcbSvg = await convertCircuitJsonToPcbSvg(circuitJson as CircuitJson)
13
13
 
14
- const project = convertCircuitJsonToLbrn(circuitJson as CircuitJson)
14
+ const project = await convertCircuitJsonToLbrn(circuitJson as CircuitJson)
15
15
 
16
16
  Bun.write("debug-output/lga-interconnect.lbrn2", project.getString(), {
17
17
  createPath: true,
@@ -98,7 +98,7 @@ const circuitJson: CircuitJson = [
98
98
  test("renders mixed elements with global and per-element soldermask margins", async () => {
99
99
  const pcbSvg = await convertCircuitJsonToPcbSvg(circuitJson as CircuitJson)
100
100
 
101
- const project = convertCircuitJsonToLbrn(circuitJson as CircuitJson, {
101
+ const project = await convertCircuitJsonToLbrn(circuitJson as CircuitJson, {
102
102
  includeSoldermask: true,
103
103
  globalCopperSoldermaskMarginAdjustment: 0.2,
104
104
  })
@@ -53,7 +53,7 @@ test("single-trace", async () => {
53
53
 
54
54
  const pcbSvg = await convertCircuitJsonToPcbSvg(circuitJson)
55
55
 
56
- const project = convertCircuitJsonToLbrn(circuitJson)
56
+ const project = await convertCircuitJsonToLbrn(circuitJson)
57
57
 
58
58
  Bun.write("debug-output/single-trace.lbrn2", project.getString(), {
59
59
  createPath: true,
@@ -83,7 +83,7 @@ const circuitJson: CircuitJson = [
83
83
  test("renders both copper and soldermask", async () => {
84
84
  const pcbSvg = await convertCircuitJsonToPcbSvg(circuitJson)
85
85
 
86
- const project = convertCircuitJsonToLbrn(circuitJson, {
86
+ const project = await convertCircuitJsonToLbrn(circuitJson, {
87
87
  includeCopper: true,
88
88
  includeSoldermask: true,
89
89
  })
@@ -83,7 +83,7 @@ const circuitJson: CircuitJson = [
83
83
  test("renders copper only", async () => {
84
84
  const pcbSvg = await convertCircuitJsonToPcbSvg(circuitJson)
85
85
 
86
- const project = convertCircuitJsonToLbrn(circuitJson, {
86
+ const project = await convertCircuitJsonToLbrn(circuitJson, {
87
87
  includeCopper: true,
88
88
  })
89
89
 
@@ -93,7 +93,7 @@ const circuitJson: CircuitJson = [
93
93
  test("renders soldermask only (no copper, no traces)", async () => {
94
94
  const pcbSvg = await convertCircuitJsonToPcbSvg(circuitJson)
95
95
 
96
- const project = convertCircuitJsonToLbrn(circuitJson, {
96
+ const project = await convertCircuitJsonToLbrn(circuitJson, {
97
97
  includeCopper: false,
98
98
  includeSoldermask: true,
99
99
  })