Keepout exits and rule areas
A route may not leave a cell inside a wire keepout as a wire, nor reach a pin there by one: it changes layer instead, and the via goes in the pad. A pin whose every stub enters a keepout is reached by a via only. A structure keepout named rule_area... (mckicad names KiCad rule areas so) is checked for overlap only, as KiCad's DRC does, with the free ends of each wire tested for their round caps.
This commit is contained in:
@@ -42,6 +42,7 @@ from freeroute.geometry import (
|
||||
segment_octagon,
|
||||
shove_segment,
|
||||
)
|
||||
from freeroute.geometry.polyline import corner_box
|
||||
|
||||
from .grid_router import RouteResult, route_board
|
||||
|
||||
@@ -157,7 +158,10 @@ def route_board_exact(
|
||||
box = tile.bounding_box()
|
||||
if not box.is_empty():
|
||||
tree.insert(
|
||||
TreeShape(next(owner), -1, frozenset({obstacle.layer}), box, blocks=blocks)
|
||||
TreeShape(
|
||||
next(owner), -1, frozenset({obstacle.layer}), box,
|
||||
blocks=blocks, clearance=obstacle.clearance,
|
||||
)
|
||||
)
|
||||
|
||||
via_layers = frozenset(signal_layers)
|
||||
@@ -178,7 +182,9 @@ def route_board_exact(
|
||||
)
|
||||
for i, (box, box_layers) in enumerate(boxes)
|
||||
for layer in box_layers
|
||||
) or (outline is not None and not all(outline.box_clear(b, edge) for b, _ in boxes)):
|
||||
) or _end_in_rule_area(tree, wires, half_width) or (
|
||||
outline is not None and not all(outline.box_clear(b, edge) for b, _ in boxes)
|
||||
):
|
||||
rejected.append((net_no, *ends))
|
||||
continue # exact-clearance conflict -> drop (may be recovered by shove)
|
||||
acc = accepted.get(net_no)
|
||||
@@ -592,6 +598,17 @@ def _net_boxes(result, net_no, half_width, via_layers, via_half=None):
|
||||
)
|
||||
|
||||
|
||||
def _end_in_rule_area(tree, wires, half_width) -> bool:
|
||||
"""A wire's tiles stop at its end points, but a track ends in a round cap
|
||||
half its width beyond them. Against other copper the pad or via there
|
||||
covers it; a rule area has no clearance to absorb it, so check it."""
|
||||
for layer, points in wires:
|
||||
for end in (points[0], points[-1]):
|
||||
if tree.rule_area_overlap(corner_box(end, half_width), layer):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _copper_boxes(wires, vias, half_width, via_layers, via_half=None):
|
||||
via_half = via_half or half_width
|
||||
boxes: list[tuple[IntBox, frozenset[int]]] = []
|
||||
|
||||
Reference in New Issue
Block a user