Repository navigation
Render castellated pad holes with board clipping and continuous outlines - #576
Conversation
qu1ck
left a comment
There was a problem hiding this comment.
Great contribution but needs some changes:
- As far as I can tell the split between board geometry and drill hole geometry is done so that when pads are hidden the notches that the castellated pads create in the outline disappear. I don't think they should disappear at all, hiding pads should not affect visual board outline. So merge the clipping geometry of holes with the board edge geometry on the backend, export only one set of polygons.
- Always clip the silkscreen but not the fab layer.
- 0.001 error in polygon approxymation is way too fine and will generate unnecessarily large amount of vertexes. Use something from 0.01-0.05 range, pick largest one that doesnt make 0.3mm hole look jagged.
- Bezier curve outlines need to be tested
- KiCad 7.0+ API compatibility need to be tested. There are kicad docker images for all versions, use them to generate a simple board BOM in cli mode. It's fine if old kicad does not have new functionality, it just has to not crash and preserve old behavior.
|
|
||
| # Work in native integer coordinates. Tessellate drills to 1 um, | ||
| # independently of the board's (usually coarser) zone-fill setting. | ||
| error = pcbnew.FromMM(0.001) |
| var margin = 1 + 1 / scalefactor; | ||
| path.rect(bbox.minx - margin, bbox.miny - margin, | ||
| bbox.maxx - bbox.minx + 2 * margin, bbox.maxy - bbox.miny + 2 * margin); |
There was a problem hiding this comment.
- The margin is too small. Large pads or silkscreen can extend far beyond the edge and bounding box. Apply a liberally huge margin (say 10x bbox length/width).
- Calculate clipping path with margin once, cache and reuse it.
qu1ck
left a comment
There was a problem hiding this comment.
Looking good, just 2 more minor comments inline.
Also please update DATAFORMAT.md with board_clip field description and rebase the branch on top of master.
| "type": "object", | ||
| "additionalProperties": false, | ||
| "properties": { | ||
| "polygons": { "$ref": "#/definitions/Polygons" } |
There was a problem hiding this comment.
Add option to pass geometry as svgpath. For some CAD packages they might support native arcs in the outline and this is preferable format.
Make any of [svgpath, polygons] required similar to other structs containing svgpath.
| // stroke and the minimum one-pixel width at any zoom. | ||
| ctx.lineWidth = pcbdata.edges.reduce((width, edge) => | ||
| ["segment", "arc", "circle", "curve", "rect", "polygon"].includes(edge.type) | ||
| ? Math.max(width, edge.width || 0) : width, 1 / scalefactor); |
There was a problem hiding this comment.
Reduce edge widths using min(), pick max of that and 1 / scalefactor to ensure it's always visible.
In legacy kicad versions edge thickness was used as margin for zone pullbacks. Picking max thickness can lead to extremely thick outlines in some cases. Nowadays kicad treats all edge lines as 0 thickness for board geometry so min edge thickness is a safe pick.
432a037 to
bb343cb
Compare
|
Thanks for the follow-up review. I’ve addressed the remaining points:
The full suite passed locally on KiCad 7–10, with 16 tests and 24 subtests per version. Browser checks for SVG clipping, outline widths and PNG export also passed. The intermittent outline rejection was traced to three zero-length curves in my test board; after removing them, all repeated Windows and Linux outline checks passed. CI setup is unchanged; the isolated Hatch environment was used only for local testing. |
|
Thanks! |
|
@qu1ck I was wondering if you could publish another release. There have been quite a few new features and bug fixes lately. |




Addresses #325 for KiCad boards.
When a pad drill intersects the PCB boundary, the current viewer draws the complete pad and gray drill, including the portion outside the board. This change clips copper to the physical board region and renders the opening as a notch. The board outline follows the curved notch edge and remains continuous when pad visibility is turned off.
Implementation
This follows the clipping approach suggested in the issue, using KiCad's existing geometry API instead of reconstructing a closed outline from exported Edge.Cuts segments.
GetBoardPolygonOutlines(), including internal cutouts and separate board islands.TransformHoleToPolygon(). A crossing drill must have positive area both inside and outside the original board region. This uses the physical drill geometry, so rotated slots and copper offsets are handled independently.board_clipfor the remaining board interior andedge_drillsfor the crossing-drill union.Path2Dobjects and apply even-odd clipping to normal and highlighted copper, including pads, tracks, zones, and copper footprint drawings. Net hit testing rejects points in removed regions.Geometry construction happens during HTML generation. Browser redraws reuse the cached paths. No additional geometry library is introduced.
Clipping is scoped with canvas save/restore, including the shared-canvas PNG export path. Openings remain transparent rather than being painted with an opaque background color. Ordinary internal drill holes keep their gray appearance. Silkscreen, fabrication graphics, and footprint selection boxes retain their existing behavior.
Before / after
These examples use the same saved STK8321 test board for both renderers. “Before” uses upstream
5114701; “After” uses this implementation. They do not use the intermediate clipping-only implementation as the baseline.With pads visible, complete pads and gray drills extending beyond the edge become clipped pads with open notches:
With pads hidden, the original edge does not show the drill cutouts. The new perimeter explicitly outlines the notches:
KiCad compatibility
aInferOutlineIfNecessary=False, so it does not infer a guessed outline. Tested with KiCad 10.0.6.PM_STRICTLY_SIMPLEwhen that older API constant is available. Automated tests passed in the KiCad 8.0 and 9.0 CI containers. KiCad 10.0.6 was validated locally, including browser rendering and PNG export. Interactive rendering was not separately tested under KiCad 8/9.Malformed outline: no clipping is performed. If KiCad rejects the outline, generation logs
Invalid board outline; copper clipping disabledand falls back to the original rendering. It does not apply a partial or guessed clipping region. Correct the Edge.Cuts geometry, save the PCB, and regenerate the HTML to restore clipping. This fallback and recovery were observed on the test project.Other ECAD formats
The rendering contract is format-independent, but this PR adds automatic clipping-geometry extraction only to the KiCad parser.
board_clipandedge_drillspolygon regions. An external exporter can supply them to use the same renderer behavior.Validation
jsonschemais unavailable in the installed KiCad Python environment.Native regression tests are included in
tests/test_board_clipping.py. Browser checks and screenshots were run locally and are supporting evidence, not part of the committed repository test suite. Full local pytest collection encountered the existing CLI-mode package-initializer issue; native tests were run with unittest and the import smoke test was invoked directly.Scope and tradeoffs
Additional local examples:
STK8321_after.html
STK8321_before.html