diff --git a/src/fn/lga.ts b/src/fn/lga.ts
index 1d7cab98..cbcb12d8 100644
--- a/src/fn/lga.ts
+++ b/src/fn/lga.ts
@@ -51,8 +51,20 @@ export const lga = (
)
}
- const width = parameters.w ?? (grid.y - 1) * parameters.p + 2 * parameters.pl
- const height = parameters.h ?? (grid.x - 1) * parameters.p + 2 * parameters.pl
+ // The default body size must leave room for the pads on the perpendicular
+ // sides: without the corner allowance, the inner edge of the left/right
+ // pads lands exactly on the center line of the outermost top/bottom pads
+ // (and vice versa), so corner pads overlap. Only needed when pads exist on
+ // adjacent sides.
+ const cornerPadClearance = 0.2
+ const cornerAllowance =
+ grid.x > 0 && grid.y > 0 ? parameters.pw + 2 * cornerPadClearance : 0
+ const width =
+ parameters.w ??
+ (grid.y - 1) * parameters.p + 2 * parameters.pl + cornerAllowance
+ const height =
+ parameters.h ??
+ (grid.x - 1) * parameters.p + 2 * parameters.pl + cornerAllowance
const leftRightX = (width - parameters.pl) / 2
const topBottomY = (height - parameters.pl) / 2
const pads: AnyCircuitElement[] = []
diff --git a/tests/__snapshots__/lga14.snap.svg b/tests/__snapshots__/lga14.snap.svg
new file mode 100644
index 00000000..ac444bc8
--- /dev/null
+++ b/tests/__snapshots__/lga14.snap.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tests/__snapshots__/lga8.snap.svg b/tests/__snapshots__/lga8.snap.svg
new file mode 100644
index 00000000..7b763764
--- /dev/null
+++ b/tests/__snapshots__/lga8.snap.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tests/lga.test.ts b/tests/lga.test.ts
index 65f3f3d4..716180ec 100644
--- a/tests/lga.test.ts
+++ b/tests/lga.test.ts
@@ -63,3 +63,34 @@ test("lga rejects a side grid that does not match its pad count", () => {
"requires 16 pads, got 14",
)
})
+
+const getMinPadToPadClearance = (footprint: string) => {
+ const pads = getPads(footprint)
+ let minClearance = Number.POSITIVE_INFINITY
+ for (let i = 0; i < pads.length; i++) {
+ for (let j = i + 1; j < pads.length; j++) {
+ const a = pads[i]
+ const b = pads[j]
+ if (!a || !b) continue
+ const dx = Math.max(0, Math.abs(a.x - b.x) - (a.width + b.width) / 2)
+ const dy = Math.max(0, Math.abs(a.y - b.y) - (a.height + b.height) / 2)
+ minClearance = Math.min(minClearance, Math.hypot(dx, dy))
+ }
+ }
+ return minClearance
+}
+
+test("lga14 and lga8 keep clearance between corner pads", () => {
+ // Regression test: with the default (derived) body size, the inner edge of
+ // the left/right pads landed exactly on the center line of the outermost
+ // top/bottom pads, so corner pads overlapped with 0mm clearance.
+ expect(getMinPadToPadClearance("lga14")).toBeGreaterThan(0.1)
+ expect(getMinPadToPadClearance("lga8")).toBeGreaterThan(0.1)
+
+ expect(
+ convertCircuitJsonToPcbSvg(fp.string("lga14").circuitJson()),
+ ).toMatchSvgSnapshot(import.meta.path, "lga14")
+ expect(
+ convertCircuitJsonToPcbSvg(fp.string("lga8").circuitJson()),
+ ).toMatchSvgSnapshot(import.meta.path, "lga8")
+})