開発環境
- macOS Mojave - Apple (OS)
- Emacs (Text Editor)
- Windows 10 Pro (OS)
- Visual Studio Code (Text Editor)
- Python 3.7 (プログラミング言語)
- GIMP (ビットマップ画像編集・加工ソフトウェア、PPM形式(portable pixmap)の画像用)
The Ray Tracer Challenge: A Test-Driven Guide to Your First 3D Renderer (Jamis Buck(著)、Pragmatic Bookshelf)、Chapter 14(Groups)のImplementing Groupsを取り組んでみる。
コード
groups_test.py
#!/usr/bin/env python3 from unittest import TestCase, main from shapes import Shape from spheres import Sphere from groups import Group from matrices import IDENTITY_MATRIX from rays import Ray from tuples import Point, Vector from transformations import translation, scaling class GroupTest(TestCase): def setUp(self): pass def tearDown(self): pass def test_group(self): group = Group() self.assertEqual(group.transform, IDENTITY_MATRIX) self.assertEqual(len(group), 0) def test_adding_child_to(self): group = Group() shape = Shape() group.add_child(shape) self.assertIn(shape, group) self.assertEqual(shape.parent, group) def test_intersecting_ray_with_empty_group(self): group = Group() ray = Ray(Point(0, 0, 0), Vector(0, 0, 1)) intersections = group.intersect(ray) self.assertEqual(len(intersections), 0) def test_intersecting_ray_nonempty_group(self): group = Group() s1 = Sphere() s2 = Sphere(transform=translation(0, 0, -3)) s3 = Sphere(transform=translation(5, 0, 0)) for s in [s1, s2, s3]: group.add_child(s) ray = Ray(Point(0, 0, -5), Vector(0, 0, 1)) intersections = group.intersect(ray) self.assertEqual(len(intersections), 4) for intersection, shape in zip(intersections, [s2, s2, s1, s1]): self.assertEqual(intersection.obj, shape) def test_intersecting_transformed(self): group = Group(transform=scaling(2, 2, 2)) sphere = Sphere(transform=translation(5, 0, 0)) group.add_child(sphere) ray = Ray(Point(10, 0, -10), Vector(0, 0, 1)) intersections = group.intersect(ray) self.assertEqual(len(intersections), 2) if __name__ == '__main__': main()
groups.py
from shapes import Shape from intersections import Intersections class Group(Shape): def __init__(self, transform=None, material=None): super().__init__(transform=transform, material=material) self.shapes = [] def __len__(self): return len(self.shapes) def __getitem__(self, y): return self.shapes[y] def add_child(self, shape): shape.parent = self self.shapes.append(shape) def intersect(self, ray): ray = ray.transform(self.transform.inverse()) intersections = [] for shape in self.shapes: intersections += shape.intersect(ray).xs return Intersections(*intersections)
shapes_test.py
#!/usr/bin/env python3 from unittest import TestCase, main from shapes import Shape from transformations import translation from matrices import IDENTITY_MATRIX, Matrix from materials import Material from rays import Ray from tuples import Point, Vector from transformations import scaling class ShapeTest(TestCase): def setUp(self): self.shape = Shape(material=Material()) def tearDown(self): pass def test_default_transformation(self): self.assertEqual(self.shape.transform, IDENTITY_MATRIX) def test_material(self): self.assertEqual(self.shape.material.ambient, 0.1) self.assertEqual(self.shape.material, Material()) def test_transform(self): self.assertEqual(Shape().transform, IDENTITY_MATRIX) s = Shape() t = translation(2, 3, 4) s.transform = t self.assertEqual(s.transform, t) def test_parent_attribute(self): s = Shape() self.assertIsNone(s.parent) if __name__ == '__main__': main()
shapes.py
from matrices import Matrix, IDENTITY_MATRIX from materials import Material class Shape: def __init__(self, transform=None, material=None, parent=None): if transform is None: self.transform = IDENTITY_MATRIX else: self.transform = transform if material is None: self.material = Material() else: self.material = material self.parent = None def __repr__(self): return f'{self.__class__.__name__}({self.transform},{self.material})' def intersect(self, ray): raise NotImplementedError() def normal_at(self, point): raise NotImplementedError()
入出力結果(Bash、cmd.exe(コマンドプロンプト)、Terminal、Jupyter(IPython))
C:\Users\...>py groups_test.py ..... ---------------------------------------------------------------------- Ran 5 tests in 0.005s OK C:\Users\...>py shapes_test.py .... ---------------------------------------------------------------------- Ran 4 tests in 0.000s OK C:\Users\...>
0 コメント:
コメントを投稿