def when_wavefront_created(self): self.wavefront = WaveFront(self.triangles)
class TestWaveFront(unittest.TestCase): """ Test WaveFront Class """ def setUp(self): self.wavefront = None self.triangles = [ SphericalTriangle((Ray.right, Ray.forward, Ray.up)), SphericalTriangle((Ray.right, Ray.down, Ray.forward)), SphericalTriangle((Ray.left, Ray.forward, Ray.down)), ] self.unit_sphere_volume_sequence = [ 4.0 / 3.0, 2.942809041582063, 3.817729619828364, 4.091600620085994, 4.164203596248617, ] self.volume_of_unit_sphere = 4.0 / 3.0 * pi # 4.1887902047863905 self.accepted_diameter = 0.2 self.orifice_diameter = 0.2 def tearDown(self): self.wavefront = None self.triangles = None; self.unit_sphere_volume_sequence = None self.volume_of_unit_sphere = None self.accepted_diameter = None self.orifice_diameter = None def test_wave_front_normal_construction(self): self.when_wavefront_created() self.then_wavefront_has_normal_values() def when_wavefront_created(self): self.wavefront = WaveFront(self.triangles) def then_wavefront_has_normal_values(self): self.assertEqual(self.wavefront.triangles, tuple(self.triangles)) def test_wavefront_constructor_requires_triangle_collection(self): with self.assertRaises(TypeError): WaveFront(self.triangles + ["wrong stuff"]) def test_wavefront_unit_sphere_has_expected_values(self): self.when_wavefront_set_to_unit_sphere() self.then_wavefront_has_unit_sphere_content() def when_wavefront_set_to_unit_sphere(self): self.wavefront = WaveFront.unit_sphere def then_wavefront_has_unit_sphere_content(self): self.assertEqual(8, self.wavefront.count) expected_volume = self.unit_sphere_volume_sequence[0] self.assertAlmostEqual(expected_volume, self.wavefront.volume) def test_wavefront_subdivision(self): self.when_wavefront_set_to_unit_sphere() self.then_sequence_of_subdivided_wavefronts_meet_expectations() def then_sequence_of_subdivided_wavefronts_meet_expectations(self): expected_volume_sequence = self.unit_sphere_volume_sequence[1:] for depth, expected_volume in enumerate(expected_volume_sequence): self.when_wavefront_is_subdivided() self.then_wavefront_has_correct_count_for_depth(depth) self.then_wavefront_converges_on_perfect_volume_from_below() self.then_wavefront_has_expected_volume(expected_volume) def when_wavefront_is_subdivided(self): self.wavefront = self.wavefront.subdivide() def then_wavefront_has_correct_count_for_depth(self, depth): expected_count = 32 * 4 ** depth self.assertEqual(expected_count, self.wavefront.count) def then_wavefront_converges_on_perfect_volume_from_below(self): perfect_volume = self.volume_of_unit_sphere self.assertLess(self.wavefront.volume, perfect_volume) def then_wavefront_has_expected_volume(self, expected_volume): self.assertAlmostEqual(expected_volume, self.wavefront.volume) def test_wavefront_refine_with_diameter_filter(self): self.when_wavefront_set_to_unit_sphere() self.when_wavefront_is_refined_by_diameter() self.then_wavefront_has_expected_count_and_volume() self.then_each_triangle_in_wavefront_has_refined_diameter() def when_wavefront_is_refined_by_diameter(self): def testfilter(triangle): if triangle.diameter < self.accepted_diameter: return TriangleClassification.Accept else: return TriangleClassification.Refine self.wavefront = self.wavefront.refine_with_filter(testfilter) def then_wavefront_has_expected_count_and_volume(self): self.assertEqual(2048, self.wavefront.count) self.assertAlmostEqual(self.unit_sphere_volume_sequence[4], self.wavefront.volume) def then_each_triangle_in_wavefront_has_refined_diameter(self): for triangle in self.wavefront: self.assertLess(triangle.diameter, self.accepted_diameter) def test_wavefront_refine_with_orifice_filter(self): self.when_wavefront_set_to_unit_sphere() self.when_wavefront_is_refined_by_orifice() expected_volume = self.orifice_diameter ** 2 self.assertAlmostEqual(expected_volume, self.wavefront.volume, 3) self.then_wavefront_points_up() def when_wavefront_is_refined_by_orifice(self): def testfilter(triangle): orifice_center = Ray.up.endpoint.coordinates orifice_diameter = self.orifice_diameter vertex_a = triangle.a.endpoint.coordinates vertex_b = triangle.b.endpoint.coordinates vertex_c = triangle.c.endpoint.coordinates a_length = vector_distance(vertex_a, orifice_center) b_length = vector_distance(vertex_b, orifice_center) c_length = vector_distance(vertex_c, orifice_center) farthest_distance = max(a_length, b_length, c_length) closest_distance = min(a_length, b_length, c_length) if farthest_distance <= orifice_diameter: return TriangleClassification.Accept elif triangle.diameter < 0.01 or closest_distance >= orifice_diameter: return TriangleClassification.Reject else: return TriangleClassification.Refine self.wavefront = self.wavefront.refine_with_filter(testfilter) def then_wavefront_points_up(self): actual_direction = self.wavefront.central_direction.normalized() expected_direction = Direction.up disparity = vector_distance(actual_direction.xyz, expected_direction.xyz) self.assertLess(disparity, 0.00000001)