- 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.
73 lines
2.3 KiB
Python
73 lines
2.3 KiB
Python
"""``BasicBoard`` — the board container.
|
|
|
|
Ports the data-model core of ``board/BasicBoard.java``: the layer stack, the
|
|
net list, the clearance matrix, the bounding box, and the list of items with
|
|
insertion and query helpers. The routing operations live in ``RoutingBoard``
|
|
(the router phase); this class is what DSN import produces and what the
|
|
board-model invariants check.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from freeroute.geometry import IntBox
|
|
|
|
from .clearance import ClearanceMatrix
|
|
from .items import Item, ObstacleArea, Pin, Trace, Via
|
|
from .layer import LayerStructure
|
|
from .net import Nets
|
|
|
|
__all__ = ["BasicBoard"]
|
|
|
|
|
|
class BasicBoard:
|
|
"""A board: layers, nets, clearances, a bounding box, and items."""
|
|
|
|
__slots__ = ("layer_structure", "nets", "clearance_matrix", "bounding_box", "outline", "_items")
|
|
|
|
def __init__(
|
|
self,
|
|
layer_structure: LayerStructure,
|
|
nets: Nets,
|
|
clearance_matrix: ClearanceMatrix,
|
|
bounding_box: IntBox,
|
|
) -> None:
|
|
self.layer_structure = layer_structure
|
|
self.nets = nets
|
|
self.clearance_matrix = clearance_matrix
|
|
self.bounding_box = bounding_box
|
|
#: the real board outline, when the DSN has a polygon boundary
|
|
self.outline = None
|
|
self._items: list[Item] = []
|
|
|
|
# --- layers -------------------------------------------------------------
|
|
|
|
def get_layer_count(self) -> int:
|
|
return len(self.layer_structure)
|
|
|
|
# --- items --------------------------------------------------------------
|
|
|
|
def insert(self, item: Item) -> Item:
|
|
self._items.append(item)
|
|
return item
|
|
|
|
def get_items(self) -> list[Item]:
|
|
return list(self._items)
|
|
|
|
def get_pins(self) -> list[Pin]:
|
|
return [it for it in self._items if isinstance(it, Pin)]
|
|
|
|
def get_obstacle_areas(self) -> list[ObstacleArea]:
|
|
return [it for it in self._items if isinstance(it, ObstacleArea)]
|
|
|
|
def get_traces(self) -> list[Trace]:
|
|
return [it for it in self._items if isinstance(it, Trace)]
|
|
|
|
def get_vias(self) -> list[Via]:
|
|
return [it for it in self._items if isinstance(it, Via)]
|
|
|
|
def get_connectable_items(self, net_no: int) -> list[Item]:
|
|
return [it for it in self._items if it.contains_net(net_no)]
|
|
|
|
def item_count(self) -> int:
|
|
return len(self._items)
|