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:
+21
-8
@@ -26,6 +26,7 @@ import sys
|
||||
from freeroute.board import build_board
|
||||
from freeroute.board.search_tree import ShapeSearchTree
|
||||
from freeroute.dsn import parse_dsn
|
||||
from freeroute.geometry.octagon import overlaps_2d
|
||||
from freeroute.route import grid_router
|
||||
from freeroute.route.exact_router import route_board_exact
|
||||
from freeroute.route.grid_router import GridRouter, _ends_of
|
||||
@@ -80,13 +81,24 @@ def _capture_conflicts() -> list:
|
||||
def conflict(self, box, net_no, layer, clearance, kind="wire"):
|
||||
hit = original(self, box, net_no, layer, clearance, kind)
|
||||
if hit:
|
||||
# the shape that tripped the check, found the way the check does
|
||||
other = None
|
||||
expanded = box.offset(clearance)
|
||||
other = next(
|
||||
(s for s in self.overlapping(expanded)
|
||||
if s.net_no != net_no and s.on_layer(layer)
|
||||
and (s.blocks == "all" or s.blocks == kind + "s")),
|
||||
None,
|
||||
)
|
||||
for s in self.overlapping(expanded):
|
||||
if s.net_no == net_no or not s.on_layer(layer):
|
||||
continue
|
||||
if s.blocks != "all" and s.blocks != kind + "s":
|
||||
continue
|
||||
if not s.clearance:
|
||||
if s.tile.overlaps(box):
|
||||
other = s
|
||||
break
|
||||
continue
|
||||
if (s.exact is not None and overlaps_2d(s.exact, expanded)) or (
|
||||
s.exact is None and s.tile.overlaps(expanded)
|
||||
):
|
||||
other = s
|
||||
break
|
||||
log.append((net_no, kind, layer, box, clearance, other))
|
||||
return hit
|
||||
|
||||
@@ -177,10 +189,11 @@ def diagnose(
|
||||
if other is None:
|
||||
what = "?"
|
||||
elif other.net_no == -1:
|
||||
what = "keepout"
|
||||
what = "keepout" if other.clearance else "rule area"
|
||||
else:
|
||||
what = ("trace/via of " if other.routed else "pad of ") + names.get(other.net_no, "?")
|
||||
short = (clearance - _gap(box, other.tile)) / scale / 1000 if other is not None else 0
|
||||
need = clearance if other is None or other.clearance else 0
|
||||
short = (need - _gap(box, other.tile)) / scale / 1000 if other is not None else 0
|
||||
per_net.setdefault(net_no, []).append(
|
||||
{"copper": kind, "layer": layer, "against": what, "short_mm": round(short, 4)}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user