Route to the real board outline, per connection, and out of fine-pitch pins
- The exact engine verified copper per net and dropped a whole net on any conflict: a 25-pin +3V3 net lost every connection to one bad segment. Verify and accept per ratsnest connection instead. - Pad and keepout cells were rounded outward, blocking cells up to half a step clear of the copper; 62 of the 64 pins of a 0.5 mm pitch LQFP could not start a route. Block only cells whose centre is inside the clearance zone, and let a net walk along inside its own pad, which adds no copper. - Routing was bounded by the outline's bounding box, so tracks cut across rounded corners. Keep the DSN boundary as a polygon; the grid blocks cells too close to it (scanline plus per-edge, precomputed for vias) and the exact and room engines reject copper that is. - --edge-clearance MM sets copper-to-edge clearance, e.g. KiCad's min_copper_edge_clearance, which the DSN does not carry. Default 0. On the TerraHawk rc4 power stage the exact engine now matches the FreeRouting JAR: same open count, no DRC errors, with a 0.5 mm edge rule.
This commit is contained in:
@@ -50,6 +50,7 @@ def build_board(dsn: DsnBoard) -> BasicBoard:
|
||||
bounding_box = _build_bounding_box(dsn, transform)
|
||||
|
||||
board = BasicBoard(layer_structure, nets, clearance, bounding_box)
|
||||
board.outline = _build_outline(dsn, transform)
|
||||
|
||||
_insert_pins(dsn, board, transform, terminal_to_net)
|
||||
_insert_keepouts(dsn, board, transform)
|
||||
@@ -99,6 +100,18 @@ def _build_bounding_box(dsn: DsnBoard, transform: CoordinateTransform) -> IntBox
|
||||
return IntBox(llx, lly, urx, ury)
|
||||
|
||||
|
||||
def _build_outline(dsn: DsnBoard, transform: CoordinateTransform):
|
||||
"""The DSN boundary as a polygon, or None when it is not a polygon."""
|
||||
from .outline import BoardOutline
|
||||
|
||||
shape = dsn.boundary
|
||||
if not isinstance(shape, (Polygon, Path)):
|
||||
return None
|
||||
c = shape.coords
|
||||
pts = [transform.dsn_to_board_point(c[i], c[i + 1]) for i in range(0, len(c) - 1, 2)]
|
||||
return BoardOutline(pts) if len(pts) >= 3 else None
|
||||
|
||||
|
||||
def _shape_coords(shape: Shape) -> list[float]:
|
||||
if isinstance(shape, Rectangle):
|
||||
return list(shape.coords)
|
||||
|
||||
Reference in New Issue
Block a user