Пример #1
0
 def when_ordinary_sphere_is_constructed(self):
     self.sphere = Sphere(self.expected_center, self.expected_radius)
Пример #2
0
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))