def solar_disk_bundle(num_rays, center, direction, radius, ang_range): """Generates a ray bundle emanating from a disk, with each surface element of the disk having the same ray density. The rays all point at directions uniformly distributed between a given angle range from a given direction. Setting of the bundle's energy is left to the caller. Arguments: num_rays - number of rays to generate. center - a column 3-array with the 3D coordinate of the disk's center direction - a 1D 3-array with the unit average direction vector for the bundle. radius - of the disk. ang_range - in radians, the maximum deviation from <direction). Returns: a RayBundle object with the above charachteristics set. """ # Divergence from <direction>: phi = random.uniform(high=2 * N.pi, size=num_rays) theta = random.uniform(high=ang_range, size=num_rays) # A vector on the xy plane (arbitrary), around which we rotate <direction> # by theta: perp = N.array([direction[1], -direction[0], 0]) if N.all(perp == 0): perp = N.array([1., 0., 0.]) directions = N.empty((3, num_rays)) for ray in xrange(num_rays): dir = N.dot(general_axis_rotation(perp, theta[ray]), direction) dir = N.dot(general_axis_rotation(direction, phi[ray]), dir) directions[:, ray] = dir # Locations: not_inside = N.ones(num_rays, dtype=N.bool) xs = N.empty(num_rays) ys = N.empty(num_rays) while not_inside.any(): xs[not_inside] = random.uniform(low=-radius, high=radius, size=len(not_inside)) ys[not_inside] = random.uniform(low=-radius, high=radius, size=len(not_inside)) not_inside = xs**2 + ys**2 > radius**2 # Rotate locations to the plane defined by <direction>: rot = N.vstack((perp, N.cross(direction, perp), direction)) vertices_local = N.array([xs, ys, N.zeros(num_rays)]) vertices_global = N.dot(rot, vertices_local) rayb = RayBundle() rayb.set_vertices(vertices_global + center) rayb.set_directions(directions) return rayb
def solar_disk_bundle(num_rays, center, direction, radius, ang_range): """Generates a ray bundle emanating from a disk, with each surface element of the disk having the same ray density. The rays all point at directions uniformly distributed between a given angle range from a given direction. Setting of the bundle's energy is left to the caller. Arguments: num_rays - number of rays to generate. center - a column 3-array with the 3D coordinate of the disk's center direction - a 1D 3-array with the unit average direction vector for the bundle. radius - of the disk. ang_range - in radians, the maximum deviation from <direction). Returns: a RayBundle object with the above charachteristics set. """ # Divergence from <direction>: phi = random.uniform(high=2*N.pi, size=num_rays) theta = random.uniform(high=ang_range, size=num_rays) # A vector on the xy plane (arbitrary), around which we rotate <direction> # by theta: perp = N.array([direction[1], -direction[0], 0]) if N.all(perp == 0): perp = N.array([1., 0., 0.]) directions = N.empty((3, num_rays)) for ray in xrange(num_rays): dir = N.dot(general_axis_rotation(perp, theta[ray]), direction) dir = N.dot(general_axis_rotation(direction, phi[ray]), dir) directions[:, ray] = dir # Locations: not_inside = N.ones(num_rays, dtype=N.bool) xs = N.empty(num_rays) ys = N.empty(num_rays) while not_inside.any(): xs[not_inside] = random.uniform(low=-radius, high=radius, size=len(not_inside)) ys[not_inside] = random.uniform(low=-radius, high=radius, size=len(not_inside)) not_inside = xs**2 + ys**2 > radius**2 # Rotate locations to the plane defined by <direction>: rot = N.vstack((perp, N.cross(direction, perp), direction)) vertices_local = N.array([xs, ys, N.zeros(num_rays)]) vertices_global = N.dot(rot, vertices_local) rayb = RayBundle() rayb.set_vertices(vertices_global + center) rayb.set_directions(directions) return rayb
def test_intersect_ray2(self): rot = general_axis_rotation([1, 0, 0], N.pi / 4) objects = [FlatSurface(rotation=rot, width=4, height=4)] engine = TracerEngine(objects) params = engine.intersect_ray(self._bund)[0] correct_params = N.r_[[False, True, False]] N.testing.assert_array_almost_equal(params, correct_params)
def setUp(self): self.x = 1 / (math.sqrt(2)) dir = N.c_[[0, self.x, -self.x], [0, 1, 0]] position = N.c_[[0, 0, 1], [0, 0, 1]] self._bund = RayBundle() self._bund.set_vertices(position) self._bund.set_directions(dir) rot1 = general_axis_rotation([1, 0, 0], N.pi / 4) rot2 = general_axis_rotation([1, 0, 0], N.pi / (-4)) objects = [ FlatSurface(rotation=rot1, width=4, height=4), FlatSurface(rotation=rot2, width=4, height=4) ] energy = N.array([1, 1]) self._bund.set_energy(energy) self.engine = TracerEngine(objects)