def when_ordinary_sphere_is_constructed(self): self.sphere = Sphere(self.expected_center, self.expected_radius)
class TestSphere(unittest.TestCase): """ Test Sphere class """ def clean_state(self): self.sphere = None self.expected_center = None self.expected_radius = None self.starting_point = None self.test_ray = None self.intersection_points = None def setUp(self): self.clean_state() self.expected_center = Position.from_xyz((10.0, 20.0, 30.0)) self.expected_radius = 5.0 def tearDown(self): self.clean_state() def test_ordinary_sphere_construction(self): self.when_ordinary_sphere_is_constructed() self.then_sphere_has_ordinary_values() def when_ordinary_sphere_is_constructed(self): self.sphere = Sphere(self.expected_center, self.expected_radius) def then_sphere_has_ordinary_values(self): self.assertAlmostEqual(self.expected_radius, self.sphere.radius) self.assertAlmostEqual(self.expected_center.x, self.sphere.x) self.assertAlmostEqual(self.expected_center.y, self.sphere.y) self.assertAlmostEqual(self.expected_center.z, self.sphere.z) def test_elevation_above_sphere_surface(self): self.when_ordinary_sphere_is_constructed() for expected_elevation, test_point in [ (-self.expected_radius, self.expected_center), (0.0, Position.from_xyz((15.0, 20.0, 30.0))), (0.0, Position.from_xyz((5.0, 20.0, 30.0))), (0.0, Position.from_xyz((10.0, 23.0, 34.0))), (sqrt(125.0) - 5.0, Position.from_xyz((0.0, 23.0, 34.0))), ]: self.then_point_has_correct_elevation(expected_elevation, test_point) def then_point_has_correct_elevation(self, expected_elevation, test_point): actual_elevation = self.sphere.elevation(test_point) self.assertAlmostEqual(expected_elevation, actual_elevation) def test_sphere_intersects_rays_through_center(self): self.when_ordinary_sphere_is_constructed() self.then_sphere_intersects_rays_correctly() def then_sphere_intersects_rays_correctly(self): starting_points = [ Position.from_xyz((0.0, 0.0, 0.0)), Position.from_xyz((100.0, 200.0, 300.0)), Position.from_xyz((-50.0, 10.0, 10.0)), ] interior_points = [ self.expected_center, self.expected_center.add(Direction.up.scale(4.0)), self.expected_center.add(Direction.left.scale(4.0)), self.expected_center.add(Direction.backward.scale(4.0)), ] for self.starting_point in starting_points: for self.interior_point in interior_points: self.when_sphere_intersects_ray_through_interior_point() self.then_intersection_points_are_correct() def when_sphere_intersects_ray_through_interior_point(self): self.test_ray = Ray.from_origin_endpoint(self.starting_point, self.interior_point) def then_intersection_points_are_correct(self): self.when_intersection_points_are_calculated() self.then_there_are_two_intersection_points() self.then_all_intersection_points_lie_on_both_sphere_and_ray() def when_intersection_points_are_calculated(self): self.intersection_points = self.sphere.intersection_points(self.test_ray) def then_there_are_two_intersection_points(self): self.assertEqual(2, len(self.intersection_points)) def then_all_intersection_points_lie_on_both_sphere_and_ray(self): self.then_intersection_points_lie_on_ray() self.then_intersection_points_lie_on_sphere() def then_intersection_points_lie_on_ray(self): for intersection_point in self.intersection_points: distance_to_ray = self.test_ray.distance_to_point(intersection_point) self.assertAlmostEqual(0.0, distance_to_ray, 4) def then_intersection_points_lie_on_sphere(self): for intersection_point in self.intersection_points: elevation_above_sphere = self.sphere.elevation(intersection_point) self.assertAlmostEqual(0.0, elevation_above_sphere, 4) def test_sphere_has_no_intersection_points_with_distant_ray(self): self.when_ordinary_sphere_is_constructed() self.when_distant_ray_is_constructed() self.when_intersection_points_are_calculated() self.then_there_are_no_interection_points() def when_distant_ray_is_constructed(self): self.test_ray = Ray(Position.from_xyz((0.0, 20.0, 30.0)), Direction.up) def then_there_are_no_interection_points(self): self.assertEqual(0, len(self.intersection_points))