Tests for pads placed as KiCad places them, and the via size
This commit is contained in:
@@ -196,3 +196,61 @@ def test_grid_router_leaves_the_interior_of_a_ring_keepout_open():
|
|||||||
)
|
)
|
||||||
result, _, _ = route_dsn_board(parse_dsn(ring_only), max_passes=2)
|
result, _, _ = route_dsn_board(parse_dsn(ring_only), max_passes=2)
|
||||||
assert result.routed_net_numbers
|
assert result.routed_net_numbers
|
||||||
|
|
||||||
|
|
||||||
|
# --- pads placed as KiCad places them (2026-09-27, TerraHawk rc4) ------------
|
||||||
|
|
||||||
|
_PAD_DSN = """(pcb pads (parser) (resolution um 10) (unit um)
|
||||||
|
(structure
|
||||||
|
(layer F.Cu (type signal)) (layer B.Cu (type signal))
|
||||||
|
(boundary (path pcb 0 0 0 40000 0 40000 -30000 0 -30000 0 0))
|
||||||
|
(via "Via[0-1]_600:300_um")
|
||||||
|
(rule (width 250) (clearance 150)))
|
||||||
|
(placement
|
||||||
|
(component R (place TOP 10000 -10000 front 0) (place BOT 20000 -10000 back 0)
|
||||||
|
(place ROT 30000 -10000 front 90)))
|
||||||
|
(library
|
||||||
|
(image R (pin rect 1 -1000 0))
|
||||||
|
(padstack rect (shape (rect F.Cu -400 -250 400 250)) (attach off))
|
||||||
|
(padstack "Via[0-1]_600:300_um" (shape (circle F.Cu 600)) (shape (circle B.Cu 600)) (attach off)))
|
||||||
|
(network))"""
|
||||||
|
|
||||||
|
|
||||||
|
def _pins_by_ref(text):
|
||||||
|
board = build_board(parse_dsn(text))
|
||||||
|
return {p.component_ref: p for p in board.get_pins()}, board
|
||||||
|
|
||||||
|
|
||||||
|
def test_back_side_pad_moves_to_the_bottom_layer():
|
||||||
|
pins, board = _pins_by_ref(_PAD_DSN)
|
||||||
|
names = [layer.name for layer in board.layer_structure.arr]
|
||||||
|
assert [names[i] for i in pins["TOP"].layers] == ["F.Cu"]
|
||||||
|
assert [names[i] for i in pins["BOT"].layers] == ["B.Cu"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_back_side_pin_offset_is_mirrored():
|
||||||
|
pins, _ = _pins_by_ref(_PAD_DSN)
|
||||||
|
assert pins["TOP"].location.x == (10000 - 1000) * 10
|
||||||
|
assert pins["BOT"].location.x == (20000 + 1000) * 10
|
||||||
|
|
||||||
|
|
||||||
|
def test_rotated_part_rotates_its_pad_outline():
|
||||||
|
pins, _ = _pins_by_ref(_PAD_DSN)
|
||||||
|
flat = pins["TOP"].shape.bounding_box()
|
||||||
|
turned = pins["ROT"].shape.bounding_box()
|
||||||
|
assert (flat.ur.x - flat.ll.x, flat.ur.y - flat.ll.y) == (8000, 5000)
|
||||||
|
assert (turned.ur.x - turned.ll.x, turned.ur.y - turned.ll.y) == (5000, 8000)
|
||||||
|
|
||||||
|
|
||||||
|
def test_oval_pad_keeps_its_width():
|
||||||
|
oval = _PAD_DSN.replace("(shape (rect F.Cu -400 -250 400 250))", "(shape (path F.Cu 500 -300 0 300 0))")
|
||||||
|
pins, _ = _pins_by_ref(oval)
|
||||||
|
box = pins["TOP"].shape.bounding_box()
|
||||||
|
assert box.ur.y - box.ll.y == 5000 # the aperture, not a zero-height line
|
||||||
|
assert box.ur.x - box.ll.x == 11000 # centreline 600 um plus the aperture
|
||||||
|
|
||||||
|
|
||||||
|
def test_via_size_comes_from_the_via_padstack():
|
||||||
|
from freeroute.route.pipeline import _via_half_board
|
||||||
|
|
||||||
|
assert _via_half_board(parse_dsn(_PAD_DSN), 10) == 3000 # 0.6 mm via, board units
|
||||||
|
|||||||
Reference in New Issue
Block a user