Skip to content

Commit e8b26dc

Browse files
authored
Support top and bottom courtyard layers in footprint generation (#30)
1 parent da46d83 commit e8b26dc

2 files changed

Lines changed: 26 additions & 98 deletions

File tree

lib/generate-footprint-tsx.tsx

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -243,50 +243,25 @@ export const generateFootprintTsx = (
243243
}
244244

245245
for (const courtyardOutline of courtyardOutlines) {
246-
const courtyardOutlineAny = courtyardOutline as any
247246
const attrs = [
248247
`outline={${JSON.stringify(courtyardOutline.outline ?? [])}}`,
249248
]
250-
251-
if (courtyardOutlineAny.stroke_width !== undefined) {
252-
attrs.push(`strokeWidth={${courtyardOutlineAny.stroke_width}}`)
253-
}
254-
if (courtyardOutlineAny.is_closed !== undefined) {
255-
attrs.push(`isClosed={${courtyardOutlineAny.is_closed}}`)
256-
}
257-
if (courtyardOutlineAny.is_stroke_dashed !== undefined) {
258-
attrs.push(`isStrokeDashed={${courtyardOutlineAny.is_stroke_dashed}}`)
259-
}
260-
if (courtyardOutlineAny.color !== undefined) {
261-
attrs.push(`color="${courtyardOutlineAny.color}"`)
249+
if (courtyardOutline.layer !== undefined) {
250+
attrs.push(`layer="${courtyardOutline.layer}"`)
262251
}
263252

264253
elementStrings.push(`<courtyardoutline ${attrs.join(" ")} />`)
265254
}
266255

267256
for (const courtyardRect of courtyardRects) {
268-
const courtyardRectAny = courtyardRect as any
269257
const attrs = [
270258
`pcbX={${courtyardRect.center?.x ?? 0}}`,
271259
`pcbY={${courtyardRect.center?.y ?? 0}}`,
272260
`width={${courtyardRect.width ?? 0}}`,
273261
`height={${courtyardRect.height ?? 0}}`,
274262
]
275-
276-
if (courtyardRectAny.stroke_width !== undefined) {
277-
attrs.push(`strokeWidth={${courtyardRectAny.stroke_width}}`)
278-
}
279-
if (courtyardRectAny.is_filled !== undefined) {
280-
attrs.push(`isFilled={${courtyardRectAny.is_filled}}`)
281-
}
282-
if (courtyardRectAny.has_stroke !== undefined) {
283-
attrs.push(`hasStroke={${courtyardRectAny.has_stroke}}`)
284-
}
285-
if (courtyardRectAny.is_stroke_dashed !== undefined) {
286-
attrs.push(`isStrokeDashed={${courtyardRectAny.is_stroke_dashed}}`)
287-
}
288-
if (courtyardRectAny.color !== undefined) {
289-
attrs.push(`color="${courtyardRectAny.color}"`)
263+
if (courtyardRect.layer !== undefined) {
264+
attrs.push(`layer="${courtyardRect.layer}"`)
290265
}
291266

292267
elementStrings.push(`<courtyardrect ${attrs.join(" ")} />`)
Lines changed: 22 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { expect, test } from "bun:test"
2-
import { convertCircuitJsonToPcbSvg } from "circuit-to-svg"
32
import { convertCircuitJsonToTscircuit } from "lib"
43
import { runTscircuitCode } from "tscircuit"
54

@@ -13,17 +12,18 @@ test("test8 support courtyard elements", async () => {
1312
export const Test8Component = (props: ChipProps) => (
1413
<chip
1514
footprint={<footprint>
16-
<smtpad portHints={[\"1\"]} pcbX=\"-0.5mm\" pcbY=\"0mm\" width=\"0.6mm\" height=\"0.9mm\" shape=\"rect\" />
17-
<courtyardoutline outline={[{\"x\":-1.8,\"y\":-1.4},{\"x\":1.8,\"y\":-1.4},{\"x\":1.8,\"y\":1.4},{\"x\":-1.8,\"y\":1.4}]} strokeWidth={0.12} isClosed={true} isStrokeDashed={true} color=\"#ff00ff\" />
18-
<courtyardrect pcbX={0} pcbY={0} width={4} height={3} strokeWidth={0.1} isFilled={false} hasStroke={true} isStrokeDashed={true} color=\"#00ffff\" />
15+
<smtpad portHints={["1"]} pcbX="-0.5mm" pcbY="0mm" width="0.6mm" height="0.9mm" shape="rect" />
16+
<courtyardoutline outline={[{"x":-1.8,"y":-1.4},{"x":1.8,"y":-1.4},{"x":1.8,"y":1.4},{"x":-1.8,"y":1.4}]} layer="top" />
17+
<courtyardrect pcbX={0} pcbY={0} width={4} height={3} layer="top" />
18+
<courtyardrect pcbX={0.2} pcbY={0.2} width={4.6} height={3.6} layer="bottom" />
1919
</footprint>}
2020
{...props}
2121
/>
2222
)"
2323
`)
2424
})
2525

26-
test("test8 pcb svg snapshot includes courtyard geometry", async () => {
26+
test("test8 renders courtyard as courtyard circuit json", async () => {
2727
const tscircuit = convertCircuitJsonToTscircuit(circuitJson, {
2828
componentName: "Test8Component",
2929
})
@@ -32,7 +32,7 @@ test("test8 pcb svg snapshot includes courtyard geometry", async () => {
3232
${tscircuit}
3333
3434
circuit.add(
35-
<board width=\"20mm\" height=\"20mm\">
35+
<board width="20mm" height="20mm">
3636
<Test8Component />
3737
</board>,
3838
)
@@ -42,62 +42,15 @@ circuit.add(
4242
["pcb_courtyard_outline", "pcb_courtyard_rect"].includes(elm.type),
4343
)
4444

45-
expect(courtyardElements.length).toBeGreaterThan(0)
46-
47-
const pcbSvg = convertCircuitJsonToPcbSvg([
48-
...renderedCircuitJson,
49-
...projectCourtyardToFabricationNotes(courtyardElements),
50-
])
51-
52-
await expect(pcbSvg).toMatchSvgSnapshot(import.meta.path, "courtyard-pcb")
45+
expect(courtyardElements).toHaveLength(6)
46+
expect(
47+
courtyardElements.filter((elm) => elm.type === "pcb_courtyard_outline"),
48+
).toHaveLength(2)
49+
expect(
50+
courtyardElements.filter((elm) => elm.type === "pcb_courtyard_rect"),
51+
).toHaveLength(4)
5352
})
5453

55-
const projectCourtyardToFabricationNotes = (courtyardElements: any[]) => {
56-
const projected: any[] = []
57-
58-
for (const elm of courtyardElements) {
59-
if (elm.type === "pcb_courtyard_outline") {
60-
const route = [...(elm.outline ?? [])]
61-
if (elm.is_closed && route.length > 1) {
62-
const firstPoint = route[0]
63-
const lastPoint = route[route.length - 1]
64-
if (firstPoint.x !== lastPoint.x || firstPoint.y !== lastPoint.y) {
65-
route.push(firstPoint)
66-
}
67-
}
68-
69-
projected.push({
70-
type: "pcb_fabrication_note_path",
71-
pcb_fabrication_note_path_id: `projected_fnp_${elm.pcb_courtyard_outline_id}`,
72-
pcb_component_id: elm.pcb_component_id,
73-
layer: elm.layer,
74-
route,
75-
stroke_width: elm.stroke_width ?? 0.1,
76-
color: elm.color,
77-
})
78-
}
79-
80-
if (elm.type === "pcb_courtyard_rect") {
81-
projected.push({
82-
type: "pcb_fabrication_note_rect",
83-
pcb_fabrication_note_rect_id: `projected_fnr_${elm.pcb_courtyard_rect_id}`,
84-
pcb_component_id: elm.pcb_component_id,
85-
layer: elm.layer,
86-
center: elm.center,
87-
width: elm.width,
88-
height: elm.height,
89-
stroke_width: elm.stroke_width ?? 0.1,
90-
is_filled: elm.is_filled ?? false,
91-
has_stroke: elm.has_stroke ?? true,
92-
is_stroke_dashed: elm.is_stroke_dashed,
93-
color: elm.color,
94-
})
95-
}
96-
}
97-
98-
return projected
99-
}
100-
10154
const circuitJson: any = [
10255
{
10356
type: "source_component",
@@ -154,10 +107,6 @@ const circuitJson: any = [
154107
{ x: 1.8, y: 1.4 },
155108
{ x: -1.8, y: 1.4 },
156109
],
157-
stroke_width: 0.12,
158-
is_closed: true,
159-
is_stroke_dashed: true,
160-
color: "#ff00ff",
161110
},
162111
{
163112
type: "pcb_courtyard_rect",
@@ -167,10 +116,14 @@ const circuitJson: any = [
167116
width: 4,
168117
height: 3,
169118
layer: "top",
170-
stroke_width: 0.1,
171-
is_filled: false,
172-
has_stroke: true,
173-
is_stroke_dashed: true,
174-
color: "#00ffff",
119+
},
120+
{
121+
type: "pcb_courtyard_rect",
122+
pcb_courtyard_rect_id: "pcb_courtyard_rect_1",
123+
pcb_component_id: "pcb_generic_component_0",
124+
center: { x: 0.2, y: 0.2 },
125+
width: 4.6,
126+
height: 3.6,
127+
layer: "bottom",
175128
},
176129
]

0 commit comments

Comments
 (0)