def testHit(self): sphere = Sphere() ray1 = Ray(origin=Point(0, 0, 2), dir=-VEC_Z) intersection1 = sphere.ray_intersection(ray1) assert intersection1 assert HitRecord( world_point=Point(0.0, 0.0, 1.0), normal=Normal(0.0, 0.0, 1.0), surface_point=Vec2d(0.0, 0.0), t=1.0, ray=ray1, material=sphere.material, ).is_close(intersection1) ray2 = Ray(origin=Point(3, 0, 0), dir=-VEC_X) intersection2 = sphere.ray_intersection(ray2) assert intersection2 assert HitRecord( world_point=Point(1.0, 0.0, 0.0), normal=Normal(1.0, 0.0, 0.0), surface_point=Vec2d(0.0, 0.5), t=2.0, ray=ray2, material=sphere.material, ).is_close(intersection2) assert not sphere.ray_intersection( Ray(origin=Point(0, 10, 2), dir=-VEC_Z))
def testNormals(self): sphere = Sphere(transformation=scaling(Vec(2.0, 1.0, 1.0))) ray = Ray(origin=Point(1.0, 1.0, 0.0), dir=Vec(-1.0, -1.0)) intersection = sphere.ray_intersection(ray) # We normalize "intersection.normal", as we are not interested in its length assert intersection.normal.normalize().is_close( Normal(1.0, 4.0, 0.0).normalize())
def demo(width, height, angle_deg, orthogonal, pfm_output, png_output): image = HdrImage(width, height) # Create a world and populate it with a few shapes world = World() for x in [-0.5, 0.5]: for y in [-0.5, 0.5]: for z in [-0.5, 0.5]: world.add( Sphere(transformation=translation(Vec(x, y, z)) * scaling(Vec(0.1, 0.1, 0.1)))) # Place two other balls in the bottom/left part of the cube, so # that we can check if there are issues with the orientation of # the image world.add( Sphere(transformation=translation(Vec(0.0, 0.0, -0.5)) * scaling(Vec(0.1, 0.1, 0.1)))) world.add( Sphere(transformation=translation(Vec(0.0, 0.5, 0.0)) * scaling(Vec(0.1, 0.1, 0.1)))) # Initialize a camera camera_tr = rotation_z(angle_deg=angle_deg) * translation( Vec(-1.0, 0.0, 0.0)) if orthogonal: camera = OrthogonalCamera(aspect_ratio=width / height, transformation=camera_tr) else: camera = PerspectiveCamera(aspect_ratio=width / height, transformation=camera_tr) # Run the ray-tracer tracer = ImageTracer(image=image, camera=camera) def compute_color(ray: Ray) -> Color: if world.ray_intersection(ray): return WHITE else: return BLACK tracer.fire_all_rays(compute_color) # Save the HDR image with open(pfm_output, "wb") as outf: image.write_pfm(outf) print(f"HDR demo image written to {pfm_output}") # Apply tone-mapping to the image image.normalize_image(factor=1.0) image.clamp_image() # Save the LDR image with open(png_output, "wb") as outf: image.write_ldr_image(outf, "PNG") print(f"PNG demo image written to {png_output}")
def testNormalDirection(self): # Scaling a sphere by -1 keeps the sphere the same but reverses its # reference frame sphere = Sphere(transformation=scaling(Vec(-1.0, -1.0, -1.0))) ray = Ray(origin=Point(0.0, 2.0, 0.0), dir=-VEC_Y) intersection = sphere.ray_intersection(ray) # We normalize "intersection.normal", as we are not interested in its length assert intersection.normal.normalize().is_close( Normal(0.0, 1.0, 0.0).normalize())
def testInnerHit(self): sphere = Sphere() ray = Ray(origin=Point(0, 0, 0), dir=VEC_X) intersection = sphere.ray_intersection(ray) assert intersection assert HitRecord( world_point=Point(1.0, 0.0, 0.0), normal=Normal(-1.0, 0.0, 0.0), surface_point=Vec2d(0.0, 0.5), t=1.0, ray=ray, ).is_close(intersection)
def testFlatRenderer(self): sphere_color = Color(1.0, 2.0, 3.0) sphere = Sphere(transformation=translation(Vec(2, 0, 0)) * scaling(Vec(0.2, 0.2, 0.2)), material=Material(brdf=DiffuseBRDF( pigment=UniformPigment(sphere_color)))) image = HdrImage(width=3, height=3) camera = OrthogonalCamera() tracer = ImageTracer(image=image, camera=camera) world = World() world.add_shape(sphere) renderer = FlatRenderer(world=world) tracer.fire_all_rays(renderer) assert image.get_pixel(0, 0).is_close(BLACK) assert image.get_pixel(1, 0).is_close(BLACK) assert image.get_pixel(2, 0).is_close(BLACK) assert image.get_pixel(0, 1).is_close(BLACK) assert image.get_pixel(1, 1).is_close(sphere_color) assert image.get_pixel(2, 1).is_close(BLACK) assert image.get_pixel(0, 2).is_close(BLACK) assert image.get_pixel(1, 2).is_close(BLACK) assert image.get_pixel(2, 2).is_close(BLACK)
def testFurnace(self): pcg = PCG() # Run the furnace test several times using random values for the emitted radiance and reflectance for i in range(5): world = World() emitted_radiance = pcg.random_float() reflectance = pcg.random_float( ) * 0.9 # Be sure to pick a reflectance that's not too close to 1 enclosure_material = Material( brdf=DiffuseBRDF( pigment=UniformPigment(Color(1.0, 1.0, 1.0) * reflectance)), emitted_radiance=UniformPigment( Color(1.0, 1.0, 1.0) * emitted_radiance), ) world.add_shape(Sphere(material=enclosure_material)) path_tracer = PathTracer(pcg=pcg, num_of_rays=1, world=world, max_depth=100, russian_roulette_limit=101) ray = Ray(origin=Point(0, 0, 0), dir=Vec(1, 0, 0)) color = path_tracer(ray) expected = emitted_radiance / (1.0 - reflectance) assert pytest.approx(expected, 1e-3) == color.r assert pytest.approx(expected, 1e-3) == color.g assert pytest.approx(expected, 1e-3) == color.b
def build_sequentially_attaching_sheres(N): """ Arguments: --------- N: number of shapes to be build """ def t(s): return s[0] def r(s): return s[1] def overlap(s1, s2): d = np.sqrt(np.sum((t(s1)-t(s2))**2)) return d < r(s1) + r(s2) def random_point(s, d=0): v = np.random.randn(3) v = v / np.sqrt((v**2).sum()) return t(s) + v*(r(s)+d) spheres = [(np.zeros(3), np.random.rand()*0.4 + 0.1)] while len(spheres) < N: s1 = spheres[np.random.choice(len(spheres))] s2r = np.random.rand()*0.4 + 0.1 s2c = random_point(s1, s2r) s2 = (s2c, s2r) if not any(overlap(s, s2) for s in spheres): spheres.append(s2) return [Sphere(r(s)).translate(t(s)[:, np.newaxis]) for s in spheres]
def __init__(self, **kwargs): if 'boundary_shape' in kwargs.keys(): self.boundary = kwargs['boundary_shape'] elif 'r' in kwargs.keys(): self.boundary = Sphere(kwargs['r']) self.intersections = [] self.intersected = False self.collected = [] self.depth = 0 # these parameters are used if one wants to generate # electrons piece-wise inside the Disc. Then the depth inside the # Disc where the electrons are generated is given by self.depth # and the thickness of the piece is given by self.height self.height = 0.01 self.n_event_cutoff = 50 # max number of inel events per electron self.parameters = {}
def sphere(center=(0,0,0), size=1, **kwds): r""" Return a plot of a sphere of radius size centered at `(x,y,z)`. INPUT: - ``(x,y,z)`` - center (default: (0,0,0) - ``size`` - the radius (default: 1) EXAMPLES: A simple sphere:: sage: sphere() Two spheres touching:: sage: sphere(center=(-1,0,0)) + sphere(center=(1,0,0), aspect_ratio=[1,1,1]) Spheres of radii 1 and 2 one stuck into the other:: sage: sphere(color='orange') + sphere(color=(0,0,0.3), \ center=(0,0,-2),size=2,opacity=0.9) We draw a transparent sphere on a saddle. :: sage: u,v = var('u v') sage: saddle = plot3d(u^2 - v^2, (u,-2,2), (v,-2,2)) sage: sphere((0,0,1), color='red', opacity=0.5, aspect_ratio=[1,1,1]) + saddle TESTS:: sage: T = sage.plot.plot3d.texture.Texture('red') sage: S = sphere(texture=T) sage: T in S.texture_set() True """ kwds['texture'] = Texture(**kwds) G = Sphere(size, **kwds) H = G.translate(center) H._set_extra_kwds(kwds) return H
def testRayIntersections(self): world = World() sphere1 = Sphere(transformation=translation(VEC_X * 2)) sphere2 = Sphere(transformation=translation(VEC_X * 8)) world.add_shape(sphere1) world.add_shape(sphere2) intersection1 = world.ray_intersection( Ray(origin=Point(0.0, 0.0, 0.0), dir=VEC_X)) assert intersection1 assert intersection1.world_point.is_close(Point(1.0, 0.0, 0.0)) intersection2 = world.ray_intersection( Ray(origin=Point(10.0, 0.0, 0.0), dir=-VEC_X)) assert intersection2 assert intersection2.world_point.is_close(Point(9.0, 0.0, 0.0))
def main(): canvas_pixels = 500 canvas = Canvas(canvas_pixels, canvas_pixels) shape = Sphere() # assign material shape.material = Material() shape.material.color = color(1, 0.2, 1) light_position = point(-10, 10, -10) light_color = color(1, 1, 1) light = PointLight(light_position, light_color) ray_origin = point(0, 0, -5) wall_z = 10 wall_size = 7.0 pixel_size = wall_size / canvas_pixels half = wall_size / 2 for y in range(canvas_pixels): world_y = half - pixel_size * y for x in range(canvas_pixels): world_x = -half + pixel_size * x pos = point(world_x, world_y, wall_z) r = Ray(ray_origin, normalize(subtract(pos, ray_origin))) xs = shape.intersect(r) shape_hit = hit(xs) if shape_hit is not None: hit_point = r.position_at(shape_hit.t) normal = shape_hit.object.normal_at(hit_point) eye = negate(r.direction) px_color = lighting(shape_hit.object.material, shape_hit.object, light, hit_point, eye, normal) canvas.set_pixel(x, y, px_color) with open('render_phong_sphere.ppm', 'w') as out_file: out_file.write(canvas.to_ppm())
def make_ball(self, scale, color): """ Create a Sphere with the specified parameters @param scale: scale factor for the sphere @param color: color for the sphere @return: the created sphere """ sphere = Sphere() sphere.set_location(0, 0, 0) sphere.set_size(scale, scale, scale) sphere.set_color(c=color) return sphere
def test_quick_ray_intersection(self): world = World() sphere1 = Sphere(transformation=translation(VEC_X * 2)) sphere2 = Sphere(transformation=translation(VEC_X * 8)) world.add_shape(sphere1) world.add_shape(sphere2) assert not world.is_point_visible(point=Point(10.0, 0.0, 0.0), observer_pos=Point(0.0, 0.0, 0.0)) assert not world.is_point_visible(point=Point(5.0, 0.0, 0.0), observer_pos=Point(0.0, 0.0, 0.0)) assert world.is_point_visible(point=Point(5.0, 0.0, 0.0), observer_pos=Point(4.0, 0.0, 0.0)) assert world.is_point_visible(point=Point(0.5, 0.0, 0.0), observer_pos=Point(0.0, 0.0, 0.0)) assert world.is_point_visible(point=Point(0.0, 10.0, 0.0), observer_pos=Point(0.0, 0.0, 0.0)) assert world.is_point_visible(point=Point(0.0, 0.0, 10.0), observer_pos=Point(0.0, 0.0, 0.0))
def main(): canvas_pixels = 400 canvas = Canvas(canvas_pixels, canvas_pixels) red = color(1, 0, 0) shape = Sphere() # shrink it along the y axis #shape.set_transform(scaling(1, 0.5, 1)) # shrink it along the x axis #shape.set_transform(scaling(0.5, 1, 1)) # shrink it, and rotate it! # shape.set_transform(multiply_matrix(rotation_z(pi / 4), scaling(0.5, 1, # 1))) # shrink it, and skew it! # shape.set_transform( # multiply_matrix(shearing(1, 0, 0, 0, 0, 0), scaling(0.5, 1, 1))) ray_origin = point(0, 0, -5) wall_z = 10 wall_size = 7.0 pixel_size = wall_size / canvas_pixels half = wall_size / 2 for y in range(canvas_pixels): world_y = half - pixel_size * y for x in range(canvas_pixels): world_x = -half + pixel_size * x pos = point(world_x, world_y, wall_z) r = Ray(ray_origin, normalize(subtract(pos, ray_origin))) xs = shape.intersect(r) if hit(xs) is not None: canvas.set_pixel(x, y, red) with open('render_sphere.ppm', 'w') as out_file: out_file.write(canvas.to_ppm())
def testTransformation(self): sphere = Sphere(transformation=translation(Vec(10.0, 0.0, 0.0))) ray1 = Ray(origin=Point(10, 0, 2), dir=-VEC_Z) intersection1 = sphere.ray_intersection(ray1) assert intersection1 assert HitRecord( world_point=Point(10.0, 0.0, 1.0), normal=Normal(0.0, 0.0, 1.0), surface_point=Vec2d(0.0, 0.0), t=1.0, ray=ray1, material=sphere.material, ).is_close(intersection1) ray2 = Ray(origin=Point(13, 0, 0), dir=-VEC_X) intersection2 = sphere.ray_intersection(ray2) assert intersection2 assert HitRecord( world_point=Point(11.0, 0.0, 0.0), normal=Normal(1.0, 0.0, 0.0), surface_point=Vec2d(0.0, 0.5), t=2.0, ray=ray2, material=sphere.material, ).is_close(intersection2) # Check if the sphere failed to move by trying to hit the untransformed shape assert not sphere.ray_intersection( Ray(origin=Point(0, 0, 2), dir=-VEC_Z)) # Check if the *inverse* transformation was wrongly applied assert not sphere.ray_intersection( Ray(origin=Point(-10, 0, 0), dir=-VEC_Z))
def testUVCoordinates(self): sphere = Sphere() # The first four rays hit the unit sphere at the # points P1, P2, P3, and P4. # # ^ y # | P2 # , - ~ * ~ - , # , ' | ' , # , | , # , | , # , | , P1 # -----*-------------+-------------*---------> x # P3 , | , # , | , # , | , # , | , ' # ' - , _ * _ , ' # | P4 # # P5 and P6 are aligned along the x axis and are displaced # along z (ray5 in the positive direction, ray6 in the negative # direction). ray1 = Ray(origin=Point(2.0, 0.0, 0.0), dir=-VEC_X) assert sphere.ray_intersection(ray1).surface_point.is_close( Vec2d(0.0, 0.5)) ray2 = Ray(origin=Point(0.0, 2.0, 0.0), dir=-VEC_Y) assert sphere.ray_intersection(ray2).surface_point.is_close( Vec2d(0.25, 0.5)) ray3 = Ray(origin=Point(-2.0, 0.0, 0.0), dir=VEC_X) assert sphere.ray_intersection(ray3).surface_point.is_close( Vec2d(0.5, 0.5)) ray4 = Ray(origin=Point(0.0, -2.0, 0.0), dir=VEC_Y) assert sphere.ray_intersection(ray4).surface_point.is_close( Vec2d(0.75, 0.5)) ray5 = Ray(origin=Point(2.0, 0.0, 0.5), dir=-VEC_X) assert sphere.ray_intersection(ray5).surface_point.is_close( Vec2d(0.0, 1 / 3)) ray6 = Ray(origin=Point(2.0, 0.0, -0.5), dir=-VEC_X) assert sphere.ray_intersection(ray6).surface_point.is_close( Vec2d(0.0, 2 / 3))
def parse_sphere(input_file: InputStream, scene: Scene) -> Sphere: expect_symbol(input_file, "(") material_name = expect_identifier(input_file) if material_name not in scene.materials.keys(): # We raise the exception here because input_file is pointing to the end of the wrong identifier raise GrammarError(input_file.location, f"unknown material {material_name}") expect_symbol(input_file, ",") transformation = parse_transformation(input_file, scene) expect_symbol(input_file, ")") return Sphere(transformation=transformation, material=scene.materials[material_name])
def revolution_animate(self, ring='n'): """Function that makes the animation of moviment""" if ring == 'y': self.draw_ring() if self.__revolution_loop == self.__number_revolution: self.__revolution_loop = 0 x = self.orbit_list[self.__revolution_loop].x y = self.orbit_list[self.__revolution_loop].y z = self.orbit_list[self.__revolution_loop].z if self.__mode == "2D": Circle(x, y, self.radius, self.__total).draw() else: Sphere(x, y, z, self.radius, self.__total, self.color).draw() self.__revolution_loop += 1
def default(cls): world = cls() world.add_light(PointLight(point(-10, 10, -10), color(1, 1, 1))) sphere1 = Sphere() mat = Material() mat.color = color(0.8, 1.0, 0.6) mat.diffuse = 0.7 mat.specular = 0.2 sphere1.material = mat sphere2 = Sphere() sphere2.set_transform(scaling(0.5, 0.5, 0.5)) world.objects.append(sphere1) world.objects.append(sphere2) return world
def import_objects(self, engine): ''' Imports all objects stored in the ObjectData table according to their type. ''' for name, colour, points, lines, surfaces, position, _type, *args in self.cursor.execute( 'SELECT * FROM ObjectData'): args = [attribute for attribute in args if attribute != None] if _type == 'Cube': object_3d = Cube(name, data_handling.string_to_float_array(position), *args, colour) if _type == 'Quad': object_3d = Quad(name, data_handling.string_to_float_array(position), *args, colour) if _type == 'Plane': object_3d = Plane( name, data_handling.string_to_float_array(position), *args, colour) if _type == 'Polygon': object_3d = Polygon( name, data_handling.string_to_float_array(position), *args, colour) if _type == 'Sphere': object_3d = Sphere( name, data_handling.string_to_float_array(position), *args, colour) if _type == 'Line2D': object_3d = Line2D( name, data_handling.string_to_float_array(position), *args, colour) if _type == 'Line3D': object_3d = Line3D( name, data_handling.string_to_float_array(position), data_handling.string_to_float_array(*args), colour) object_3d.add_points( Matrix(data_handling.string_to_2d_float_array(points, 3))) object_3d.add_lines(data_handling.string_to_2d_int_array(lines, 2)) object_3d.add_surfaces( data_handling.string_to_2d_int_array(surfaces, 4)) engine.add_object(object_3d)
"""Examples of how to use the shapes module.""" # Import the classes we use here (shapes.py should be in the same directory): from shapes import Cube, Sphere # The following creates a new object (my_cube) from the Cube class: my_cube = Cube(position=(1, -2, 0.5), edge_length=5) my_cube.draw() print('My cube\'s volume: ', my_cube.volume()) print('My cube\'s surface: ', my_cube.surface(), '\n') # The following creates a new object (my_sphere) from the Sphere class: my_sphere = Sphere(position=(12.2, 0, -17.87), radius=7.5) my_sphere.draw() print('My sphere\'s volume: ', my_sphere.volume()) print('My sphere\'s surface: ', my_sphere.surface(), '\n') # What is the distance between my_square and my_cube? print('The distance between my cube and my sphere is: ', my_cube.distance_to(my_sphere))
def add_sphere(self): """ Add a sohere to the current scene """ self.scenes[self.current_scene].add_object(Sphere()) self.redraw()
def step_create_sphere_s_from_yaml(context): context.s = Sphere.from_yaml(context.data)
def glass_sphere(): sphere = Sphere() sphere.material.transparency = 1.0 sphere.material.refractive_index = 1.5 return sphere
def step_create_sphere_s(context): context.s = Sphere()
def step_create_sphere_s1(context): context.s1 = Sphere()
red = np.array([.047, .09, .447]) orange = np.array([.137, .568, .901]) green = np.array([.274, .627, .431]) white = np.array([1., 1., 1]) MatGray = Material(color=gray, ambient=0.7, diffuse=0.9, specular=1., shinyness=80.) MatBlue = Material(color=blue, ambient=0.7, diffuse=0.9, specular=.9, shinyness=80.) MatRed = Material(color=white, ambient=0.7, diffuse=0.9, specular=.9, shinyness=80., refraction_weight=.8) MatGreen = Material(color=green, ambient=0.7, diffuse=0.6, specular=1., shinyness=80.) MatOrange = Material(color=orange, ambient=0.1, diffuse=0.9, specular=1., shinyness=80., refraction_weight=.4) MatWhite = Material(color=white, ambient=0.1, diffuse=0.9, specular=1., shinyness=80.) MatBack = Material(color=light_green, ambient=0.1, diffuse=0.9, specular=1., shinyness=80.) MatBack2 = Material(color=light_pink, ambient=0.1, diffuse=0.9, specular=1., shinyness=80.) # build shapes s1 = Sphere(np.array([170.,0.,20]), 20, MatBlue) s2 = Sphere(np.array([250.,95.,60]), 60, MatGreen) s3 = Sphere(np.array([260.,-35.,35]), 35, MatRed) s4 = Sphere(np.array([200.,-15.,45]), 5, MatOrange) s5 = Sphere(np.array([0., 0., 20.]), 20, MatRed) s6 = Sphere(np.array([-20., 10., 5.]), 5, MatOrange) s7 = Sphere(np.array([-20., -10., 5.]), 5, MatGreen) back = Plane(np.array([300., 0., 0.]), np.array([1., 0., 0.]), MatBack) right = Plane(np.array([0., -170., 0.]), np.array([0, -1., 0.]), MatBack2) left = Plane(np.array([0., 170., 0.]), np.array([0, 1., 0.]), MatBack2) b = CheckBoard(np.array([0., 0., 0.]), np.array([0., 0., 1.]), MatGray) if True: s = ShapeSet()
from math import pi as PI from core import Vector, Canvas, Camera, Scene, LightSource from core.dynamics import rotate, oscillate, combine from shapes import Sphere, Cuboid # Camera canvas = Canvas(Vector(60, 30)) camera = Camera(Vector(3, 3, 0), Vector(0, 0, 1), canvas, PI / 3, 13) camera.advance = combine(rotate(Vector(3, 3, 5), -2 * PI / 60), ) main_light = LightSource(Vector(2, 4.5, 1), 9) secondary_light = LightSource(Vector(6, 3, 7), 4) lights = [main_light, secondary_light] # Objects body = Cuboid(Vector(3, 3, 5), Vector(1.2, 3, 1)) head = Sphere(Vector(3, 4.5, 5), 0.8) balls = [Sphere(Vector(x, 1, 5), 1) for x in [2, 4]] wall = Cuboid(Vector(3, 3, 11), Vector(10, 10, 1)) corner = Cuboid(Vector(-3, 3, 5), Vector(1, 10, 10)) floor = Cuboid(Vector(3, 0, 5), Vector(10, 1, 10)) objects = [body, head, wall, corner, floor] + balls # Scene scene = Scene("bigben", camera, lights, objects, frame_count=60)
def step_create_sphere_s2(context): context.s2 = Sphere()