from numpy.testing import assert_allclose from numpy import pi from ..abstract import Abstract from ..ports import Port from ..ref import Ref def test_abstract_init() -> None: ports = {"A": Port((0, 0), 0), "B": Port((10, 0), pi)} abs_obj = Abstract("test", ports) assert abs_obj.name == "test" assert len(abs_obj.ports) == 2 assert abs_obj.ports["A"] is not ports["A"] # Should be deepcopied def test_abstract_transform() -> None: abs_obj = Abstract("test", {"A": Port((10, 0), 0)}) # Rotate 90 deg around (0,0) abs_obj.rotate_around((0, 0), pi / 2) # (10, 0) rot 0 -> (0, 10) rot pi/2 assert_allclose(abs_obj.ports["A"].offset, [0, 10], atol=1e-10) assert abs_obj.ports["A"].rotation is not None assert_allclose(abs_obj.ports["A"].rotation, pi / 2, atol=1e-10) # Mirror across x axis (axis 0): flips y-offset abs_obj.mirror(0) # (0, 10) mirrored(0) -> (0, -10) # rotation pi/2 mirrored(0) -> -pi/2 == 3pi/2 assert_allclose(abs_obj.ports["A"].offset, [0, -10], atol=1e-10) assert abs_obj.ports["A"].rotation is not None assert_allclose(abs_obj.ports["A"].rotation, 3 * pi / 2, atol=1e-10) def test_abstract_ref_transform() -> None: abs_obj = Abstract("test", {"A": Port((10, 0), 0)}) ref = Ref(offset=(100, 100), rotation=pi / 2, mirrored=True) # Apply ref transform abs_obj.apply_ref_transform(ref) # Ref order: mirror, rotate, scale, translate # 1. mirror (across x: y -> -y) # (10, 0) rot 0 -> (10, 0) rot 0 # 2. rotate pi/2 around (0,0) # (10, 0) rot 0 -> (0, 10) rot pi/2 # 3. translate (100, 100) # (0, 10) -> (100, 110) assert_allclose(abs_obj.ports["A"].offset, [100, 110], atol=1e-10) assert abs_obj.ports["A"].rotation is not None assert_allclose(abs_obj.ports["A"].rotation, pi / 2, atol=1e-10) def test_abstract_ref_transform_scales_offsets() -> None: abs_obj = Abstract("test", {"A": Port((10, 0), 0)}) ref = Ref(offset=(100, 100), rotation=pi / 2, mirrored=True, scale=2) abs_obj.apply_ref_transform(ref) assert_allclose(abs_obj.ports["A"].offset, [100, 120], atol=1e-10) assert abs_obj.ports["A"].rotation is not None assert_allclose(abs_obj.ports["A"].rotation, pi / 2, atol=1e-10) def test_abstract_undo_transform() -> None: abs_obj = Abstract("test", {"A": Port((100, 110), pi / 2)}) ref = Ref(offset=(100, 100), rotation=pi / 2, mirrored=True) abs_obj.undo_ref_transform(ref) assert_allclose(abs_obj.ports["A"].offset, [10, 0], atol=1e-10) assert abs_obj.ports["A"].rotation is not None assert_allclose(abs_obj.ports["A"].rotation, 0, atol=1e-10) def test_abstract_undo_transform_scales_offsets() -> None: abs_obj = Abstract("test", {"A": Port((100, 120), pi / 2)}) ref = Ref(offset=(100, 100), rotation=pi / 2, mirrored=True, scale=2) abs_obj.undo_ref_transform(ref) assert_allclose(abs_obj.ports["A"].offset, [10, 0], atol=1e-10) assert abs_obj.ports["A"].rotation is not None assert_allclose(abs_obj.ports["A"].rotation, 0, atol=1e-10)