Skip to content

copperpour stored as one pcb_copper_pour per fill fragment: KiCad export emits a zone per fragment and refills destroy the pour #2621

Description

@maci0

A single <copperpour> whose fill is split by traces produces one pcb_copper_pour record per disjoint fill fragment, and the KiCad exporter (correctly, given its input) emits one (zone) per record. On a real board we got 65+ GND zones from one pour. Minimal repro (a full-width trace splits the pour; GND anchors on both sides keep both fragments):

export default () => (
  <board width="20mm" height="20mm">
    <resistor name="R1" resistance="1k" footprint="0402" pcbX={-9} pcbY={-5} />
    <resistor name="R2" resistance="1k" footprint="0402" pcbX={9} pcbY={-5} />
    <resistor name="R3" resistance="1k" footprint="0402" pcbX={0} pcbY={5} />
    <trace from=".R1 > .pin2" to=".R2 > .pin1" />
    <trace from=".R3 > .pin1" to="net.GND" />
    <via connectsTo="net.GND" holeDiameter="0.3mm" outerDiameter="0.6mm"
         fromLayer="top" toLayer="bottom" pcbX={0} pcbY={-8} />
    <copperpour connectsTo="net.GND" layer="top" clearance="0.3mm" />
  </board>
)

Circuit json: 2 pcb_copper_pour records (brep outer rings spanning y[-9.7,-5.38] and y[-4.62,9.7]). KiCad export: 2 zones, each (net_name GND), each outline being one fragment's computed fill shape.

Expected: one zone per <copperpour> whose outline is the requested pour region, with the fill left for KiCad to compute.

Why it matters: in KiCad the zone outline is design intent and the fill is derived. With outline == previous fill fragment, any refill (edit + B, or a pcbnew script) reapplies clearances inside the already-shrunk outline, so copper shrinks every refill and fragments that split further are deleted as islands. Dozens of independent zones per pour also make the file uneditable, and a script that unions fragments into one zone cannot save the result (a KiCad zone keeps a single outline).

Cause: CopperPour.doInitialPcbCopperPourRender (lib/components/primitive-components/CopperPour/CopperPour.ts:73-87) inserts one record per solver brep_shape, drops the source region, and the records carry no id linking them to the pour element, so downstream cannot even union them per pour.

Suggested fix: store the requested pour region on the pcb_copper_pour (one record per pour element), with the solver's computed fragments in a separate fill field or in records referencing the pour id, so viewers render fills while exporters emit the region.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions