def test_translation(self): t = Matrix.translate(5, -3, 2) p = Point(-3, 4, 5) self.assertEqual(t * p, Point(2, 1, 7)) self.assertEqual(t.inverse() * p, Point(-8, 7, 3)) v = Vector(-3, 4, 5) self.assertEqual(t * v, v) self.assertEqual(t.inverse() * v, v)
def test_light_directly_behind_surface_and_eye(self): m = Material() position = Point(0, 0, 0) eyev = Vector(0, 0, -1) normalv = Vector(0, 0, -1) light = PointLight(Point(0, 0, 10), Color(1, 1, 1)) result = lighting(m, light, position, eyev, normalv) self.assertEqual(result, Color(0.1, 0.1, 0.1))
def test_light_and_eye_perpendicular(self): m = Material() position = Point(0, 0, 0) eyev = Vector(0, 0, -1) normalv = Vector(0, 0, -1) light = PointLight(Point(0, 0, -10), Color(1, 1, 1)) result = lighting(m, light, position, eyev, normalv) self.assertEqual(result, Color(1.9, 1.9, 1.9))
def test_light_perpendicular_and_eye_at_45(self): r = math.sqrt(2) / 2 m = Material() position = Point(0, 0, 0) eyev = Vector(0, r, -r) normalv = Vector(0, 0, -1) light = PointLight(Point(0, 0, -10), Color(1, 1, 1)) result = lighting(m, light, position, eyev, normalv) self.assertEqual(result, Color(1.0, 1.0, 1.0))
def test_point_subtraction(self): # subtracting two points results in a vector p1 = Point(3, 2, 1) p2 = Point(5, 6, 7) self.assertEqual(p1 - p2, Vector(-2, -4, -6)) # subtracting a vector from a point results in a new point p = Point(3, 2, 1) v = Vector(5, 6, 7) self.assertEqual(p - v, Point(-2, -4, -6))
def test_scaling(self): s = Matrix.scale(2, 3, 4) p = Point(-4, 6, 8) self.assertEqual(s * p, Point(-8, 18, 32)) v = Vector(-4, 6, 8) self.assertEqual(s * v, Vector(-8, 18, 32)) self.assertEqual(s.inverse() * v, Vector(-2, 2, 2)) s = Matrix.scale(-1, 1, 1) p = Point(2, 3, 4) self.assertEqual(s * p, Point(-2, 3, 4))
def test_light_at_45_and_eye_at_neg_45(self): r = math.sqrt(2) / 2 m = Material() position = Point(0, 0, 0) eyev = Vector(0, -r, -r) normalv = Vector(0, 0, -1) light = PointLight(Point(0, 10, -10), Color(1, 1, 1)) result = lighting(m, light, position, eyev, normalv) x = 1.6363961 self.assertColorEqual(result, Color(x, x, x))
def test_normal_with_transform(self): s = Sphere() s.transform = Matrix.translate(0, 5, 0) n = s.normal(Point(1, 5, 0)) self.assertEqual(n, Vector(1, 0, 0)) s = Sphere() s.transform = Matrix.scale(1, 0.5, 1) r = math.sqrt(2) / 2 n = s.normal(Point(0, r, -r)) self.assertTupleEqual(n, Vector(0, 0.97014, -0.24254))
def test_normal(self): s = Sphere() n = s.normal(Point(1, 0, 0)) self.assertEqual(n, Vector(1, 0, 0)) n = s.normal(Point(0, 1, 0)) self.assertEqual(n, Vector(0, 1, 0)) n = s.normal(Point(0, 0, 1)) self.assertEqual(n, Vector(0, 0, 1)) r = math.sqrt(3) / 3 n = s.normal(Point(r, r, r)) self.assertEqual(n, Vector(r, r, r)) self.assertEqual(n, n.norm())
def test_combinations(self): p = Point(1, 0, 1) a = Matrix.rotate_x(math.pi / 2) b = Matrix.scale(5, 5, 5) c = Matrix.translate(10, 5, 7) p2 = a * p self.assertTupleEqual(p2, Point(1, -1, 0)) p3 = b * p2 self.assertTupleEqual(p3, Point(5, -5, 0)) p4 = c * p3 self.assertTupleEqual(p4, Point(15, 0, 7)) self.assertTupleEqual(c * b * a * p, Point(15, 0, 7))
def test_intersect(self): r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) s = Sphere() xs = s.intersect(r) self.assertEqual(len(xs), 2) self.assertEqual(xs[0].object, s) self.assertEqual(xs[1].object, s)
def test_intersect_with_transform(self): # intersect a scaled sphere r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) s = Sphere() s.transform = Matrix.scale(2, 2, 2) xs = s.intersect(r) self.assertEqual(len(xs), 2) self.assertEqual(xs[0].t, 3) self.assertEqual(xs[1].t, 7) # intersect a translated sphere r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) s = Sphere() s.transform = Matrix.translate(5, 0, 0) xs = s.intersect(r) self.assertEqual(len(xs), 0)
def test_rotation(self): p = Point(0, 1, 0) r = math.sqrt(2) / 2 self.assertTupleEqual(Matrix.rotate_x(math.pi / 4) * p, Point(0, r, r)) self.assertTupleEqual(Matrix.rotate_x(math.pi / 2) * p, Point(0, 0, 1)) # NOTE: error in draft of book where he uses inverse instead of transpose self.assertTupleEqual( Matrix.rotate_x(math.pi / 4).transpose() * p, Point(0, r, -r)) p = Point(0, 0, 1) self.assertTupleEqual(Matrix.rotate_y(math.pi / 4) * p, Point(r, 0, r)) self.assertTupleEqual(Matrix.rotate_y(math.pi / 2) * p, Point(1, 0, 0)) p = Point(0, 1, 0) self.assertTupleEqual( Matrix.rotate_z(math.pi / 4) * p, Point(-r, r, 0)) self.assertTupleEqual( Matrix.rotate_z(math.pi / 2) * p, Point(-1, 0, 0))
def test_shearing(self): p = Point(2, 3, 4) self.assertEqual(Matrix.shear(1, 0, 0, 0, 0, 0) * p, Point(5, 3, 4)) self.assertEqual(Matrix.shear(0, 1, 0, 0, 0, 0) * p, Point(6, 3, 4)) self.assertEqual(Matrix.shear(0, 0, 1, 0, 0, 0) * p, Point(2, 5, 4)) self.assertEqual(Matrix.shear(0, 0, 0, 1, 0, 0) * p, Point(2, 7, 4)) self.assertEqual(Matrix.shear(0, 0, 0, 0, 1, 0) * p, Point(2, 3, 6)) self.assertEqual(Matrix.shear(0, 0, 0, 0, 0, 1) * p, Point(2, 3, 7))
def get_filtered_elements(self): ls = [] punts = self._page.findall('Punt') for punt in punts: if punt.find('Coord').find('Latitud').text \ and punt.find('Coord').find('Longitud').text \ and punt.find('Tooltip').text and self._has_restrictions(punt): lat = float(punt.find('Coord').find('Latitud').text) long = float(punt.find('Coord').find('Longitud').text) name = punt.find('Tooltip').text[0:-1] ls.append(MetroStop(name, Point(lat, long))) return ls
def test_intersect_sphere(self): # through the center r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) s = Sphere() xs = s.intersect(r) self.assertEqual(len(xs), 2) self.assertEqual(xs[0].t, 4) self.assertEqual(xs[1].t, 6) # at a tangent r = Ray(Point(0, 1, -5), Vector(0, 0, 1)) s = Sphere() xs = s.intersect(r) self.assertEqual(len(xs), 2) self.assertEqual(xs[0].t, 5) self.assertEqual(xs[1].t, 5) # why two points? # no intersection r = Ray(Point(0, 2, -5), Vector(0, 0, 1)) s = Sphere() xs = s.intersect(r) self.assertEqual(len(xs), 0) # starting inside the sphere r = Ray(Point(0, 0, 0), Vector(0, 0, 1)) s = Sphere() xs = s.intersect(r) self.assertEqual(len(xs), 2) self.assertEqual(xs[0].t, -1) self.assertEqual(xs[1].t, 1) # starting past the sphere r = Ray(Point(0, 0, 5), Vector(0, 0, 1)) s = Sphere() xs = s.intersect(r) self.assertEqual(len(xs), 2) self.assertEqual(xs[0].t, -6) self.assertEqual(xs[1].t, -4)
def test_create_ray(self): origin = Point(1, 2, 3) direction = Vector(4, 5, 6) r = Ray(origin, direction) self.assertEqual(r.origin, origin) self.assertEqual(r.direction, direction)
def test_point_light(self): p = Point(0, 0, 0) c = Color(1, 1, 1) l = PointLight(p, c) self.assertEqual(l.position, p) self.assertEqual(l.intensity, c)
def test_translation(self): r = Ray(Point(1, 2, 3), Vector(0, 1, 0)) m = Matrix.translate(3, 4, 5) r2 = m.transform(r) self.assertEqual(r2.origin, Point(4, 6, 8)) self.assertEqual(r2.direction, Vector(0, 1, 0))
def __init__(self, radius=1): self.radius = radius self.center = Point(0, 0, 0) self.transform = Matrix.identity() self.material = Material()
def cells(self): for y in range(0, self.columns): for x in range(0, self.rows): yield self[Point(x, y)]
def test_scaling(self): r = Ray(Point(1, 2, 3), Vector(0, 1, 0)) m = Matrix.scale(2, 3, 4) r2 = m.transform(r) self.assertEqual(r2.origin, Point(2, 6, 12)) self.assertEqual(r2.direction, Vector(0, 3, 0))
def __str__(self): return "P={}, V={}".format(self.position, self.velocity) class World(object): def __init__(self, gravity, wind): self.gravity = gravity self.wind = wind def tick(world, projectile): p = projectile.position + projectile.velocity v = projectile.velocity + world.gravity + world.wind return Projectile(p, v) W, H = 900, 550 im = Image.new('RGB', (W, H)) pix = im.load() p = Projectile(Point(0, 1, 0), Vector(1, 1.8, 0).norm() * 11.25) w = World(Vector(0, -0.1, 0), Vector(-0.01, 0, 0)) while p.position.y > 0: pix[int(p.position.x), H - int(p.position.y)] = (255, 0, 0) print(p) p = tick(w, p) im.show()
from sphere import Sphere from color import Color from ray import Ray import intersection from light import PointLight, lighting W = 200 H = 200 D = 200 im = Image.new('RGB', (W, H)) pix = im.load() sphere = Sphere() sphere.material.color = Color(1, 0.2, 1) light_color = Color(1, 1, 1) light_position = Point(-10, 10, -10) light = PointLight(light_position, light_color) ## this is done in object coordinates eye = Point(0, 0, -5) tt = Matrix.translate(0, 0, -2) sphere.transform = tt wall = (-3, 3, -3, 3) # LRBT # the -1 flips the y-coordinate so it's up my = Matrix.scale(1.0, -1.0, 1.0) ms = Matrix.scale( float(wall[1] - wall[0]) / W, float(wall[3] - wall[2]) / H, 1.0) mt = Matrix.translate(wall[0], wall[2], 0) m = my * mt * ms
def test_ray_position(self): r = Ray(Point(2, 3, 4), Vector(1, 0, 0)) self.assertEqual(r.position(0.0), Point(2, 3, 4)) self.assertEqual(r.position(1.0), Point(3, 3, 4)) self.assertEqual(r.position(-1.0), Point(1, 3, 4)) self.assertEqual(r.position(2.5), Point(4.5, 3, 4))
def test_point(self): p = Point(4.3, -4.2, 3.1) self.assertEqual(p.x, 4.3) self.assertEqual(p.y, -4.2) self.assertEqual(p.z, 3.1) self.assertEqual(p.w, 1.0)
def test_point_tuple_equality(self): p = Point(4, -4, 3) t = Tuple(4, -4, 3, 1) self.assertEqual(p, t)
""" """ import math from PIL import Image from tuples import Point from matrix import Matrix S = 500 im = Image.new('RGB', (S, S)) pix = im.load() d = int( S * 0.4) # the length of the "hand" is a little less than half the canvas size p = Point(0, 1, 0) # assume canvas is in XY plane so this is the 12 o'clock position for i in range(12): r = Matrix.rotate_z(i * math.pi / 6) # 2pi/12 positions or pi/6 q = r * p q = Matrix.scale(d, d, 0) * q # make it the size of the "hand" dimensions q = Matrix.translate( S / 2, S / 2, 0) * q # move to the origin of the canvas, really could do S/2, -S/2 pix[int(q.x), S - int(q.y)] = (255, 255, 255) print("{}, {}".format(int(q.x), S - int(q.y))) im.show()
import math from PIL import Image from tuples import Point from matrix import Matrix from sphere import Sphere from ray import Ray W = 200 H = 200 D = 200 im = Image.new('RGB', (W, H)) pix = im.load() if False: ## this is done in image coordinates eye = Point(W / 2, H / 2, D) sphere = Sphere() ts = Matrix.scale(50, 50, 50) tt = Matrix.translate(W / 2, H / 2, D / 4) sphere.transform = tt * ts for x in range(W): for y in range(H): ray = Ray(eye, Point(x, y, 0) - eye) xs = sphere.intersect(ray) if xs: pix[x, y] = (255, 0, 0) print(x) else: ## this is done in object coordinates
def get_event_coordinates(event): attributes = event.find('lloc_simple').find('adreca_simple').find( 'coordenades').find('googleMaps').attrib latitude = float(attributes.get('lat')) longitude = float(attributes.get('lon')) return Point(latitude, longitude)