def test_ray_cylinder(self): length = 1.0 radius = 1.0 # end caps only ray_origin = (0.2, 0.2, -1) ray_direction = norm((0.0, 0.0, 1.0)) expected = ((0.2, 0.2, -0.5), (0.2, 0.2, 0.5)) points, _ = ray_z_cylinder(length, radius, ray_origin, ray_direction) assert all([np.allclose(a, b) for a, b in zip(expected, points)]) # surface and bottom ray_origin = (-2, 0.2, 0.0) ray_direction = norm((1.0, 0.2, -0.2)) expected = ((-0.9082895433880116, 0.41834209132239775, -0.2183420913223977), (0.5, 0.7, -0.5)) points, _ = ray_z_cylinder(length, radius, ray_origin, ray_direction) assert all([np.allclose(a, b) for a, b in zip(expected, points)]) # surface and top ray_origin = (-2, 0.2, 0.0) ray_direction = norm((1.0, 0.2, 0.2)) expected = ((-0.9082895433880116, 0.41834209132239775, 0.2183420913223977), (0.5, 0.7, 0.5)) points, _ = ray_z_cylinder(length, radius, ray_origin, ray_direction) assert all([np.allclose(a, b) for a, b in zip(expected, points)]) # touching ray_origin = (0.0, 0.0, -1.5) ray_direction = norm((0.0, 1.0, 1.0)) expected = ((0.0, 1.0, -0.5), ) points, _ = ray_z_cylinder(length, radius, ray_origin, ray_direction) print(points) print(expected) assert all([np.allclose(a, b) for a, b in zip(expected, points)])
def test_angle_between_acute(self): # 45 deg. between vectors (pi/4) v1 = norm((1.0, 1.0, 0.0)) v2 = norm((1.0, 0.0, 0.0)) rads = angle_between(v1, v2) expected = np.pi / 4.0 assert np.isclose(rads, expected)
def test_angle_between_obtuse(self): """ Negative dot product means vectors form an obtuse angle. """ v1 = norm((1.0, 1.0, 0.0)) v2 = norm((-1.0, 0.0, 0.0)) d = np.dot(v1, v2) assert d < 0.0 rads = angle_between(v1, v2) expected = np.pi - np.pi / 4.0 assert np.isclose(rads, expected)
def test_intersection(self): obj = Cylinder(length=1.0, radius=1.0) # surface and bottom ro = (-2, 0.2, 0.0) rd = norm((1.0, 0.2, -0.2)) expected = ((-0.9082895433880116, 0.41834209132239775, -0.2183420913223977), (0.5, 0.7, -0.5)) points = obj.intersections(ro, rd) assert all([np.allclose(a, b) for a, b in zip(expected, points)])
def test_intersection(self): obj = Cylinder(length=1.0, radius=1.0) # surface and bottom ro = (-2, 0.2, 0.0) rd = norm((1.0, 0.2, -0.2)) expected = ( (-0.9082895433880116, 0.41834209132239775, -0.2183420913223977), (0.5, 0.7, -0.5) ) points = obj.intersections(ro, rd) assert all([np.allclose(a, b) for a, b in zip(expected, points)])
def is_on_surface(self, point): # Just use any direction for a fake ray, we only need the distance _, dist = ray_z_cylinder(self.length, self.radius, point, norm((1, 1, 1))) if len(dist) == 0: return False dist = dist[0] # Only need closest intersection if close_to_zero(dist): # print("dist from point {} {} is_on_surface True".format(dist, point)) return True # print("dist from point {} {} is_on_surface False".format(dist, point)) return False
def is_on_surface(self, point): # Just use any direction for a fake ray, we only need the distance _, dist = ray_z_cylinder(self.length, self.radius, point, norm((1,1,1))) if len(dist) == 0: return False dist = dist[0] # Only need closest intersection if close_to_zero(dist): print("dist from point {} {} is_on_surface True".format(dist, point)) return True print("dist from point {} {} is_on_surface False".format(dist, point)) return False
def normal(self, surface_point): """ Normal faces outwards by convention. """ z = surface_point[2] if np.isclose(z, -0.5 * self.length): return (0.0, 0.0, -1.0) elif np.isclose(z, 0.5 * self.length): return (0.0, 0.0, 1.0) elif np.isclose(self.radius, np.sqrt(np.sum(np.array(surface_point[:2]) ** 2))): v = np.array(surface_point) - np.array([0.0, 0.0, surface_point[2]]) n = tuple(norm(v).tolist()) return n else: raise GeometryError("Not a surface point.")
def normal(self, surface_point): """ Normal faces outwards by convention. """ z = surface_point[2] if np.isclose(z, -0.5 * self.length): return (0.0, 0.0, -1.0) elif np.isclose(z, 0.5 * self.length): return (0.0, 0.0, 1.0) elif np.isclose(self.radius, np.sqrt(np.sum(np.array(surface_point[:2])**2))): v = np.array(surface_point) - np.array([0.0, 0.0, surface_point[2]]) n = tuple(norm(v).tolist()) return n else: raise GeometryError("Not a surface point.")
def test_is_entering_true(self): obj = Cylinder(length=1.0, radius=1.0) ro, rd = (0.0, 0.0, 0.5), norm((1.0, 1.0, -1.0)) assert obj.is_entering(ro, rd) == True ro, rd = (0.0, 0.0, 0.5), norm((1.0, 1.0, 1.0)) assert obj.is_entering(ro, rd) == False ro, rd = (0.0, 0.0, -0.5), norm((1.0, 1.0, 1.0)) assert obj.is_entering(ro, rd) == True ro, rd = (0.0, 0.0, -0.5), norm((1.0, 1.0, -1.0)) assert obj.is_entering(ro, rd) == False ro, rd = (0.0, 1.0, 0.0), norm((1.0, -1.0, 1.0)) assert obj.is_entering(ro, rd) == True ro, rd = (0.0, 1.0, 0.0), norm((1.0, 1.0, 1.0)) assert obj.is_entering(ro, rd) == False ro, rd = (-1.0, 0.0, 0.0), norm((1.0, 1.0, 1.0)) assert obj.is_entering(ro, rd) == True ro, rd = (-1.0, 0.0, 0.0), norm((-1.0, 1.0, 1.0)) assert obj.is_entering(ro, rd) == False
def test_ray_reflecting_interaction(self): # low > very high refractive index np.random.seed(2) mat1 = Dielectric.make_constant((400, 800), 1.0) mat2 = Dielectric.make_constant((400, 800), 6.0) root = Node(name="Root", parent=None) root.geometry = Sphere(radius=10.0, material=mat1) a = Node(name="A", parent=root) a.geometry = Sphere(radius=1.0, material=mat2) ray = Ray(position=(-1.0, 0.0, 0.0), direction=norm((-0.2, 0.2, 1.0)), wavelength=555.0, is_alive=True) from_node = root to_node = a interface = DielectricInterface(from_node, to_node) new_ray = interface.trace(ray) assert np.sign(ray.direction[0]) != np.sign(new_ray.direction[0]) # Reflected # Direction should be different after refracting interface assert all([not np.allclose(new_ray.direction, ray.direction), np.allclose(new_ray.position, ray.position), new_ray.wavelength == ray.wavelength, new_ray.is_alive == ray.is_alive])
def test_surface_point_is_exiting_3(self): m = Mesh(trimesh.creation.icosphere()) position = (0, 0, -1) direction = norm((1, 0, -1)) # tangential ray # Assert surface point is entering assert m.is_entering(position, direction) == False
def test_smallest_angle_between(self): v1 = norm((1.0, 1.0, 0.0)) v2 = norm((-1.0, 0.0, 0.0)) smallest_angle_between(v1, v2)
def test_angle_between(self): normal = norm((1.0, 0.0, 0.0)) vector = norm((1.0, 0.0, 0.0)) assert angle_between(normal, vector) == 0.0 assert angle_between(-normal, vector) == np.pi
def test_norm(self): v = (1.0, 1.0, 1.0) expected = np.array(v) / magnitude(v) assert np.allclose(norm(v), expected)