def follow(ray: Ray, scene: Scene, max_iters=1000, renderer=None) -> [Tuple[Ray, Decision]]: """ Follow the ray through a scene. This the highest level ray-tracing function. It moves the ray through the scene and returns a list of rays a Monte Carlo decision events. Each decision is an interaction which alters one of the rays properties such as position, direction or wavelength. Raises ------ TraceError If an error occurred while tracing. Returns ------- List of (Ray, Decision) tuples. """ path = [(ray, Decision.EMIT)] idx = 0 last_ray = ray while ray.is_alive: intersections = scene.intersections(ray.position, ray.direction) points, nodes = zip(*[(x.point, x.hit) for x in intersections]) for ray, decision in step(ray, points, nodes, renderer=renderer): path.append((ray, decision)) if points_equal(ray.position, last_ray.position) and np.allclose(ray.direction, last_ray.direction): raise TraceError("Ray did not move.") last_ray = ray if idx > max_iters: raise TraceError("Ray got stuck.") return path
def test_intersection(self): root = Node(name='Root') a = Node(name="A", parent=root) b = Node(name="B", parent=a) b.geometry = Sphere(radius=1.0) a.translate((1.0, 0.0, 0.0)) loc = (-2.0, 0.0, 0.0) vec = (1.0, 0.0, 0.0) scene = Scene(root=root) intersections = scene.intersections(loc, vec) points = tuple([x.point for x in intersections]) # In frame of a everything is shifed 1 along x assert points == ((0.0, 0.0, 0.0), (2.0, 0.0, 0.0))
def test_intersection_with_rotation_around_z(self): root = Node(name='Root') a = Node(name="A", parent=root) b = Node(name="B", parent=a) b.geometry = Sphere(radius=1.0) a.translate((1.0, 0.0, 0.0)) # This rotation make an z translation in b becomes a -y translation in a a.rotate(np.pi / 2, axis=(0.0, 0.0, 1.0)) loc = (-2.0, 0.0, 0.0) vec = (1.0, 0.0, 0.0) scene = Scene(root=root) intersections = scene.intersections(loc, vec) points = tuple([x.point for x in intersections]) assert np.allclose(points, ((0.0, 0.0, 0.0), (2.0, 0.0, 0.0)))
def test_intersection_with_rotation_around_x(self): root = Node(name='Root') a = Node(name="A", parent=root) b = Node(name="B", parent=a) b.geometry = Sphere(radius=1.0) b.translate((1.0, 0.0, 0.0)) # Rotation around x therefore no displace in x b.rotate(np.pi / 2, (1.0, 0.0, 0.0)) loc = (-2.0, 0.0, 0.0) vec = (1.0, 0.0, 0.0) scene = Scene(root=root) intersections = scene.intersections(loc, vec) points = tuple([x.point for x in intersections]) assert points == ((0.0, 0.0, 0.0), (2.0, 0.0, 0.0))
def test_intersection_with_rotation_around_z(self): root = Node(name='Root') a = Node(name="A", parent=root) b = Node(name="B", parent=a) b.geometry = Sphere(radius=1.0) a.translate((1.0, 0.0, 0.0)) # This rotation make an z translation in b becomes a -y translation in a a.rotate(np.pi/2, axis=(0.0, 0.0, 1.0)) loc = (-2.0, 0.0, 0.0) vec = (1.0, 0.0, 0.0) scene = Scene(root=root) intersections = scene.intersections(loc, vec) points = tuple([x.point for x in intersections]) assert np.allclose(points, ((0.0, 0.0, 0.0), (2.0, 0.0, 0.0)))
def test_intersection_with_rotation_around_x(self): root = Node(name='Root') a = Node(name="A", parent=root) b = Node(name="B", parent=a) b.geometry = Sphere(radius=1.0) b.translate((1.0, 0.0, 0.0)) # Rotation around x therefore no displace in x b.rotate(np.pi/2, (1.0, 0.0, 0.0)) loc = (-2.0, 0.0, 0.0) vec = (1.0, 0.0, 0.0) scene = Scene(root=root) intersections = scene.intersections(loc, vec) points = tuple([x.point for x in intersections]) assert points == ((0.0, 0.0, 0.0), (2.0, 0.0, 0.0))
def test_intersection_coordinate_system(self): root = Node(name="Root", geometry=Sphere(radius=10.0)) a = Node(name="A", parent=root, geometry=Sphere(radius=1.0)) a.translate((1.0, 0.0, 0.0)) scene = Scene(root) initial_ray = Ray( position=(-2.0, 0.0, 0.0), direction=(1.0, 0.0, 0.0), wavelength=None, is_alive=True, ) scene_intersections = scene.intersections(initial_ray.position, initial_ray.direction) a_intersections = tuple(map(lambda x: x.to(root), scene_intersections)) assert scene_intersections == a_intersections
def test_intersection_coordinate_system(self): root = Node(name="Root", geometry=Sphere(radius=10.0)) a = Node(name="A", parent=root, geometry=Sphere(radius=1.0)) a.translate((1.0, 0.0, 0.0)) scene = Scene(root) initial_ray = Ray( position=(-2.0, 0.0, 0.0), direction=(1.0, 0.0, 0.0), wavelength=None, is_alive=True, ) scene_intersections = scene.intersections( initial_ray.position, initial_ray.direction ) a_intersections = tuple(map(lambda x: x.to(root), scene_intersections)) assert scene_intersections == a_intersections