[set_dead / skip_geometry] Improve dead pathers so more "broken" layouts can be successfully executed
This commit is contained in:
parent
cf822c7dcf
commit
f42e720c68
7 changed files with 273 additions and 73 deletions
|
|
@ -73,3 +73,57 @@ def test_builder_set_dead() -> None:
|
|||
|
||||
b.place("sub")
|
||||
assert not b.pattern.has_refs()
|
||||
|
||||
|
||||
def test_builder_dead_ports() -> None:
|
||||
lib = Library()
|
||||
pat = Pattern()
|
||||
pat.ports['A'] = Port((0, 0), 0)
|
||||
b = Builder(lib, pattern=pat)
|
||||
b.set_dead()
|
||||
|
||||
# Attempt to plug a device where ports don't line up
|
||||
# A has rotation 0, C has rotation 0. plug() expects opposing rotations (pi difference).
|
||||
other = Pattern(ports={'C': Port((10, 10), 0), 'D': Port((20, 20), 0)})
|
||||
|
||||
# This should NOT raise PortError because b is dead
|
||||
b.plug(other, map_in={'A': 'C'}, map_out={'D': 'B'})
|
||||
|
||||
# Port A should be removed, and Port B (renamed from D) should be added
|
||||
assert 'A' not in b.ports
|
||||
assert 'B' in b.ports
|
||||
|
||||
# Verify geometry was not added
|
||||
assert not b.pattern.has_refs()
|
||||
assert not b.pattern.has_shapes()
|
||||
|
||||
|
||||
def test_dead_plug_best_effort() -> None:
|
||||
lib = Library()
|
||||
pat = Pattern()
|
||||
pat.ports['A'] = Port((0, 0), 0)
|
||||
b = Builder(lib, pattern=pat)
|
||||
b.set_dead()
|
||||
|
||||
# Device with multiple ports, none of which line up correctly
|
||||
other = Pattern(ports={
|
||||
'P1': Port((10, 10), 0), # Wrong rotation (0 instead of pi)
|
||||
'P2': Port((20, 20), pi) # Correct rotation but wrong offset
|
||||
})
|
||||
|
||||
# Try to plug. find_transform will fail.
|
||||
# It should fall back to aligning the first pair ('A' and 'P1').
|
||||
b.plug(other, map_in={'A': 'P1'}, map_out={'P2': 'B'})
|
||||
|
||||
assert 'A' not in b.ports
|
||||
assert 'B' in b.ports
|
||||
|
||||
# Dummy transform aligns A (0,0) with P1 (10,10)
|
||||
# A rotation 0, P1 rotation 0 -> rotation = (0 - 0 - pi) = -pi
|
||||
# P2 (20,20) rotation pi:
|
||||
# 1. Translate P2 so P1 is at origin: (20,20) - (10,10) = (10,10)
|
||||
# 2. Rotate (10,10) by -pi: (-10,-10)
|
||||
# 3. Translate by s_port.offset (0,0): (-10,-10)
|
||||
assert_allclose(b.ports['B'].offset, [-10, -10], atol=1e-10)
|
||||
# P2 rot pi + transform rot -pi = 0
|
||||
assert_allclose(b.ports['B'].rotation, 0, atol=1e-10)
|
||||
|
|
|
|||
|
|
@ -81,3 +81,25 @@ def test_pather_at_chaining(pather_setup: tuple[Pather, PathTool, Library]) -> N
|
|||
# pi/2 (North) + CCW (90 deg) -> 0 (East)?
|
||||
# Actual behavior results in pi (West).
|
||||
assert_allclose(p.ports["start"].rotation, pi, atol=1e-10)
|
||||
|
||||
|
||||
def test_pather_dead_ports() -> None:
|
||||
lib = Library()
|
||||
tool = PathTool(layer=(1, 0), width=1)
|
||||
p = Pather(lib, ports={"in": Port((0, 0), 0)}, tools=tool)
|
||||
p.set_dead()
|
||||
|
||||
# Path with negative length (impossible for PathTool, would normally raise BuildError)
|
||||
p.path("in", None, -10)
|
||||
|
||||
# Port 'in' should be updated by dummy extension despite tool failure
|
||||
# port_rot=0, forward is -x. path(-10) means moving -10 in -x direction -> +10 in x.
|
||||
assert_allclose(p.ports["in"].offset, [10, 0], atol=1e-10)
|
||||
|
||||
# Downstream path should work correctly using the dummy port location
|
||||
p.path("in", None, 20)
|
||||
# 10 + (-20) = -10
|
||||
assert_allclose(p.ports["in"].offset, [-10, 0], atol=1e-10)
|
||||
|
||||
# Verify no geometry
|
||||
assert not p.pattern.has_shapes()
|
||||
|
|
|
|||
|
|
@ -73,3 +73,23 @@ def test_renderpather_retool(rpather_setup: tuple[RenderPather, PathTool, Librar
|
|||
# Different tools should cause different batches/shapes
|
||||
assert len(rp.pattern.shapes[(1, 0)]) == 1
|
||||
assert len(rp.pattern.shapes[(2, 0)]) == 1
|
||||
|
||||
|
||||
def test_renderpather_dead_ports() -> None:
|
||||
lib = Library()
|
||||
tool = PathTool(layer=(1, 0), width=1)
|
||||
rp = RenderPather(lib, ports={"in": Port((0, 0), 0)}, tools=tool)
|
||||
rp.set_dead()
|
||||
|
||||
# Impossible path
|
||||
rp.path("in", None, -10)
|
||||
|
||||
# port_rot=0, forward is -x. path(-10) means moving -10 in -x direction -> +10 in x.
|
||||
assert_allclose(rp.ports["in"].offset, [10, 0], atol=1e-10)
|
||||
|
||||
# Verify no render steps were added
|
||||
assert len(rp.paths["in"]) == 0
|
||||
|
||||
# Verify no geometry
|
||||
rp.render()
|
||||
assert not rp.pattern.has_shapes()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue