Honour KiCad's keepouts: keyhole rings, wire_keepout, per-tile rasterizing

On the TerraHawk rc4 power stage every engine misread the board's rule areas:

- A no-track ring along the board edge arrives as one keyhole polygon, and
  keepout polygons were wrapped in a single convex tile, so the ring became
  the whole board. Split keepout polygons into convex pieces instead.
- The grid engine rasterized an area by its overall bounding box, which for
  that ring is again the whole board; it routed nothing. Rasterize per tile.
- "Keep router off" rule areas arrive as wire_keepout, which the reader did
  not know, so tracks ran through them (172 DRC items_not_allowed). Read it
  at board and image level. For now it blocks vias too, which is stricter
  than KiCad and cannot create a violation.
- place_keepout only restricts part placement; stop treating it as copper.

The oracle now runs the JAR headless; it was opening FreeRouting's GUI on
the desktop for every oracle test.
This commit is contained in:
2026-09-27 06:30:43 -06:00
parent b26fdd96d5
commit 3ad5c983f5
6 changed files with 115 additions and 10 deletions
+8 -5
View File
@@ -199,11 +199,14 @@ class GridRouter:
elif isinstance(item, ObstacleArea):
if item.layer not in self.layers:
continue
box = item.bounding_box()
if box.is_empty():
continue
for cell in self._cells_in_box(box, self.clearance):
self._keepout.add((*cell, item.layer))
# Tile by tile: the area's own bounding box of a ring (a
# no-track border along the board edge) is the whole board.
for tile in item.tiles:
box = tile.bounding_box()
if box.is_empty():
continue
for cell in self._cells_in_box(box, self.clearance):
self._keepout.add((*cell, item.layer))
# --- occupancy cost -----------------------------------------------------