Skip to content

Commit a31de95

Browse files
committed
up in 1mm
1 parent 780c7d9 commit a31de95

File tree

5 files changed

+114
-2
lines changed

5 files changed

+114
-2
lines changed

src/convert-kicad-json-to-tscircuit-soup.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ export const convertKicadJsonToTsCircuitSoup = async (
620620
const mid = makePoint(segment.mid)
621621
const end = makePoint(segment.end)
622622
const arcLength = getArcLength(start, mid, end)
623-
const numPoints = Math.max(8, Math.ceil(arcLength * 10))
623+
const numPoints = Math.max(8, Math.ceil(arcLength))
624624
const arcPoints = generateArcPath(start, mid, end, numPoints).map(
625625
(p) => ({
626626
x: p.x,
@@ -632,7 +632,35 @@ export const convertKicadJsonToTsCircuitSoup = async (
632632
arcPoints.shift()
633633
}
634634
}
635-
for (const point of arcPoints) {
635+
const adjustedNumPoints = Math.max(2, Math.ceil(arcLength / 0.1))
636+
const arcPointsAdjusted = generateArcPath(
637+
start,
638+
mid,
639+
end,
640+
adjustedNumPoints,
641+
).map((p) => ({
642+
x: p.x,
643+
y: -p.y,
644+
}))
645+
646+
if (arcPointsAdjusted.length > 0 && route.length > 0) {
647+
if (
648+
pointsAreClose(route[route.length - 1]!, arcPointsAdjusted[0]!)
649+
) {
650+
arcPointsAdjusted.shift()
651+
}
652+
}
653+
for (let i = 0; i < arcPointsAdjusted.length - 1; i++) {
654+
const p0 = arcPointsAdjusted[i]!
655+
const p1 = arcPointsAdjusted[i + 1]!
656+
const dx = p1.x - p0.x
657+
const dy = p1.y - p0.y
658+
const segmentArcLength = Math.sqrt(dx * dx + dy * dy)
659+
console.log(`Segment ${i} length:`, segmentArcLength)
660+
}
661+
// now refactor the code to use arcPointsAdjusted
662+
663+
for (const point of arcPointsAdjusted) {
636664
pushRoutePoint(point)
637665
}
638666
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
(footprint "viaGrid-pacman-1mm"
2+
(version 20241229)
3+
(generator "pcbnew")
4+
(generator_version "9.0")
5+
(layer "F.Cu")
6+
(property "Reference" "REF**"
7+
(at 0 -0.25 0)
8+
(unlocked yes)
9+
(layer "F.SilkS")
10+
(hide yes)
11+
(effects (font (size 0.25 0.25) (thickness 0.05)))
12+
)
13+
(property "Value" "viaGrid-pacman-1mm"
14+
(at 0 0.5 0)
15+
(unlocked yes)
16+
(layer "F.Fab")
17+
(hide yes)
18+
(effects (font (size 0.25 0.25) (thickness 0.05)))
19+
)
20+
(attr smd)
21+
(fp_poly
22+
(pts
23+
(xy 0.5 0.04)
24+
(xy -0.04 0.04)
25+
(xy -0.039999 -0.5)
26+
(arc
27+
(start -0.04 -0.5)
28+
(mid -0.354683 0.354683)
29+
(end 0.5 0.04)
30+
)
31+
)
32+
(stroke (width 0) (type solid))
33+
(fill yes)
34+
(layer "F.Cu")
35+
)
36+
)
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { test, expect } from "bun:test"
2+
import { parseKicadModToCircuitJson } from "src"
3+
import fs from "fs"
4+
import { join } from "path"
5+
import { convertCircuitJsonToPcbSvg } from "circuit-to-svg"
6+
7+
test("fp_poly with arc segments loads without NaNs", async () => {
8+
const fixturePath = join(
9+
import.meta.dirname,
10+
"..",
11+
"data",
12+
"viaGrid-pacman-1mm.kicad_mod",
13+
)
14+
const fileContent = fs.readFileSync(fixturePath, "utf-8")
15+
16+
const circuitJson = await parseKicadModToCircuitJson(fileContent)
17+
const result = convertCircuitJsonToPcbSvg(circuitJson as any)
18+
// validate the segment length should be around 0.1mm
19+
const arcSegments = result.match(/<path d="([^"]+)"/g) || []
20+
for (const pathTag of arcSegments) {
21+
const dAttrMatch = pathTag.match(/<path d="([^"]+)"/)
22+
if (!dAttrMatch) continue
23+
const dAttr = dAttrMatch[1]
24+
const commands = dAttr.match(/[ML][^ML]+/g) || []
25+
for (let i = 1; i < commands.length; i++) {
26+
const [x1, y1] = commands[i - 1].slice(1).trim().split(" ").map(Number)
27+
const [x2, y2] = commands[i].slice(1).trim().split(" ").map(Number)
28+
const segmentLength = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
29+
expect(segmentLength).toBeLessThanOrEqual(0.1) // allow small tolerance
30+
}
31+
}
32+
expect(result).toMatchSvgSnapshot(import.meta.path)
33+
})

tests/repros/fp-poly-arc-loading.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,19 @@ test("fp_poly with arc segments loads without NaNs", async () => {
1515

1616
const circuitJson = await parseKicadModToCircuitJson(fileContent)
1717
const result = convertCircuitJsonToPcbSvg(circuitJson as any)
18+
// validate the segment length should be around 0.1mm
19+
const arcSegments = result.match(/<path d="([^"]+)"/g) || []
20+
for (const pathTag of arcSegments) {
21+
const dAttrMatch = pathTag.match(/<path d="([^"]+)"/)
22+
if (!dAttrMatch) continue
23+
const dAttr = dAttrMatch[1]
24+
const commands = dAttr.match(/[ML][^ML]+/g) || []
25+
for (let i = 1; i < commands.length; i++) {
26+
const [x1, y1] = commands[i - 1].slice(1).trim().split(" ").map(Number)
27+
const [x2, y2] = commands[i].slice(1).trim().split(" ").map(Number)
28+
const segmentLength = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
29+
expect(segmentLength).toBeLessThanOrEqual(0.1) // allow small tolerance
30+
}
31+
}
1832
expect(result).toMatchSvgSnapshot(import.meta.path)
1933
})

0 commit comments

Comments
 (0)