def test_vec_identities(py_c_vec) -> None: """Check that vectors in the same axis as the rotation don't get spun.""" Vec, Angle, Matrix, parse_vec_str = py_c_vec for ang in range(0, 360, 13): # Check the two constructors match. assert_rot(Matrix.from_pitch(ang), Matrix.from_angle(Angle(pitch=ang))) assert_rot(Matrix.from_yaw(ang), Matrix.from_angle(Angle(yaw=ang))) assert_rot(Matrix.from_roll(ang), Matrix.from_angle(Angle(roll=ang))) # Various magnitudes to test for mag in (-250, -1, 0, 1, 250): assert_vec(Vec(y=mag) @ Matrix.from_pitch(ang), 0, mag, 0) assert_vec(Vec(z=mag) @ Matrix.from_yaw(ang), 0, 0, mag) assert_vec(Vec(x=mag) @ Matrix.from_roll(ang), mag, 0, 0)
def test_matrix_roundtrip_roll(py_c_vec): """Check converting to and from a Matrix does not change values.""" Vec, Angle, Matrix, parse_vec_str = py_c_vec for roll in range(0, 360, 45): if roll in (90, -90): # Don't test gimbal lock. continue mat = Matrix.from_roll(roll) assert_ang(mat.to_angle(), 0, 0, roll)
def test_vec_basic_roll(py_c_vec): """Check each direction rotates appropriately in roll.""" Vec, Angle, Matrix, parse_vec_str = py_c_vec assert_vec(Vec(0, 200, 0) @ Matrix.from_roll(0), 0, 200, 0) assert_vec(Vec(0, 0, 150) @ Matrix.from_roll(0), 0, 0, 150) assert_vec(Vec(0, 200, 0) @ Matrix.from_roll(90), 0, 0, 200) assert_vec(Vec(0, 0, 150) @ Matrix.from_roll(90), 0, -150, 0) assert_vec(Vec(0, 200, 0) @ Matrix.from_roll(180), 0, -200, 0) assert_vec(Vec(0, 0, 150) @ Matrix.from_roll(180), 0, 0, -150) assert_vec(Vec(0, 200, 0) @ Matrix.from_roll(270), 0, 0, -200) assert_vec(Vec(0, 0, 150) @ Matrix.from_roll(270), 0, 150, 0)
def res_alt_orientation(res: Property) -> Callable[[Entity], None]: """Apply an alternate orientation. "wall" makes the attaching surface in the -X direction, making obs rooms, corridors etc easier to build. The Z axis points in the former +X direction. "ceiling" flips the instance, making items such as droppers easier to build. The X axis remains unchanged. """ val = res.value.casefold() if val == 'wall': pose = Matrix.from_angle(-90, 180, 0) elif val in ('ceil', 'ceiling'): pose = Matrix.from_roll(180) else: raise ValueError(f'Unknown orientation type "{res.value}"!') def swap_orient(inst: Entity) -> None: """Apply the new orientation.""" inst['angles'] = pose @ Angle.from_str(inst['angles']) return swap_orient