def test_mul(self): m1 = rng(4, 4).astype(FLOAT) m2 = rng(4, 4).astype(FLOAT) m1_inv = np.linalg.inv(m1).astype(FLOAT) m2_inv = np.linalg.inv(m2).astype(FLOAT) t1 = Transform(m1, m1_inv) t2 = Transform(m2, m2_inv) t = t1 * t2 assert (t.m == m1.dot(m2)).all() assert (t.m_inv == m2_inv.dot(m1_inv)).all()
def test_call_bbox(self, p1, p2): box = geo.BBox(p1, p2) t = Transform() b = t(box) assert isinstance(b, geo.BBox) assert_elem_eq(b.pMax, box.pMax) assert_elem_eq(b.pMin, box.pMin)
def test_look_at(self, pnt, vec, x_axis, y_axis, z_axis, origin): t = Transform.look_at(pnt, vec, y_axis) assert_elem_eq(t(origin), pnt) assert_elem_eq(t.inverse()(pnt), origin) if not pnt == vec and not pnt == y_axis and not vec == y_axis: assert not t.has_scale()
def test_call_ray_differential(self, pnt, vec): ray = geo.RayDifferential(pnt, vec) t = Transform() r = t(ray) assert isinstance(r, geo.RayDifferential) assert r.o == ray.o assert r.d == ray.d
def test_call_ray(self, pnt, vec): ray = geo.Ray(pnt, vec) t = Transform() r = t(ray) assert isinstance(r, geo.Ray) assert r.o == ray.o assert r.d == ray.d
def test_orthographic(self): znear = rng() zfar = znear + rng() * VAR t = Transform.orthographic(znear, zfar) p = geo.Point(rng(), rng(), znear) assert_almost_eq(t(p).z, 0.) p = geo.Point(rng(), rng(), zfar) assert_almost_eq(t(p).z, 1.)
def test_translate_norm(self, norm, trans_vec): t = Transform.translate(trans_vec) n = t(norm) assert n == norm nn = t.inverse()(n) assert_elem_eq(nn, norm)
def test_translate_pnt(self, pnt, trans_vec): t = Transform.translate(trans_vec) p = t(pnt) assert p == pnt + trans_vec pp = t.inverse()(p) assert_elem_eq(pp, pnt)
def test_scale_pnt(self, pnt, scale_coef): t = Transform.scale(scale_coef[0], scale_coef[1], scale_coef[2]) p = t(pnt) assert_elem_eq(p, pnt * scale_coef) pp = t.inverse()(p) assert_elem_eq(pp, pnt)
def test_scale_norm(self, norm, scale_coef): t = Transform.scale(scale_coef[0], scale_coef[1], scale_coef[2]) n = t(norm) assert_elem_eq(n, norm / scale_coef) nn = t.inverse()(n) assert_elem_eq(nn, norm)
def test_translate_vec(self, vec, trans_vec): t = Transform.translate(trans_vec) v = t(vec) assert v == vec vv = t.inverse()(v) assert vv == vec
def test_scale_vec(self, vec, scale_coef): t = Transform.scale(scale_coef[0], scale_coef[1], scale_coef[2]) v = t(vec) assert_elem_eq(v, vec * scale_coef) vv = t.inverse()(v) assert_elem_eq(vv, vec)
def test_rotate_x(self, x_axis, y_axis, z_axis): t = Transform.rotate_x(45) assert_elem_eq(t(x_axis), x_axis) v = t(y_axis) assert_elem_eq(v, geo.Vector(0., np.sqrt(2) / 2., np.sqrt(2) / 2.)) vv = t(v) assert_elem_eq(vv, z_axis) vv = t.inverse()(v) assert_elem_eq(vv, y_axis)
def test_translate_bbox(self, p1, p2, trans_vec): t = Transform.translate(trans_vec) b = geo.BBox(p1, p2) bb = t(b) assert_elem_eq(bb.pMin, b.pMin + trans_vec) assert_elem_eq(bb.pMax, b.pMax + trans_vec) bbb = t.inverse()(bb) assert_elem_eq(bbb.pMin, b.pMin) assert_elem_eq(bbb.pMax, b.pMax)
def test_perspective(self): znear = rng() * VAR zfar = znear + rng() * VAR fov = rng() * 45. + 45. t = Transform.perspective(fov, znear, zfar) p = geo.Point(znear * rng(), znear * rng(), znear + rng() * (zfar - znear)) pp = t(p) assert_almost_eq(pp.z, (p.z - znear) * zfar / ((zfar - znear) * p.z)) assert_almost_eq(pp.x, p.x / (p.z * np.tan(np.deg2rad(.5 * fov)))) assert_almost_eq(pp.y, p.y / (p.z * np.tan(np.deg2rad(.5 * fov))))
def test_rotate(self, x_axis, y_axis, z_axis): t = Transform.rotate(45., x_axis) assert_elem_eq(t(x_axis), x_axis) v = t(y_axis) assert_elem_eq(v, geo.Vector(0., np.sqrt(2) / 2., np.sqrt(2) / 2.)) vv = t(v) assert_elem_eq(vv, z_axis) vv = t.inverse()(v) assert_elem_eq(vv, y_axis) t = Transform.rotate(30., y_axis) assert_elem_eq(t(y_axis), y_axis) p = geo.Point.from_arr(z_axis) pp = t(t(t(p))) assert_elem_eq(pp, x_axis) t = Transform.rotate(90., z_axis) assert_elem_eq(t(z_axis), z_axis) n = geo.Normal.from_arr(y_axis) nn = t(t(t(n))) assert_elem_eq(nn, x_axis)
def test_scale_bbox(self, p1, p2, scale_coef): t = Transform.scale(scale_coef[0], scale_coef[1], scale_coef[2]) b = geo.BBox(p1, p2) bb = t(b) assert_elem_eq(bb.pMin, b.pMin * scale_coef) assert_elem_eq(bb.pMax, b.pMax * scale_coef) bbb = t.inverse()(bb) assert_elem_eq(bbb.pMin, b.pMin) assert_elem_eq(bbb.pMax, b.pMax)
def to_transform(q: 'Quaternion') -> 'Transform': x, y, z, w = q.w, q.x, q.y, q.z m = np.array([[ 1. - 2. * (y * y + z * z), 2. * (x * y + z * w), 2. * (x * z - y * w), 0. ], [ 2. * (x * y - z * w), 1. - 2. * (x * x + z * z), 2. * (y * z + x * w), 0. ], [ 2. * (x * z + y * w), 2. * (y * z - x * w), 1. - 2. * (x * x + y * y), 0. ], [0., 0., 0., 1.]], dtype=FLOAT) from pytracer.transform import Transform return Transform(m.T, m) # transpose for left-handedness
def test_rotate_bbox(self): t = Transform.rotate(180., geo.Vector(1., 1., 1.)) p1 = geo.Point(0., 0., 0.) p2 = geo.Point(1., 1., 1.) box = geo.BBox(p1, p2) b = t(box) pmax = t(box.pMax) pmin = t(box.pMin) assert_elem_eq(b.pMin, pmin) assert_elem_eq(b.pMax, pmax) bb = t(b) pmax = t(pmax) pmin = t(pmin) assert_elem_eq(bb.pMin, pmin) assert_elem_eq(bb.pMax, pmax)
def test_init(self): m = np.random.rand(4, 4).astype(FLOAT) m_inv = np.linalg.inv(m).astype(FLOAT) t = Transform(m, m_inv) assert (m == t.m).all() assert not id(m) == id(t.m) assert (m_inv == t.m_inv).all() assert not id(m_inv) == id(t.m_inv) with pytest.raises(AttributeError): t.m = m with pytest.raises(AttributeError): t.m_inv = m t = Transform() assert not id(t.m) == id(t.m_inv) assert (t.m == t.m_inv).all() assert (t.m == np.eye(4)).all() t = Transform(m) assert_array_almost_equal(t.m_inv, m_inv) with pytest.raises(TypeError): t = Transform(np.random.rand(3, 3).astype(FLOAT)) t = Transform() tt = t.copy() assert (tt == t) assert not id(tt) == id(t)
def test_identity(self): assert Transform().is_identity() assert not Transform(rng(4, 4).astype(FLOAT)).is_identity()
def test_has_scale(self): assert not Transform().has_scale() assert Transform(rng(4, 4).astype(FLOAT)).has_scale()
def test_swap_handedness(self): assert not Transform().swaps_handedness()
def test_rotate_z(self, x_axis, y_axis, z_axis): t = Transform.rotate_z(90) assert_elem_eq(t(z_axis), z_axis) n = geo.Normal.from_arr(y_axis) nn = t(t(t(n))) assert_elem_eq(nn, x_axis)
def test_call_vector(self, vec): t = Transform() v = t(vec) assert isinstance(v, geo.Vector) assert v == vec assert not id(v) == id(vec)
def test_rotate_y(self, x_axis, y_axis, z_axis): t = Transform.rotate_y(30) assert_elem_eq(t(y_axis), y_axis) p = geo.Point.from_arr(z_axis) pp = t(t(t(p))) assert_elem_eq(pp, x_axis)
def test_call_point(self, pnt): t = Transform() p = t(pnt) assert isinstance(p, geo.Point) assert p == pnt assert not id(p) == id(pnt)
def test_call_normal(self, norm): t = Transform() n = t(norm) assert isinstance(n, geo.Normal) assert n == norm assert not id(n) == id(norm)
def test_call_logic(self): t = Transform() with pytest.raises(TypeError): t(1.)
def test_inverse(self): t = Transform(rng(4, 4).astype(FLOAT)) ti = t.inverse() assert_array_almost_equal(t.m, ti.m_inv) assert_array_almost_equal(t.m_inv, ti.m)