Include the net's traces as conductors alongside zone fills

Straight tracks become capsule outline polygons (rectangle +
semicircular caps), arc tracks annular bands with end caps, both
tessellated to the same sagitta tolerance as zone-fill arcs; they merge
into the per-layer copper next to the fills, so rasterization, via
stitching, the solver and the plots handle them unchanged. Trace-only
layers and trace-only nets now qualify as candidates. Dialog checkbox
(on by default, INCLUDE_TRACKS) toggles them per run.

Hole-less polygons (every track outline) now paint the layer mask
directly instead of allocating a full-frame temporary each.

Tests: exact N-cell chain on a rasterized capsule, analytic annular-
sector convergence for an arc trace, capsule/arc-band outline geometry
invariants, collinear-arc degradation, and fill+trace union solve.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
janik
2026-07-15 15:37:51 +07:00
parent b62e45a9b4
commit 56e2f9c81a
10 changed files with 327 additions and 44 deletions
+10 -5
View File
@@ -167,11 +167,16 @@ def rasterize_stack(problem: Problem, h_nm: float) -> RasterStack:
)
for li, layer in enumerate(problem.layers):
for poly in layer.polygons:
pmask = np.zeros((ny, nx), dtype=bool)
_paint_ring(stack, poly.outline, True, pmask)
for hole in poly.holes:
_paint_ring(stack, hole, False, pmask)
stack.masks[li] |= pmask
if poly.holes:
pmask = np.zeros((ny, nx), dtype=bool)
_paint_ring(stack, poly.outline, True, pmask)
for hole in poly.holes:
_paint_ring(stack, hole, False, pmask)
stack.masks[li] |= pmask
else:
# hole-less (e.g. one of many track outlines): paint the
# layer mask directly, skipping the full-frame temp
_paint_ring(stack, poly.outline, True, stack.masks[li])
if problem.buildups:
stack.buildup = np.zeros_like(stack.masks)