In [11]:
from vpython import *
import numpy

scene = canvas()

#Classes
# A class is a template for an object
    #Ray class is a template for a ray
    #init: Set all of the variables for the beam
    #define methods

class ray():
    '''A light ray class'''
    def __init__(self,startPoint,directionVector,color):
        self.startPoint = startPoint
        self.currentPoint = startPoint
        self.directionVector= directionVector.norm()
        self.color = color
        self.length = 10
        self.ray = curve(pos=self.currentPoint, color=self.color)
        self.draw_ray()
        
        #Draw all rays in Source
    def draw_ray(self):
        '''Draw a single light ray'''
        newPoint = self.currentPoint+self.length*self.directionVector.norm()
        self.currentPoint = newPoint
        self.ray.append(newPoint)
    
        #Define normal as normal vector to object
        #Using Snell's Law (numpy.arcsin((1/(1.5))*sin(vector.diff_angle(ray1,normal))))
    def newDirection(self,newDirection):
        '''Set a new direction for the ray'''
        self.directionVector = newDirection                   
        
        #Stop when encounters an object and then reset length to 10
    def newLength(self,newLength):
        '''Set a new length for the vector'''
        self.length=newLength
        
class beam():
    '''A Beam Class'''
    def __init__(self, centerRay, width):
        self.centerRay = centerRay
        self.currentPoint = centerRay.currentPoint
        self.beamDirection = centerRay.directionVector
        self.width = width
        self.color = centerRay.color
        self.beam = []
        #### The following line is added and the two lines defining the perpendiculars are removed
        self.find_perp()   #Find two rays perpendicular to centerRay
    
        self.draw_beam()
        
    ### The following method is added to create the two perpendicular rays    
    def find_perp(self):
        '''Find two vectors perpendicular to the center ray'''
        if centerRay.directionVector.y==0 and centerRay.directionVector.x==0:
            self.perp1=vec(1,0,0)
        else:
            self.perp1 = norm(vec(centerRay.directionVector.y,-centerRay.directionVector.x,0))
        self.perp2 = norm(vec(centerRay.directionVector.cross(self.perp1)))
    ### End changes
        
    def draw_beam(self):
        '''Draw a beam; lots of parallel rays'''
        for i in numpy.arange(0,self.width,.1): #CAN WE DEFINE A BEAM USING A FOR LOOP?
            for k in numpy.arange(0,2*pi+0.1,.1):
                self.newStart = centerRay.startPoint + i*(self.perp1*cos(k)+self.perp2*sin(k))
            
                beamRay = ray(self.newStart, self.beamDirection, self.color)
                        
                self.beam.append(beamRay)
        
#Do Class for Point Source
class pointSource():
    def __init__(self, position, color):
        self.position = position
        self.color = color
        self.pointSource = []
        self.source = sphere(pos=vec(centerRay.startPoint), radius=0.01, color=self.color)
        
        self.draw_pointSource()
    
    def draw_pointSource(self):
        '''Draw a point source'''
        self.source
        
        for i in numpy.arange(0,2*pi+0.1,.1):
            for k in numpy.arange(0,2*pi+0.1,.1):
                
                x = centerRay.length*(cos(k)*cos(i))
                y = centerRay.length*(cos(k)*sin(i))
                z = centerRay.length*(sin(k))
                
                pointSourceRay = ray(self.position, vec(x,y,z), self.color)
                
                self.pointSource.append(pointSourceRay)
                        
centerRay = ray(vec(0,0,0), vec(1,1,1), color.green)
beam1 = beam(centerRay, 4)
#pointSource1 = pointSource(centerRay.startPoint, color.blue)



In [ ]: