#pixel center in space p = self.c + px * self.u_x + py * self.u_y #direction vector if self._orth: u = self.direction else: u = (p - self.position) / norm(p - self.position) yield Ray(p, u) yield None #next row if __name__ == '__main__': import pixmap s = objects.Sphere(Vector(0,0,0), 2) cpos = Vector(0, 0, 6) u = Vector.normalize(0, 0, -1) c = Camera(cpos, u, scale=0.25) image = [] l, h = 2**20, 0 for r in c.rays(): if r is not None: if s.intersects(r): col = s.intersectionDistance(r) if col > h: h = col if col < l: l = col image += [col] else: image += [-1] else:
class Ball: def __init__(self, v, circle, parent): self.v = v self.circle = circle self.parent = parent def update(self, t): time_left = t while time_left > 0: self.collisions = [] # left wall self.add_collision( geometry.wall_collision(x=0, y1=0, y2=inf, ball=self.circle.pos, v=self.v * time_left), objects.wall) # right wall self.add_collision( geometry.wall_collision(x=window_width - ballsize, y1=0, y2=inf, ball=self.circle.pos, v=self.v * time_left), objects.wall) # floor self.add_collision( geometry.floor_collision(y=0, x1=0, x2=window_width, ball=self.circle.pos, v=self.v * time_left), objects.floor) # nodes for i in range(2): self.add_collision( geometry.node_collision( list(self.parent.halves[i].node.pos), list(self.circle.pos), self.v * time_left), objects.node, i) # net left wall self.add_collision( geometry.wall_collision(x=window_width / 2 - ballsize - net_width, y1=0, y2=window_height / 2, ball=self.circle.pos, v=self.v * time_left), objects.wall) # net right wall self.add_collision( geometry.wall_collision(x=window_width / 2 + net_width, y1=0, y2=window_height / 2, ball=self.circle.pos, v=self.v * time_left), objects.wall) # net top plate self.add_collision( geometry.floor_collision(y=window_height / 2, x1=window_width / 2 - ballsize - net_width, x2=window_width / 2 + net_width, ball=self.circle.pos, v=self.v * time_left), objects.plate) if self.collisions == []: collides = False else: closest_collision = None for elem in self.collisions: try: if elem.inside: closest_collision = elem collides = True break except AttributeError: continue if closest_collision is None: closest_collision = min( self.collisions, key=lambda x: distance(x.point, self.circle.pos)) closest_collision_time = distance( closest_collision.point, self.circle.pos) / self.v.speed() if closest_collision_time > time_left: collides = False else: collides = True if not collides: self.circle.pos = [ self.circle.pos[0] + self.v.x * time_left, self.circle.pos[1] + self.v.y * time_left ] self.v.y -= g * t time_left = 0 else: stop_needed, restart_needed = \ self.handle_collision(closest_collision) if stop_needed: return (stop_needed, restart_needed) closest_collision_time = distance( closest_collision.point, self.circle.pos) / self.v.speed() time_left -= closest_collision_time self.v.y -= g * closest_collision_time return (False, False) def add_collision(self, *args): point = args[0] kind = args[1] if len(args) == 2: if point is not None: self.collisions.append(Object(kind=kind, point=point)) else: node_id = args[2] if point is not None: point, inside = point self.collisions.append( Object(kind=kind, point=point, node_id=node_id, inside=inside)) def handle_collision(self, collision): self.circle.pos = collision.point if collision.kind == objects.wall: self.v.x = -self.v.x elif collision.kind == objects.floor: if self.circle.pos[0] < window_width / 2: self.parent.add_goal(0) else: self.parent.add_goal(1) return (True, self.parent.stop()) elif collision.kind == objects.plate: self.v.y = -self.v.y elif collision.kind == objects.node: half = self.parent.halves[collision.node_id] node_pos = half.node.pos speed = self.v.speed() self.v = Vector(begin=node_pos, end=self.circle.pos) self.v.normalize() self.v *= speed self.v += half.vector self.v *= spring_ability return (False, False)
def test_vector_normalize(): v1 = Vector([4, 5, 6]) normed = v1.normalize() assert normed.is_unit_vector()
class VectorCase(unittest.TestCase): def setUp(self): self.a = Vector(1.0, 1.0, 1.0) self.b = Vector(1.0, 0.0, 0.0) self.c = Vector(0.0, 0.0, 1.0) def tearDown(self): del self.a del self.b del self.c def test_richmap(self): self.assertTrue(self.a==self.a) # Test equality self.assertFalse(self.a==self.b) # Test equality self.assertTrue(self.a!=self.b) # Test unequality self.assertRaises(TypeError, operator.gt, self.a, self.b) # Test not implemented operators. self.assertFalse(self.a==3.0) # Test other type self.assertFalse(3.0==self.a) # Test other type def test_arithmetics(self): """add and mul""" self.assertAlmostEqual( self.a + self.a, 2.0 * self.a) """sub""" self.assertAlmostEqual( self.a - self.a, Vector(0.0, 0.0, 0.0)) """div and truediv""" self.assertAlmostEqual( self.a / 2.0, Vector(0.5, 0.5, 0.5)) """pow""" """neg""" self.assertEqual( -self.a, Vector(-1.0, -1.0, -1.0)) def test_dot(self): self.assertEqual( self.a.dot(self.b) , 1.0) self.assertEqual( self.b.dot(self.a) , 1.0) def test_cross(self): self.assertEqual( self.a.cross(self.b), Vector(0.0, +1.0, -1.0) ) self.assertEqual( self.b.cross(self.a), Vector(0.0, -1.0, +1.0) ) self.assertEqual( self.b.cross(self.c), Vector(0.0, -1.0, 0.0) ) self.assertEqual( self.c.cross(self.b), Vector(0.0, +1.0, 0.0) ) self.assertEqual( self.a.cross(self.c), Vector(+1.0, -1.0, 0.0) ) self.assertEqual( self.c.cross(self.a), Vector(-1.0, +1.0, 0.0) ) def test_norm(self): # Comparing floating point numbers. self.assertAlmostEqual(self.a.norm(), 3.0**(0.5)) self.assertAlmostEqual(self.b.norm(), 1.0) self.assertAlmostEqual(self.c.norm(), 1.0) def test_normal(self): self.assertIs(type(self.a.normalize()), Vector) # Check that we get a vector back. self.assertEqual(self.b, self.b.normalize()) self.assertAlmostEqual(self.a.normalize(), self.a/self.a.norm()) def test_cosines_with(self): self.assertAlmostEqual(self.b.cosines_with(self.c), 0.0) # Vectors are orthogonal, so cos(90)=0 self.assertAlmostEqual(self.b.cosines_with(self.b), 1.0) # Vectors are parralel