def test_the_normal_is_a_normalized_vector(): # Given s = Sphere() # When n = s.normal_at(Point(sqrt(3) / 3, sqrt(3) / 3, sqrt(3) / 3)) # Then assert n == n.normalize()
def test_the_normal_on_a_sphere_at_a_point_at_a_nonaxial_axis(): # Given s = Sphere() # When n = s.normal_at(Point(sqrt(3) / 3, sqrt(3) / 3, sqrt(3) / 3)) # Then assert n == Vector(sqrt(3) / 3, sqrt(3) / 3, sqrt(3) / 3)
def test_the_normal_on_a_sphere_at_a_point_on_the_z_axis(): # Given s = Sphere() # When n = s.normal_at(Point(0, 0, 1)) # Then assert n == Vector(0, 0, 1)
def test_computing_the_normal_on_a_translated_sphere(): # Given s = Sphere() s.transform = translation(0, 1, 0) # When n = s.normal_at(Point(0, 1.70711, -0.70711)) # Then assert n == Vector(0, 0.70711, -0.70711)
def test_a_ray_misses_s_sphere(): # Given r = Ray(Point(0, 2, -5), Vector(0, 0, 1)) s = Sphere() # When xs = s.intersect(r) # Then assert len(xs) == 0
def test_commputing_the_normal_on_a_transformed_sphere(): # Given s = Sphere() m = scaling(1, 0.5, 1) * rotation_z(pi / 5) s.transform = m # When n = s.normal_at(Point(0, sqrt(2) / 2, -sqrt(2) / 2)) # Then assert n == Vector(0, 0.97014, -0.24254)
def test_intersecting_a_translated_sphere_with_a_ray(): # Given r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) s = Sphere() # When s.transform = translation(5, 0, 0) xs = s.intersect(r) # Then assert len(xs) == 0
def test_a_pattern_with_an_object_transformation(): # Given shape = Sphere() shape.transform = scaling(2, 2, 2) pattern = MockPattern() # When c = pattern.pattern_at_shape(shape, Point(2, 3, 4)) # Then assert c == Color(1, 1.5, 2)
def test_a_pattern_with_both_an_object_and_a_pattern_transformation(): # Given shape = Sphere() shape.transform = scaling(2, 2, 2) pattern = MockPattern() pattern.transform = translation(0.5, 1, 1.5) # When c = pattern.pattern_at_shape(shape, Point(2.5, 3, 3.5)) # Then assert c == Color(0.75, 0.5, 0.25)
def test_a_ray_originates_inside_a_sphere(): # Given r = Ray(Point(0, 0, 0), Vector(0, 0, 1)) s = Sphere() # When xs = s.intersect(r) # Then assert len(xs) == 2 assert xs[0].t == -1.0 assert xs[1].t == 1.0
def test_a_sphere_is_behind_a_ray(): # Given r = Ray(Point(0, 0, 5), Vector(0, 0, 1)) s = Sphere() # When xs = s.intersect(r) # Then assert len(xs) == 2 assert xs[0].t == -6.0 assert xs[1].t == -4.0
def test_a_ray_intersects_a_sphere_at_a_tangent(): # Then r = Ray(Point(0, 1, -5), Vector(0, 0, 1)) s = Sphere() # When xs = s.intersect(r) # Then assert len(xs) == 2 assert xs[0].t == 5.0 assert xs[1].t == 5.0
def test_a_ray_intersects_a_sphere_at_two_points(): # Given r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) s = Sphere() # When xs = s.intersect(r) # Then assert len(xs) == 2 assert xs[0].t == 4.0 assert xs[1].t == 6.0
def test_intersect_sets_the_object_on_the_intersection(): # Given r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) s = Sphere() # When xs = s.intersect(r) # Then assert len(xs) == 2 assert xs[0].object == s assert xs[1].object == s
def test_intersecting_a_scaled_sphere_with_a_ray(): # Given r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) s = Sphere() # When s.transform = scaling(2, 2, 2) xs = s.intersect(r) # Then assert len(xs) == 2 assert xs[0].t == 3 assert xs[1].t == 7
def test_the_hit_should_offset_the_point(): # Given r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) shape = Sphere() shape.transform = translation(0, 0, 1) i = Intersection(5, shape) # When comps = i.prepare_computations(r) # Then assert comps.over_point.z < -EPSILON / 2 assert comps.point.z > comps.over_point.z
def test_intersecting_a_transformed_group(): # Given g = Group() g.transform = scaling(2, 2, 2) s = Sphere() s.transform = translation(5, 0, 0) g.add_child(s) # When r = Ray(Point(10, 0, -10), Vector(0, 0, 1)) xs = g.intersect(r) # Then assert len(xs) == 2
def default_world(): light = PointLight(Point(-10, 10, -10), Color(1, 1, 1)) s1 = Sphere() s1.material.color = Color(0.8, 1.0, 0.6) s1.material.diffuse = 0.7 s1.material.specular = 0.2 s2 = Sphere() s2.transform = scaling(0.5, 0.5, 0.5) w = World() w.light = light w.objects = [s1, s2] return w
def test_converting_a_normal_from_object_to_world_space(): # Given g1 = Group() g1.transform = rotation_y(pi / 2) g2 = Group() g2.transform = scaling(1, 2, 3) g1.add_child(g2) s = Sphere() s.transform = translation(5, 0, 0) g2.add_child(s) # When n = s.normal_to_world(Vector(sqrt(3) / 3, sqrt(3) / 3, sqrt(3) / 3)) # Then assert n == Vector(0.28571, 0.42857, -0.85714)
def test_finding_the_normal_on_a_child_object(): # Given g1 = Group() g1.transform = rotation_y(pi / 2) g2 = Group() g2.transform = scaling(1, 2, 3) g1.add_child(g2) s = Sphere() s.transform = translation(5, 0, 0) g2.add_child(s) # When n = s.normal_at(Point(1.7321, 1.1547, -5.5774)) # Then assert n == Vector(0.2857, 0.42854, -0.85716)
def test_converting_a_point_from_world_to_object_space(): # Given g1 = Group() g1.transform = rotation_y(pi / 2) g2 = Group() g2.transform = scaling(2, 2, 2) g1.add_child(g2) s = Sphere() s.transform = translation(5, 0, 0) g2.add_child(s) # When p = s.world_to_object(Point(-2, 0, -10)) # Then assert p == Point(0, 0, -1)
def test_default_world(): # Given light = PointLight(Point(-10, 10, -10), Color(1, 1, 1)) s1 = Sphere() s1.material.color = Color(0.8, 1.0, 0.6) s1.material.diffuse = 0.7 s1.material.specular = 0.2 s2 = Sphere() s2.transform = scaling(0.5, 0.5, 0.5) # When w = default_world() # Then assert w.light == light assert s1 in w.objects assert s2 in w.objects
def test__shade_hit__is_given_an_intersection_in_shadow(): # Given w = World() w.light = PointLight(Point(0, 0, -10), Color(1, 1, 1)) s1 = Sphere() w.objects.append(s1) s2 = Sphere() s2.transform = translation(0, 0, 10) w.objects.append(s2) r = Ray(Point(0, 0, 5), Vector(0, 0, 1)) i = Intersection(4, s2) # When comps = i.prepare_computations(r) c = w.shade_hit(comps) # Then assert c == Color(0.1, 0.1, 0.1)
def test_an_intersection_encapsulates_t_and_object(): # Given s = Sphere() # When i = Intersection(3.5, s) # Then assert i.t == 3.5 assert i.object == s
def test_the_hit__when_an_intersection_occurs_on_the_outside(): # Given r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) shape = Sphere() i = Intersection(4, shape) # When comps = i.prepare_computations(r) # Then assert comps.inside is False
def test_the_hit__when_all_intersections_have_positive_t(): # Given s = Sphere() i1 = Intersection(1, s) i2 = Intersection(2, s) xs = Intersections(i2, i1) # When i = xs.hit() # Then assert i == i1
def test_the_hit__when_all_intersections_have_netative_t(): # Given s = Sphere() i1 = Intersection(-2, s) i2 = Intersection(-1, s) xs = Intersections(i2, i1) # When i = xs.hit() # Then assert i is None
def test_the_hit__when_some_intersections_have_negative_t(): # Given s = Sphere() i1 = Intersection(-1, s) i2 = Intersection(1, s) xs = Intersections(i2, i1) # When i = xs.hit() # Then assert i == i2
def test_aggregating_intersections(): # Given s = Sphere() i1 = Intersection(1, s) i2 = Intersection(2, s) # When xs = Intersections(i1, i2) # Then assert len(xs) == 2 assert xs[0].t == 1 assert xs[1].t == 2
def test_the_hit_is_always_the_lowest_nonnegative_intersection(): # Given s = Sphere() i1 = Intersection(5, s) i2 = Intersection(7, s) i3 = Intersection(-3, s) i4 = Intersection(2, s) xs = Intersections(i1, i2, i3, i4) # When i = xs.hit() # Then assert i == i4