def initialize(self):
        #particles
        index = 0
        for i, button in enumerate(self.buttons):
            if button.selected:
                index = i
        if index == len(self.particle_options):
            mass = 0.1
            Charge = 0
            if float(self.txt_mass.text)>0:
                mass = float(self.txt_mass.text)
            if len(self.txt_charge.text)>0:
                charge = float(self.txt_charge.text)
            self.ball = physics.ball(mass, self.radius, self.ball.pos.x, self.ball.pos.y)
            self.ball.name = self.txt_name.text
            self.ball.charge = charge
        else:
            self.ball = self.particle_options[index]


        v = physics.vector3(self.v, 0)
        if len(self.txt_xsp.text)>0 and len(self.txt_ysp.text)>0:
            v = physics.vector3(float(self.txt_xsp.text), float(self.txt_ysp.text))
        self.ball.vel = v

        #fields
        self.E = physics.vector3(float(self.txt_E_x.text),float(self.txt_E_y.text), float(self.txt_E_z.text))
        self.B = physics.vector3(float(self.txt_B_x.text),float(self.txt_B_y.text), float(self.txt_B_z.text))

        self.trail = [self.ball.pos]
        self.draw_all()
Exemple #2
0
def draw_spring(canvas, start, end, width, line_width = 1, colour = "#222222"):
   ''' Draw a spring between two points, specified as vector objects using the physics module for anvil.
      canvas must be an anvil canvas in the parent Form.
      start, end must be vector3 objects, although the z-component is not used.
      width specifies the width of the zig-zags of the spring
      line_width and colour give the line style used for the spring
      colour must be a #rrggbb string in hexadecimal
      '''
   section = (end - start)/6 # Length of a section of the spring, a more useful measure of it's length
   direction = (end - start).norm() # Direction of the spring
   sideways = 0.5 * width * direction.phi_rotate(math.pi/2, vector3(0,0)) # Vector giving sideways offset to corners
   pencil = vector3(start.x, start.y) # Vector to keep track of drawing position
   canvas.stroke_style = colour
   canvas.line_width = line_width
   canvas.begin_path()
   canvas.move_to(pencil.x, pencil.y)
   pencil += section
   canvas.line_to(pencil.x, pencil.y) # Draw the first flat section
   pencil += 0.5 * section + sideways
   canvas.line_to(pencil.x, pencil.y) # Draw the first half diagonal
   pencil += section - 2 * sideways
   canvas.line_to(pencil.x, pencil.y) # Draw the next diagonal
   pencil += section + 2 * sideways
   canvas.line_to(pencil.x, pencil.y) # Draw the next diagonal
   pencil += section - 2 * sideways
   canvas.line_to(pencil.x, pencil.y) # Draw the next diagonal
   pencil += 0.5 * section + sideways
   canvas.line_to(pencil.x, pencil.y) # Draw the last half diagonal
   pencil += section
   canvas.line_to(pencil.x, pencil.y) # Draw the last flat section
   canvas.stroke()
Exemple #3
0
 def __init__(self, canvas, value=0, pos=[0,0], vert=1, label_args=["","none","",True], arrow_args=["","none","","",False]):  
   # Inheriting generic component initialisation procedure
   component.__init__(self, canvas, value, pos, vert, label_args, arrow_args)
   
   [x, y] = [20*self.pos[0], 20*self.pos[1]]
   self.dic_a2 = {"aboveright":[vector3(60,0,0,"source voltage"), x-10, y-17], "aboveleft":[vector3(-60,0,0,"source voltage"), x+50, y-17],
                  "belowright":[vector3(60,0,0,"source voltage"), x-10, y+15], "belowleft":[vector3(-60,0,0,"source voltage"), x+50, y+15],
                  "leftup":[vector3(0,-60,0,"source voltage"), x-15, y+50], "leftdown":[ vector3(0,60,0,"source voltage"), x-15, y-10],
                  "rightup":[vector3(0,-60,0,"source voltage"), x+15, y+50],"rightdown":[vector3(0,60,0,"source voltage"), x+15, y-10]}
Exemple #4
0
 def __init__(self, canvas, value=0, pos=[0,0], vert= 0, label_args=["","none","",True], arrow_args=["","none","","",False]):
   component.__init__(self, canvas, value, pos, vert, label_args, arrow_args)
   
   if value < 0:
     raise "Inductance must be positive."
   
   [x, y] = [20*self.pos[0], 20*self.pos[1]]
   self.dic_a2 = {"aboveright":[vector3(60,0,0,"inductance"), x, y-16], "aboveleft":[vector3(-60,0,0,"inductance"), x+60, y-16],
                  "belowright":[vector3(60,0,0,"inductance"), x, y+16], "belowleft":[vector3(-60,0,0,"inductance"), x+60, y+16],
                  "leftup":[vector3(0,-60,0,"inductance"), x-18, y+60], "leftdown":[ vector3(0,60,0,"inductance"), x-18, y],
                  "rightup":[vector3(0,-60,0,"inductance"), x+18, y+60],"rightdown":[vector3(0,60,0,"inductance"), x+18, y]}
Exemple #5
0
 def __init__(self, canvas, value=0, pos=[0,0], vert=1, label_args=["","none","",True], arrow_args=["","none","","",False]):  
   # Inheriting generic component initialisation procedure
   component.__init__(self, canvas, value, pos, vert, label_args, arrow_args)
   
   if self.value not in [0,1]: # 0 being open, 1 being closed
     raise "Switch's value property should be set to 0 (open) or 1 (closed)."
   
   [x, y] = [20*self.pos[0], 20*self.pos[1]]
   self.dic_a2 = {"aboveright":[vector3(60,0,0,"source voltage"), x-10, y-17], "aboveleft":[vector3(-60,0,0,"source voltage"), x+50, y-17],
                  "belowright":[vector3(60,0,0,"source voltage"), x-10, y+15], "belowleft":[vector3(-60,0,0,"source voltage"), x+50, y+15],
                  "leftup":[vector3(0,-60,0,"source voltage"), x-15, y+50], "leftdown":[ vector3(0,60,0,"source voltage"), x-15, y-10],
                  "rightup":[vector3(0,-60,0,"source voltage"), x+15, y+50],"rightdown":[vector3(0,60,0,"source voltage"), x+15, y-10]}
 def txt_change (self, **event_args):
     Ex  = self.txt_E_x.text
     Ey  = self.txt_E_y.text
     Ez  = self.txt_E_z.text
     Bx  = self.txt_B_x.text
     By  = self.txt_B_y.text
     Bz  = self.txt_B_z.text
     if len(Ex)>0 and len(Ey)>0 and len(Ez)>0:
         self.E = physics.vector3(float(self.txt_E_x.text),float(self.txt_E_y.text), float(self.txt_E_z.text))
     if len(Bx)>0 and len(By)>0 and len(Ez)>0:
         self.B = physics.vector3(float(self.txt_B_x.text),float(self.txt_B_y.text), float(self.txt_B_z.text))
     self.draw_all()
Exemple #7
0
 def __init__(self, canvas, value=0, pos=[0,0], vert= 0, label_args=["","none","",True], arrow_args=["","none","","",False]):
   # Inheriting generic component initialisation procedure
   component.__init__(self, canvas, value, pos, vert, label_args, arrow_args)
   
   if value < 0: # Resisor-specific code
     raise "Resistance must be positive."
   
   # Arrow positioning dictionary placed here to reduce workload in draw()
   [x, y] = [20*self.pos[0], 20*self.pos[1]]
   self.dic_a2 = {"aboveright":[vector3(60,0,0,"resistance"), x, y-16], "aboveleft":[vector3(-60,0,0,"resistance"), x+60, y-16],
                  "belowright":[vector3(60,0,0,"resistance"), x, y+16], "belowleft":[vector3(-60,0,0,"resistance"), x+60, y+16],
                  "leftup":[vector3(0,-60,0,"resistance"), x-18, y+60], "leftdown":[ vector3(0,60,0,"resistance"), x-18, y],
                  "rightup":[vector3(0,-60,0,"resistance"), x+18, y+60],"rightdown":[vector3(0,60,0,"resistance"), x+18, y]}  
Exemple #8
0
 def __init__(self, canvas, value=0, pos=[0,0], vert=1, label_args=["","none","",True], arrow_args=["","none","","",False]):  
   # Inheriting generic component initialisation procedure
   component.__init__(self, canvas, value, pos, vert, label_args, arrow_args)
   
   if value < 0:
     raise "Capacitance can't be negative."
   
   [x, y] = [20*self.pos[0], 20*self.pos[1]]
   
   self.dic_a2 = {"aboveright":[vector3(60,0,0,"capacitance"), x-20, y-20], "aboveleft":[vector3(-60,0,0,"capacitance"), x+40, y-20],
                  "belowright":[vector3(60,0,0,"capacitance"), x-20, y+18], "belowleft":[vector3(-60,0,0,"capacitance"), x+40, y+18],
                  "leftup":[vector3(0,-60,0,"capacitance"), x-18, y+45], "leftdown":[ vector3(0,60,0,"capacitance"), x-18, y],
                  "rightup":[vector3(0,-60,0,"capacitance"), x+18, y+45],"rightdown":[vector3(0,60,0,"capacitance"), x+18, y]}
    def __init__(self):
        # This sets up a variable for every component on this form.
        # For example, if we've drawn a button called "send_button", we can
        # refer to it as self.send_button:
        self.init_components()

        # Any code you write here will run when the form opens.
        #Uncomment as required.
        self.running = False
        self.reset = True
        self.first = True
        self.dt = self.timer.interval

        self.mousedown = False
        self.mouse = physics.vector3(0, 0, 0)

        self.t = 0
        self.paths = []
        #SET SCALE (pixels per m, or unit used in code)
        self.xu = 1
        self.L = 50
        self.D = 0.1

        self.v = 30

        #APPEND ALL PARAMETER BOXES
        self.param_boxes = []

        self.param_boxes.append(self.txt_ang)
        self.param_boxes.append(self.txt_spd)
    def init_ball(self):
        xsp = 0
        ysp = 0
        ang = round(float(self.txt_ang.text), 2) * math.pi / 180
        v = float(self.txt_spd.text)
        if v < 50:
            self.v = v
        if ang > 0:
            xsp = self.v * math.cos(ang)
            ysp = self.v * math.sin(ang)
        self.ball = physics.ball(1, 0.2)
        self.ball.pos = physics.vector3(self.ball.radius,
                                        self.ball.radius + self.floor_height)
        self.ball.vel = physics.vector3(xsp, ysp)

        self.path = 0
Exemple #11
0
    def __init__(self):
        # This sets up a variable for every component on this form.
        self.init_components()
        self.running = False
        self.first = True
        self.first_run = True
        self.reset = True
        self.mousedown = [False, False, False, False, False, False]
        self.mouse = physics.vector3(0, 0, 0)
        self.collided = False
        self.zoom = False
        # list of parameter inputs
        self.param_boxes = []

        self.param_boxes.append(self.txt_mass_1)
        self.param_boxes.append(self.txt_mass_2)
        self.param_boxes.append(self.txt_xsp_1)
        self.param_boxes.append(self.txt_xsp_2)
        self.param_boxes.append(self.txt_ysp_1)
        self.param_boxes.append(self.txt_ysp_2)
        self.param_boxes.append(self.radio_elastic)
        self.param_boxes.append(self.radio_inelastic)
        self.param_boxes.append(self.txt_x_1)
        self.param_boxes.append(self.txt_x_2)
        self.param_boxes.append(self.txt_y_1)
        self.param_boxes.append(self.txt_y_2)
        self.param_boxes.append(self.btn_velreset)

        self.starts = []
        self.collides = []
        self.ends = []
Exemple #12
0
    def __init__(self):
        # This sets up a variable for every component on this form.
        self.init_components()
        self.running = False
        self.first = True
        self.first_run = True
        self.reset = True
        self.mousedown = [False, False, False, False, False, False]
        self.mouse = physics.vector3(0, 0, 0)
        self.collided = False
        self.zoom = False
        #list of parameter inputs
        self.param_boxes = [
            self.txt_mass_1, self.txt_mass_2, self.txt_xsp_1, self.txt_xsp_2,
            self.txt_ysp_1
        ]
        self.param_boxes += [
            self.txt_ysp_2, self.radio_elastic, self.radio_inelastic,
            self.txt_x_1, self.txt_x_2, self.txt_y_1, self.txt_y_2,
            self.btn_velreset
        ]

        self.starts = []
        self.collides = []
        self.ends = []
Exemple #13
0
 def txt_change(self, **event_args):
     Ex = self.txt_E_x.text
     Ey = self.txt_E_y.text
     Ez = self.txt_E_z.text
     Bx = self.txt_B_x.text
     By = self.txt_B_y.text
     Bz = self.txt_B_z.text
     if len(Ex) > 0 and len(Ey) > 0 and len(Ez) > 0:
         self.E = physics.vector3(float(self.txt_E_x.text),
                                  float(self.txt_E_y.text),
                                  float(self.txt_E_z.text))
     if len(Bx) > 0 and len(By) > 0 and len(Ez) > 0:
         self.B = physics.vector3(float(self.txt_B_x.text),
                                  float(self.txt_B_y.text),
                                  float(self.txt_B_z.text))
     self.draw_all()
Exemple #14
0
 def btn_velreset_click (self, **event_args):
     if self.reset:
         self.reset = False
         for i in range(4):
             self.param_boxes[i+2].text = "0"
             self.balls[i].vel = physics.vector3(0,0)
         self.reset = True
    def init_ball(self):
        xsp = 0
        ysp = 0
        ang = round(float(self.txt_ang.text),2)*math.pi/180
        v =float(self.txt_spd.text)
        if v<50:
            self.v = v
        if ang>0:
            xsp = self.v*math.cos(ang)
            ysp = self.v*math.sin(ang)
        self.ball = physics.ball(1, 0.2)
        self.ball.pos = physics.vector3(self.ball.radius, self.ball.radius+self.floor_height)
        self.ball.vel = physics.vector3(xsp, ysp)


        self.path = 0
Exemple #16
0
 def btn_velreset_click(self, **event_args):
     if self.reset:
         self.reset = False
         for i in range(4):
             self.param_boxes[i + 2].text = "0"
             self.balls[i].vel = physics.vector3(0, 0)
         self.reset = True
    def __init__(self):
        # This sets up a variable for every component on this form.
        # For example, if we've drawn a button called "send_button", we can
        # refer to it as self.send_button:
        self.init_components()
        self.points = []
        self.pulses = []
        self.initalize()


        self.mouse = physics.vector3(0,0)
        self.moved = 0

        # Any code you write here will run when the form opens.
        #Uncomment as required.
        self.running= False
        self.reset = True
        self.dt = self.timer.interval
        self.first = True



        self.t = 0
        #SET SCALE (pixels per m, or unit used in code)


        #APPEND ALL PARAMETER BOXES
        self.param_boxes= []
Exemple #18
0
 def move_bug(self, bug):
     aim = (bug.pos.phi_rotate(-self.a, physics.vector3(0, 0, 0)) -
            bug.pos).norm()
     bug.vel = aim * self.v
     bug.pos = bug.pos + bug.vel * self.dt
     self.t += self.dt
     self.lbl_t.text = "t = {0}s".format(repr(self.t))
 def initial(self, canvas):
     draw.reset2(canvas, self.xu)
     draw.clear_canvas(canvas, "#fff")
     self.draw_polygon(canvas, self.N, self.L)
     self.bug.pos = physics.vector3(-self.L/2, self.d, 0)
     draw.reset2(canvas, self.xu)
     self.draw_bugs(canvas, self.bug.pos, "#2a2ac7")
     draw.reset2(canvas, self.xu)
Exemple #20
0
 def initial(self, canvas):
     draw.reset2(canvas, self.xu)
     draw.clear_canvas(canvas, "#fff")
     self.draw_polygon(canvas, self.N, self.L)
     self.bug.pos = physics.vector3(-self.L / 2, self.d, 0)
     draw.reset2(canvas, self.xu)
     self.draw_bugs(canvas, self.bug.pos, "#2a2ac7")
     draw.reset2(canvas, self.xu)
 def initalize(self):
     self.spd = 0.1
     self.wav = float(self.txt_wave.text)
     self.point1 = physics.point_source(radius = 0.01, speed= 0, wavelength = self.wav)
     self.point1.vel = physics.vector3(0.1,0)
     self.points = [self.point1]
     for point in self.points:
         point.mousedown = False
Exemple #22
0
def draw_arrow(canvas, start, vect, width = 1, colour = "#222222"):
   '''Draw a simple arrow from start along vect, with a fixed size (10px) arrowhead.'''
   canvas.stroke_style = colour
   canvas.line_width = width
   end = start + vect
   direction = vect.norm() # Arrow direction
   canvas.begin_path()
   canvas.move_to(start.x, start.y) # Draw the main line
   canvas.line_to(end.x, end.y)
   flick = direction.phi_rotate(-5*math.pi/6, vector3(0, 0)) # Direction of one of the arrow tip lines
   flick *= 8 # Length of the arrow end lines
   canvas.line_to(end.x + flick.x, end.y + flick.y) # Draw one line of the arrow tip
   flick = direction.phi_rotate(5*math.pi/6, vector3(0, 0)) # Direction of the other arrow tip line
   flick *= 8
   canvas.move_to(end.x, end.y)
   canvas.line_to(end.x + flick.x, end.y + flick.y) # Draw the other line of the arrow tip
   canvas.stroke()
Exemple #23
0
 def move_bug(self, bug):
     aim = (bug.pos.phi_rotate(-self.a, physics.vector3(0,0,0)) - bug.pos).norm()
     bug.vel = aim*self.v
     if self.counter % int(1/self.v) ==0:
         self.path.append(bug.pos)
     bug.pos = bug.pos + bug.vel*self.dt
     self.t += self.dt
     self.lbl_t.text = "t = {0}s".format(repr(self.t))
    def __init__(self):
        # This sets up a variable for every component on this form.
        # For example, if we've drawn a button called "send_button", we can
        # refer to it as self.send_button:
        self.init_components()

        # Any code you write here will run when the form opens.
        #Uncomment as required.
        self.running= False
        self.reset = True
        self.dt = self.timer.interval/(1e7)
        self.first = True
        self.zoom = False

        self.t = 0
        #SET SCALE (pixels per m, or unit used in code)
        self.xu =5
        self.old = 1
        self.paths = []
        self.cur_path = []
        self.trail= []
        self.mousedown = False
        self.arrowdown = False
        self.mouse = physics.vector3(0,0)

        electron = physics.ball(self.me, self.radius)
        electron.charge  = -self.e
        electron.name = "Electron"
        electron.E = physics.vector3(0, 1e3, 0)
        electron.B = physics.vector3(0, 0, 5e-3)

        positron = physics.ball(self.me, self.radius)
        positron.charge = self.e
        positron.name = "Positron"
        positron.E = physics.vector3(0, 1e3, 0)
        positron.B = physics.vector3(0, 0, 5e-3)

        alpha = physics.ball(4*self.mp, self.radius)
        alpha.charge = 2*self.e
        alpha.name = "Alpha Particle"
        alpha.E = physics.vector3(0, 1e5, 0)
        alpha.B = physics.vector3(0, 0, 5e-1)

        self.particle_options = [electron, positron, alpha]
        self.buttons = []



        for index, particle in enumerate(self.particle_options):
            button = RadioButton(text= particle.name, value = index, group_name = "radio_particles")
            self.buttons.append(button)
            if index == 0:
                button.selected = True
            self.grid_particles.add_component(button, row = "A", col_xs = 2*index + 1, width_xs = 2)

        self.custom = RadioButton(text = "Custom", value = len(self.particle_options), group_name = "radio_particles")
        self.grid_particles.add_component(self.custom, row ="A", col_xs = 2*len(self.particle_options) + 1, width_xs =2)
        self.buttons.append(self.custom)

        self.param_boxes = self.buttons + self.grid_custom.get_components() + self.grid_fields.get_components() + self.grid_vel.get_components()
Exemple #25
0
def component_arrows(self, canvas, vector, axis_vector = physics.vector3(0,1), 
                        x= 0, y=0, vector_from_start = "both", what_to_draw = "arrow", 
                        colour_parallel = "black",colour_perpendicular = "black"):
    """Draws components of vector parallel and perpendicular to axis_vector, in the x-y plane
    returns a list containing vector3 objects corresponding to the components parallel
    and perpendicular to axis_vector. Default it draws arrow components. Can 
    modifiy to dashed lines by setting what_to_draw = "dashed"
    """
    #Created by Michael C, April 2016
    
    #canvas(canvas) -  canvas to draw on
    #vector(vector3 object) - vector to split into components
    #axis_vector(vector3 object) - vector describing direction of axis components should be given parallel
    #                              or perpendicular to
    #x(float) - x position on canvas from which components should be drawn
    #y(float) - y position on canvas from which components should be drawn
    #vector_from_start(string) - which of the component vectors should be drawn from the given x,y - if not "both", other #will be drawn from end of this component
    #what_to_draw(string) - should these components be drawn as arrows or dashes
    #colour_parallel(string) 
    #colour_perpendicular(string) - colours of these two lines/arrows
    
    if vector.z != 0 or axis_vector.z != 0:
        raise
            
    #canvas.translate(x, y)
    
    #component_parallel to axis_vector:
    parallel_vector = (vector.dot(axis_vector)/(axis_vector.mag()**2)) * axis_vector
    parallel_vector.vector_type = vector.vector_type
    
    perpendicular_vector = vector - parallel_vector
    
    if vector_from_start == "both":
        parallel_vector_start_x = 0
        parallel_vector_start_y = 0
        perpendicular_vector_start_x = 0
        perpendicular_vector_start_y = 0
    elif vector_from_start == "parallel":
        parallel_vector_start_x = 0
        parallel_vector_start_y = 0
        perpendicular_vector_start_x = parallel_vector.x
        perpendicular_vector_start_y = parallel_vector.y
    else:
        parallel_vector_start_x = perpendicular_vector.x
        parallel_vector_start_y = perpendicular_vector.y
        perpendicular_vector_start_x = 0
        perpendicular_vector_start_y = 0
    
    
    if what_to_draw == "arrow":              
      new_arrow(canvas, parallel_vector, parallel_vector_start_x+x, parallel_vector_start_y+y)
      new_arrow(canvas, perpendicular_vector, perpendicular_vector_start_x+x, perpendicular_vector_start_y+y)
    elif what_to_draw == "dashed":      
      dashed_line(canvas, 10, parallel_vector.x + parallel_vector_start_x +x, parallel_vector.y + parallel_vector_start_y+y, x=parallel_vector_start_x+x, y= parallel_vector_start_y+y, colour = colour_parallel)
      dashed_line(canvas, 10, perpendicular_vector.x + perpendicular_vector_start_x+x, perpendicular_vector.y + perpendicular_vector_start_y+y, x=perpendicular_vector_start_x+x, y= perpendicular_vector_start_y+y, colour = colour_perpendicular)
    
    return [parallel_vector, perpendicular_vector]
 def initalize(self):
     self.spd = 0.1
     self.wav = float(self.txt_wave.text)
     self.point1 = physics.point_source(radius=0.01,
                                        speed=0,
                                        wavelength=self.wav)
     self.point1.vel = physics.vector3(0.1, 0)
     self.points = [self.point1]
     for point in self.points:
         point.mousedown = False
Exemple #27
0
def cart_arrows(self, canvas, vector, line_width, arrow_scale = 0.15, 
                colours = {'x':"#666666",'y':"#666666",'z':"#666666"}, x= 0, y=0 ):
        """Draw cartesian components of vector (physics.vector3 type) in xyz in approriate 
        colours. Default colour is isaac middle grey. Draws an axes in bottom left."""
        #Modified by Michael Conterio, March 2016
        
        #Draw axis reminder
        canvas.translate(50,50)
        canvas.rotate(math.pi/6 + math.pi)
        canvas.scale(10*line_width, 10*line_width)
        canvas.begin_path()
        #dashed axes
        self.dashed_line(canvas, 0.2, 1,0)
        canvas.line_width = 0.06
        canvas.stroke()
        canvas.scale(0.1/line_width, 0.1/line_width)
        canvas.rotate(-math.pi/6- math.pi)
        
        canvas.scale(10*line_width, 10*line_width)
        canvas.begin_path()
        self.dashed_line(canvas, 0.2,1,0)
        canvas.line_width = 0.06
        canvas.stroke()
        canvas.scale(0.1/line_width, 0.1/line_width)
        
        canvas.rotate(math.pi/2)
        canvas.scale(10*line_width, 10*line_width)
        canvas.begin_path()
        canvas.stroke_style = "#000000"
        self.dashed_line(canvas, 0.2,1,0)
        canvas.line_width = 0.06
        canvas.stroke()
        canvas.scale(0.1/line_width, 0.1/line_width)
        canvas.rotate(-math.pi/2)
        
        canvas.translate(-50,-50)
        
        #z component
        canvas.translate(x, y)
        canvas.rotate(math.pi/6 + math.pi)
        #component arrow
        z_vector = physics.vector3(1,0,0,vector.vector_type)
        self.arrow(canvas, vector.z*vector3(1,0,0,vector.vector_type),0,0)
        canvas.rotate(-math.pi/6- math.pi)
    
        #x component
        self.arrow(canvas, vector.x*vector3(1,0,0,vector.vector_type),0,0)
    
        #y component
        canvas.rotate(math.pi/2)
        self.arrow(canvas, vector.y*vector3(1,0,0,vector.vector_type),0,0)
        canvas.rotate(-math.pi/2)
    
        canvas.translate(-x,-y)
    def init_ball(self):
        xsp = 0
        ysp = 0
        self.v = 0
        ang = round(float(self.txt_ang.text))*math.pi/180
        v = float(self.txt_v.text)
        if 20>=v>0:
            self.v = v
        if ang>0:
            xsp = self.v*math.cos(ang)
            ysp = self.v*math.sin(ang)
        self.ball = physics.ball(1, 0.1)
        self.ball.pos = physics.vector3(self.ball.radius, self.ball.radius+self.floor_height)
        self.ball.vel = physics.vector3(xsp, ysp)

        self.d = self.v**2/self.g.mag()
        d =self.d
        if d>0:
            self.xu  = self.cw/(d+3*self.ball.radius)

        self.path = 0
Exemple #29
0
 def set_fill_colour(self, colour = ""):
   """Sets fill colour of self.canvas to specified colour, or vector type colour as default.
   Can be called as simply set_fill_colour() for defaults.
   Colour as 6-digit hex string of form "#aabbcc".    """
   if colour != "":
     self.canvas.fill_style = colour
   else:
     # Must call new_arrow to access colour_dict
     # Creates dummy arrow, while preserving line width
     previous_line_width = self.canvas.line_width
     vector_type = self.dic_a2.values()[0][0].vector_type # Takes it from first dict entry
     new_arrow(self.canvas, vector3(1,0,0,vector_type), -1000, -1000)
     self.canvas.line_width = previous_line_width
Exemple #30
0
    def init_ball(self):
        xsp = 0
        ysp = 0
        self.v = 0
        ang = round(float(self.txt_ang.text)) * math.pi / 180
        v = float(self.txt_v.text)
        if 20 >= v > 0:
            self.v = v
        if ang > 0:
            xsp = self.v * math.cos(ang)
            ysp = self.v * math.sin(ang)
        self.ball = physics.ball(1, 0.1)
        self.ball.pos = physics.vector3(self.ball.radius,
                                        self.ball.radius + self.floor_height)
        self.ball.vel = physics.vector3(xsp, ysp)

        self.d = self.v**2 / self.g.mag()
        d = self.d
        if d > 0:
            self.xu = self.cw / (d + 3 * self.ball.radius)

        self.path = 0
Exemple #31
0
 def set_origin(self, origin = "default"):
    '''Sets the origin and the scaling factors for drawing the graph.
       The origin is a vector object which is used in drawing the graph to determine where the crossing 
       point of the axes, (0, 0) is on the canvas.
       The scaling factors are floats giving the number of pixels per unit on the x, y axes.
       '''
    if type(origin) is not vector3 and origin is not "default": # Need a vector
       raise TypeError("the origin must be set to a vector coordinate")
    elif origin == "default": # Check whether we are in default origin mode
       # Now set the scaling factors, as defined above, the 0.0s are to avoid integer division
       if self.x_range[0] >= 0: # If the axis is 0 -> x max
          self.scale_x = (self.cw - 2 * self.gap + 0.0) / self.x_range[1]
       elif self.x_range[1] <= 0: # If the axis is x min -> 0
          self.scale_x = (self.cw - 2 * self.gap + 0.0) / abs(self.x_range[0])
       else: # If the axis is x min -> x max
          self.scale_x = (self.cw - 2 * self.gap + 0.0) / (self.x_range[1] - self.x_range[0])
       if self.y_range[0] >= 0: # If the axis is 0 -> y max
          self.scale_y = (self.ch - (2 * self.gap) + 0.0) / self.y_range[1]
       elif self.y_range[1] <= 0: # If the axis is y min -> 0
          self.scale_y = (self.ch - (2 * self.gap) + 0.0) / abs(self.y_range[0])
       else: # If the axis is y min -> y max
          self.scale_y = (self.ch - (2 * self.gap) + 0.0) / (self.y_range[1] - self.y_range[0])
       # Note the self.gaps here are the gap between the axis ends and the canvas edge
       if self.x_range[0] >= 0 and self.y_range[0] >= 0:
          self.origin = vector3(self.gap, self.gap) # Bottom left corner if only top right quadrant needed
       elif self.x_range[0] >= 0 and self.y_range[1] <= 0:
          self.origin = vector3(self.gap, self.ch - self.gap) # Top left corner if only bottom right quadrant needed
       elif self.x_range[1] <= 0 and self.y_range[0] >= 0:
          self.origin = vector3(self.cw - self.gap, self.gap) # Bottom right corner if only top left quadrant needed
       elif self.x_range[1] <= 0 and self.y_range[1] <= 0:
          self.origin = vector3(self.cw - self.gap, self.ch - self.gap) # Top right corner if only bottom left quadrant needed
       elif self.x_range[0] >= 0: # If only the right half is needed
          self.origin = vector3(self.gap, -1 * self.y_range[0] * self.scale_y + self.gap)
       elif self.x_range[1] <= 0: # If only the left half is needed
          self.origin = vector3(self.cw - self.gap, -1 * self.y_range[0] * self.scale_y + self.gap)
       elif self.y_range[0] >= 0: # If only the top half is needed
          self.origin = vector3(-1 * self.x_range[0] * self.scale_x + self.gap, self.gap)
       elif self.y_range[1] <= 0: # If only the bottom half is needed
          self.origin = vector3(-1 * self.x_range[0] * self.scale_x + self.gap, self.cw - self.gap)
       else: # Otherwise all four quadrants are needed
          self.origin = vector3(-1 * self.x_range[0] * self.scale_x + self.gap, -1 * self.y_range[0] * self.scale_y + self.gap)
    else:
       self.origin = origin # If they have specified an origin
    def canvas_mouse_move (self, x, y, **event_args):
        # This method is called when the mouse cursor moves over this component
        #record mouse pos
        self.mouse.x = x/self.xu
        self.mouse.y = (self.ch-y)/self.xu

        #change text box value based on where mouse is
        if self.mousedown:
            x = ((self.mouse - self.ball.pos).x)
            y = ((self.mouse - self.ball.pos).y)
            ang = math.atan(y/x)
            if 0<=ang<=math.pi/2:
                self.txt_ang.text = "{0}".format(int(ang*180/math.pi))
                self.ball.vel = physics.vector3(self.v*math.cos(ang), self.v*math.sin(ang))
Exemple #33
0
 def draw_current(self, direction = None):
   # Calibrated for resistor display but can be called for any component object
   # Currently only supports left and down arrows
   olw = self.canvas.line_width
   if direction == None: # tries to decide for itself
     if self.vert == 0:
       direction = "left"
     else:
       direction = "down"
       
   if direction == "left": # Comes left out of resistor node 1
     vect = vector3(-30, 0, 0, "acceleration")
     new_arrow(self.canvas, vect, 20*self.node1()[0], 20*self.node1()[1])
     self.canvas.fill_style = "#4c7fbe"
     mt = self.canvas.measure_text(self.i)
     
     # Preventing overlap with label on resistor
     if self.label_args[3] and self.label_args[1] == "above":
       mt_r = self.canvas.measure_text(self.label_args[0])
     elif self.arrow_args[4] and self.arrow_args[1] == "above":
       mt_r = self.canvas.measure_text(self.arrow_args[0])
     else:
       mt_r = -1000
     overlap = mt_r/2 + mt/2 - 43
     overlap = overlap * (overlap > 0)
     
     self.canvas.fill_text(self.i, 20*self.node1()[0]-15-mt/2-overlap, 20*self.node1()[1]-20)
     
   elif direction == "down":
     vect = vector3(0, 30, 0, "acceleration")
     new_arrow(self.canvas, vect, 20*self.node2()[0], 20*self.node2()[1])
     self.canvas.fill_style = "#4c7fbe"
     mt = self.canvas.measure_text(self.i)
     self.canvas.fill_text(self.i, 20*self.node2()[0]+10, 20*self.node2()[1]+19)
     
   self.canvas.line_width = olw  
Exemple #34
0
    def initialize(self):
        #particles
        index = 0
        for i, button in enumerate(self.buttons):
            if button.selected:
                index = i
        if index == len(self.particle_options):
            mass = 0.1
            Charge = 0
            if float(self.txt_mass.text) > 0:
                mass = float(self.txt_mass.text)
            if len(self.txt_charge.text) > 0:
                charge = float(self.txt_charge.text)
            self.ball = physics.ball(mass, self.radius, self.ball.pos.x,
                                     self.ball.pos.y)
            self.ball.name = self.txt_name.text
            self.ball.charge = charge
        else:
            self.ball = self.particle_options[index]

        v = physics.vector3(self.v, 0)
        if len(self.txt_xsp.text) > 0 and len(self.txt_ysp.text) > 0:
            v = physics.vector3(float(self.txt_xsp.text),
                                float(self.txt_ysp.text))
        self.ball.vel = v

        #fields
        self.E = physics.vector3(float(self.txt_E_x.text),
                                 float(self.txt_E_y.text),
                                 float(self.txt_E_z.text))
        self.B = physics.vector3(float(self.txt_B_x.text),
                                 float(self.txt_B_y.text),
                                 float(self.txt_B_z.text))

        self.trail = [self.ball.pos]
        self.draw_all()
Exemple #35
0
    def canvas_mouse_move(self, x, y, **event_args):
        # This method is called when the mouse cursor moves over this component
        #record mouse pos
        self.mouse.x = x / self.xu
        self.mouse.y = (self.ch - y) / self.xu

        #change text box value based on where mouse is
        if self.mousedown:
            x = ((self.mouse - self.ball.pos).x)
            y = ((self.mouse - self.ball.pos).y)
            ang = math.atan(y / x)
            if 0 <= ang <= math.pi / 2:
                self.txt_ang.text = "{0}".format(int(ang * 180 / math.pi))
                self.ball.vel = physics.vector3(self.v * math.cos(ang),
                                                self.v * math.sin(ang))
Exemple #36
0
 def set_data(self, xvals, yvals, name = "graph_1"):
    '''Sets the internal data set of the graph from two lists of x values and y values.
       Will raise errors if the two are not both lists of the same length.
       '''
    # Check for input errors
    try:
       if len(xvals) is not len(yvals):
          raise ValueError("The x and y datasets must be the same length")
    except TypeError:
       raise TypeError("The x and y datasets must be lists. If you only want one point, use [point]")
    # Change the given two lists into a single vector3 list
    data = list(range(0, len(xvals))) # Make data a list of equivalent length
    for i in list(range(0, len(xvals))):
       data[i] = vector3(xvals[i], yvals[i])
    if name not in self.data: # If this is a new dataset
       self.datasets += 1
       self.set_line_colour("new", name) # Set the plot parameters
       self.set_plot_type("line", name)
       self.set_line_weight(1, name)
    self.data[name] = sorted(data, key=lambda a: a.x)
Exemple #37
0
    def initial(self, canvas):
        draw.reset2(canvas, self.xu)
        draw.clear_canvas(canvas, "#fff")

        self.N  =  self.slid_N.value
        self.L = self.slid_L.value
        self.v = self.slid_v.value

        self.draw_polygon(canvas, self.N, self.L)
        if self.reset:
            self.bug.pos = physics.vector3(-self.L/2, self.d, 0)
            self.path  = [self.bug.pos, self.bug.pos]
        draw.reset2(canvas, self.xu)
        self.draw_bugs(canvas, self.bug.pos, "#2a2ac7")
        # for i in range(len(self.path)-1):
        #     canvas.begin_path()
        #     canvas.move_to(self.path[i].x, self.path[i].y)
        #     canvas.line_to(self.path[i+1].x, self.path[i+1].y)
        #     canvas.stroke()

        draw.reset2(canvas, self.xu)
 def move_bug(self, bug):
     aim = (bug.pos.phi_rotate(-self.a, physics.vector3(0,0,0)) - bug.pos).norm()
     bug.vel = aim*self.v
     bug.pos = bug.pos + bug.vel*self.dt
     self.t += self.dt
     self.lbl_t.text = "t = {0}s".format(repr(self.t))
Exemple #39
0
    def __init__(self):
        # This sets up a variable for every component on this form.
        # For example, if we've drawn a button called "send_button", we can
        # refer to it as self.send_button:
        self.init_components()

        # Any code you write here will run when the form opens.
        #Uncomment as required.
        self.running = False
        self.reset = True
        self.dt = self.timer.interval / (1e7)
        self.first = True
        self.zoom = False

        self.t = 0
        #SET SCALE (pixels per m, or unit used in code)
        self.xu = 5
        self.old = 1
        self.paths = []
        self.cur_path = []
        self.trail = []
        self.mousedown = False
        self.arrowdown = False
        self.mouse = physics.vector3(0, 0)

        electron = physics.ball(self.me, self.radius)
        electron.charge = -self.e
        electron.name = "Electron"
        electron.E = physics.vector3(0, 1e3, 0)
        electron.B = physics.vector3(0, 0, 5e-3)

        positron = physics.ball(self.me, self.radius)
        positron.charge = self.e
        positron.name = "Positron"
        positron.E = physics.vector3(0, 1e3, 0)
        positron.B = physics.vector3(0, 0, 5e-3)

        alpha = physics.ball(4 * self.mp, self.radius)
        alpha.charge = 2 * self.e
        alpha.name = "Alpha Particle"
        alpha.E = physics.vector3(0, 1e5, 0)
        alpha.B = physics.vector3(0, 0, 5e-1)

        self.particle_options = [electron, positron, alpha]
        self.buttons = []

        for index, particle in enumerate(self.particle_options):
            button = RadioButton(text=particle.name,
                                 value=index,
                                 group_name="radio_particles")
            self.buttons.append(button)
            if index == 0:
                button.selected = True
            self.grid_particles.add_component(button,
                                              row="A",
                                              col_xs=2 * index + 1,
                                              width_xs=2)

        self.custom = RadioButton(text="Custom",
                                  value=len(self.particle_options),
                                  group_name="radio_particles")
        self.grid_particles.add_component(
            self.custom,
            row="A",
            col_xs=2 * len(self.particle_options) + 1,
            width_xs=2)
        self.buttons.append(self.custom)

        self.param_boxes = self.buttons + self.grid_custom.get_components(
        ) + self.grid_fields.get_components() + self.grid_vel.get_components()
 def init_pos(self,points):
     self.points[0].pos = physics.vector3(0.05, self.ch/(2.0*self.xu))
 def init_pos(self, points):
     self.points[0].pos = physics.vector3(0.05, self.ch / (2.0 * self.xu))
Exemple #42
0
def cart_arrows(self,
                canvas,
                vector,
                line_width,
                arrow_scale=0.15,
                colours={
                    'x': "#666666",
                    'y': "#666666",
                    'z': "#666666"
                },
                x=0,
                y=0):
    """Draw cartesian components of vector (physics.vector3 type) in xyz in approriate 
        colours. Default colour is isaac middle grey. Draws an axes in bottom left."""
    #Modified by Michael Conterio, March 2016

    #Draw axis reminder
    canvas.translate(50, 50)
    canvas.rotate(math.pi / 6 + math.pi)
    canvas.scale(10 * line_width, 10 * line_width)
    canvas.begin_path()
    #dashed axes
    self.dashed_line(canvas, 0.2, 1, 0)
    canvas.line_width = 0.06
    canvas.stroke()
    canvas.scale(0.1 / line_width, 0.1 / line_width)
    canvas.rotate(-math.pi / 6 - math.pi)

    canvas.scale(10 * line_width, 10 * line_width)
    canvas.begin_path()
    self.dashed_line(canvas, 0.2, 1, 0)
    canvas.line_width = 0.06
    canvas.stroke()
    canvas.scale(0.1 / line_width, 0.1 / line_width)

    canvas.rotate(math.pi / 2)
    canvas.scale(10 * line_width, 10 * line_width)
    canvas.begin_path()
    canvas.stroke_style = "#000000"
    self.dashed_line(canvas, 0.2, 1, 0)
    canvas.line_width = 0.06
    canvas.stroke()
    canvas.scale(0.1 / line_width, 0.1 / line_width)
    canvas.rotate(-math.pi / 2)

    canvas.translate(-50, -50)

    #z component
    canvas.translate(x, y)
    canvas.rotate(math.pi / 6 + math.pi)
    #component arrow
    z_vector = physics.vector3(1, 0, 0, vector.vector_type)
    self.arrow(canvas, vector.z * vector3(1, 0, 0, vector.vector_type), 0, 0)
    canvas.rotate(-math.pi / 6 - math.pi)

    #x component
    self.arrow(canvas, vector.x * vector3(1, 0, 0, vector.vector_type), 0, 0)

    #y component
    canvas.rotate(math.pi / 2)
    self.arrow(canvas, vector.y * vector3(1, 0, 0, vector.vector_type), 0, 0)
    canvas.rotate(-math.pi / 2)

    canvas.translate(-x, -y)
class Form1(Form1Template):
    #acceleration vector
    g = physics.vector3(0, -9.81)
    floor_height = 0.2
    arrow_scale = 0.1
    line_width = 0.05

    def txt_change(self, **event_args):
        self.init_ball()

    def canvas_mouse_move(self, x, y, **event_args):
        # This method is called when the mouse cursor moves over this component
        #record mouse pos
        self.mouse.x = x / self.xu
        self.mouse.y = (self.ch - y) / self.xu

        #change text box value based on where mouse is
        if self.mousedown:
            x = ((self.mouse - self.ball.pos).x)
            y = ((self.mouse - self.ball.pos).y)
            ang = math.atan(y / x)
            if 0 <= ang <= math.pi / 2:
                self.txt_ang.text = "{0}".format(int(ang * 180 / math.pi))
                self.ball.vel = physics.vector3(self.v * math.cos(ang),
                                                self.v * math.sin(ang))

    def canvas_mouse_up(self, x, y, button, **event_args):
        # This method is called when a mouse button is released on this component
        self.mousedown = False

    def canvas_mouse_down(self, x, y, button, **event_args):
        # This method is called when a mouse button is pressed on this component
        self.mouse.x = x / self.xu
        self.mouse.y = (self.ch - y) / self.xu

        #arrow detect
        if (0.9 * self.arrow_scale * self.ball.vel + self.ball.pos -
                self.mouse).mag() <= self.ball.radius * 3 and self.reset:
            self.mousedown = True

    def btn_path_click(self, **event_args):
        self.paths = []

    def btn_run_click(self, **event_args):
        # This method is called when the button is clicked
        if not self.running:
            if self.reset:
                self.init_ball()
            self.running = True
            self.reset = False
            self.btn_run.text = "Pause"

        else:
            self.running = False
            self.btn_run.text = "Run"

        self.cur_path = []
        self.paths.append(self.cur_path)
        #make parameters only editable while reset
        for box in self.param_boxes:
            box.enabled = self.reset

    def btn_reset_click(self, **event_args):
        #This method is called when the button is clicked
        self.running = False
        self.init_ball()
        #self.draw_floor()
        self.reset = True
        self.btn_run.enabled = True
        self.btn_run.text = "Run"
        self.t = 0
        #make parameters only editable while reset
        for box in self.param_boxes:
            box.enabled = self.reset

    def timer_tick(self, **event_args):
        # This method is called Every [interval] seconds
        dt = self.dt
        canvas = self.canvas
        self.cw = canvas.get_width()
        self.ch = canvas.get_height()
        cw = self.cw
        ch = self.ch
        xu = self.xu

        if self.first:
            self.init_ball()
            self.xu = cw / (self.L + 2)
            canvas.height = "{0}".format(10 * self.xu * (self.v**2) /
                                         (2 * 9.81))
            self.first = False

        if self.running:
            if self.ball.pos.y - self.ball.radius - self.floor_height <= 0.001 and self.t > 0:
                #to show exact solution, uncomment below
                # if abs(self.ball.pos.x - (self.L + self.ball.radius)) <= self.D:
                #     self.t = 0
                #     self.running = False
                #     self.btn_run.text = "Run"
                #     self.btn_run.enabled = False
                self.ball.pos.y = self.ball.radius + self.floor_height
                #restitution
                self.ball.vel.y *= -0.7
                #friction
                self.ball.vel.x *= 0.95

            if self.running:
                self.ball.move(dt)
                if int(self.t / self.dt) % 3 == 0:
                    self.cur_path.append(self.ball.pos)
                self.ball.vel = self.ball.vel + self.g * dt
                self.path += dt * self.ball.vel.mag()
                self.t += dt

            self.lbl_path.text = "Path = {0:.2f}m".format(self.path)
        self.draw_all()

    def draw_all(self):
        canvas = self.canvas
        cw = self.cw
        ch = self.ch
        xu = self.xu
        ball = self.ball

        draw.reset2(canvas, xu)
        draw.clear_canvas(canvas, "#7ec0ee")

        #floor
        canvas.fill_style = "#1f8107"
        canvas.fill_rect(0, 0, cw / self.xu, self.floor_height)

        #pole
        canvas.fill_style = "rgb(111, 62, 55)"
        canvas.fill_rect(self.L + self.ball.radius, self.floor_height, self.D,
                         3)
        canvas.translate(self.L + self.ball.radius - 0.05,
                         3 + self.floor_height)
        canvas.rotate(-math.pi / 2)
        draw.polygon(canvas, 3, self.D * 6)
        canvas.fill_style = "rgb(227, 81, 61)"
        canvas.fill()

        draw.reset2(canvas, xu)

        #ball
        draw.circle(canvas, ball.radius, ball.pos.x, ball.pos.y)
        canvas.fill_style = "#fff"
        canvas.fill()

        #arrow
        if not self.running:
            ball = self.ball
            #velocity vector
            canvas.translate(ball.pos.x, ball.pos.y)
            if ball.vel.y > 0:
                canvas.rotate(ball.vel.phi())
            else:
                canvas.rotate(-ball.vel.phi())
            draw.arrow(canvas,
                       ball.vel.mag() * self.arrow_scale, 4 * self.line_width)
            canvas.fill_style = "#49902a"
            canvas.fill()
            draw.reset2(canvas, xu)

        #dashes
        canvas.begin_path()
        if not self.running:
            for path in self.paths:
                if len(path) > 2:
                    for i in range(len(path) - 1):
                        canvas.move_to(path[i].x, path[i].y)
                        diff = path[i + 1] - path[i]
                        new = path[i] + diff * 0.8
                        canvas.line_to(new.x, new.y)

            canvas.line_width = self.line_width
            canvas.stroke()

    def init_ball(self):
        xsp = 0
        ysp = 0
        ang = round(float(self.txt_ang.text), 2) * math.pi / 180
        v = float(self.txt_spd.text)
        if v < 50:
            self.v = v
        if ang > 0:
            xsp = self.v * math.cos(ang)
            ysp = self.v * math.sin(ang)
        self.ball = physics.ball(1, 0.2)
        self.ball.pos = physics.vector3(self.ball.radius,
                                        self.ball.radius + self.floor_height)
        self.ball.vel = physics.vector3(xsp, ysp)

        self.path = 0

    def __init__(self):
        # This sets up a variable for every component on this form.
        # For example, if we've drawn a button called "send_button", we can
        # refer to it as self.send_button:
        self.init_components()

        # Any code you write here will run when the form opens.
        #Uncomment as required.
        self.running = False
        self.reset = True
        self.first = True
        self.dt = self.timer.interval

        self.mousedown = False
        self.mouse = physics.vector3(0, 0, 0)

        self.t = 0
        self.paths = []
        #SET SCALE (pixels per m, or unit used in code)
        self.xu = 1
        self.L = 50
        self.D = 0.1

        self.v = 30

        #APPEND ALL PARAMETER BOXES
        self.param_boxes = []

        self.param_boxes.append(self.txt_ang)
        self.param_boxes.append(self.txt_spd)
Exemple #44
0
def component_arrows(self,
                     canvas,
                     vector,
                     axis_vector=physics.vector3(0, 1),
                     x=0,
                     y=0,
                     vector_from_start="both",
                     what_to_draw="arrow",
                     colour_parallel="black",
                     colour_perpendicular="black"):
    """Draws components of vector parallel and perpendicular to axis_vector, in the x-y plane
    returns a list containing vector3 objects corresponding to the components parallel
    and perpendicular to axis_vector. Default it draws arrow components. Can 
    modifiy to dashed lines by setting what_to_draw = "dashed"
    """
    #Created by Michael C, April 2016

    #canvas(canvas) -  canvas to draw on
    #vector(vector3 object) - vector to split into components
    #axis_vector(vector3 object) - vector describing direction of axis components should be given parallel
    #                              or perpendicular to
    #x(float) - x position on canvas from which components should be drawn
    #y(float) - y position on canvas from which components should be drawn
    #vector_from_start(string) - which of the component vectors should be drawn from the given x,y - if not "both", other #will be drawn from end of this component
    #what_to_draw(string) - should these components be drawn as arrows or dashes
    #colour_parallel(string)
    #colour_perpendicular(string) - colours of these two lines/arrows

    if vector.z != 0 or axis_vector.z != 0:
        raise

    #canvas.translate(x, y)

    #component_parallel to axis_vector:
    parallel_vector = (vector.dot(axis_vector) /
                       (axis_vector.mag()**2)) * axis_vector
    parallel_vector.vector_type = vector.vector_type

    perpendicular_vector = vector - parallel_vector

    if vector_from_start == "both":
        parallel_vector_start_x = 0
        parallel_vector_start_y = 0
        perpendicular_vector_start_x = 0
        perpendicular_vector_start_y = 0
    elif vector_from_start == "parallel":
        parallel_vector_start_x = 0
        parallel_vector_start_y = 0
        perpendicular_vector_start_x = parallel_vector.x
        perpendicular_vector_start_y = parallel_vector.y
    else:
        parallel_vector_start_x = perpendicular_vector.x
        parallel_vector_start_y = perpendicular_vector.y
        perpendicular_vector_start_x = 0
        perpendicular_vector_start_y = 0

    if what_to_draw == "arrow":
        new_arrow(canvas, parallel_vector, parallel_vector_start_x + x,
                  parallel_vector_start_y + y)
        new_arrow(canvas, perpendicular_vector,
                  perpendicular_vector_start_x + x,
                  perpendicular_vector_start_y + y)
    elif what_to_draw == "dashed":
        dashed_line(canvas,
                    10,
                    parallel_vector.x + parallel_vector_start_x + x,
                    parallel_vector.y + parallel_vector_start_y + y,
                    x=parallel_vector_start_x + x,
                    y=parallel_vector_start_y + y,
                    colour=colour_parallel)
        dashed_line(canvas,
                    10,
                    perpendicular_vector.x + perpendicular_vector_start_x + x,
                    perpendicular_vector.y + perpendicular_vector_start_y + y,
                    x=perpendicular_vector_start_x + x,
                    y=perpendicular_vector_start_y + y,
                    colour=colour_perpendicular)

    return [parallel_vector, perpendicular_vector]
Exemple #45
0
class Form1(Form1Template):
    #acceleration vector
    g = physics.vector3(0, -9.81)
    floor_height = 0.05
    arrow_scale = 0.05
    linewidth = 0.01

    def txt_change(self, **event_args):
        self.init_ball()

    def canvas_mouse_move(self, x, y, **event_args):
        # This method is called when the mouse cursor moves over this component
        #record mouse pos
        self.mouse.x = x / self.xu
        self.mouse.y = (self.ch - y) / self.xu

        #change text box value based on where mouse is
        if self.mousedown:
            x = ((self.mouse - self.ball.pos).x)
            y = ((self.mouse - self.ball.pos).y)
            ang = math.atan(y / x)
            if 0 <= ang <= math.pi / 2:
                self.txt_ang.text = "{0}".format(int(ang * 180 / math.pi))
                self.ball.vel = physics.vector3(self.v * math.cos(ang),
                                                self.v * math.sin(ang))

    def canvas_mouse_up(self, x, y, button, **event_args):
        # This method is called when a mouse button is released on this component
        self.mousedown = False

    def canvas_mouse_down(self, x, y, button, **event_args):
        # This method is called when a mouse button is pressed on this component
        self.mouse.x = x / self.xu
        self.mouse.y = (self.ch - y) / self.xu

        #arrow detect
        if (0.9 * self.arrow_scale * self.ball.vel + self.ball.pos -
                self.mouse).mag() <= self.ball.radius / 3 and self.reset:
            self.mousedown = True

    def btn_path_click(self, **event_args):
        self.paths = []

    def btn_run_click(self, **event_args):
        # This method is called when the button is clicked
        if not self.running:
            if self.reset:
                self.init_ball()
            self.running = True
            self.reset = False
            self.btn_run.text = "Pause"

        else:
            self.running = False
            self.btn_run.text = "Run"

        self.cur_path = []
        self.paths.append(self.cur_path)
        #make parameters only editable while reset
        for box in self.param_boxes:
            box.enabled = self.reset

    def btn_reset_click(self, **event_args):
        #This method is called when the button is clicked
        self.running = False
        self.init_ball()
        #self.draw_floor()
        self.reset = True
        self.btn_run.enabled = True
        self.btn_run.text = "Run"
        self.t = 0
        #make parameters only editable while reset
        for box in self.param_boxes:
            box.enabled = self.reset

    def timer_tick(self, **event_args):
        # This method is called Every [interval] seconds
        dt = self.dt
        canvas = self.canvas
        self.cw = canvas.get_width()
        self.ch = canvas.get_height()
        cw = self.cw
        ch = self.ch
        xu = self.xu

        if self.first:
            self.init_ball()
            d = self.v**2 / self.g.mag()
            if d > 0:
                self.xu = cw / (d + 4 * self.ball.radius)
            canvas.height = "{0}".format(round(self.xu * (d / 2)))
            self.first = False

        if self.running:
            if self.ball.pos.y - self.ball.radius - self.floor_height <= 0.001 and self.t > 0:
                self.ball.pos.y = self.ball.radius + self.floor_height
                self.t = 0
                self.running = False
                self.btn_run.text = "Run"
                self.btn_run.enabled = False

            else:
                self.ball.move(dt)
                if int(self.t / self.dt) % 3 == 0:
                    self.cur_path.append(self.ball.pos)
                self.ball.vel = self.ball.vel + self.g * dt
                self.path += dt * self.ball.vel.mag()
                self.t += dt

            self.lbl_path.text = "Path = {0:.2f}m".format(self.path)
        self.draw_all()

    def draw_all(self):
        canvas = self.canvas
        self.cw = canvas.get_width()
        self.ch = canvas.get_height()
        cw = self.cw
        ch = self.ch
        xu = self.xu
        ball = self.ball

        draw.reset2(canvas, xu)
        draw.clear_canvas(canvas, "#fff")

        canvas.fill_style = "#000"
        canvas.fill_rect(0, 0, cw, self.floor_height)

        draw.circle(canvas, ball.radius, ball.pos.x, ball.pos.y)
        canvas.fill_style = "#3683f3"
        canvas.fill()

        #arrow
        if not self.running:
            ball = self.ball
            #velocity vector
            canvas.translate(ball.pos.x, ball.pos.y)
            if ball.vel.y > 0:
                canvas.rotate(ball.vel.phi())
            else:
                canvas.rotate(-ball.vel.phi())
            draw.arrow(canvas,
                       ball.vel.mag() * self.arrow_scale, 4 * self.linewidth)
            canvas.fill_style = "#49902a"
            canvas.fill()
            draw.reset2(canvas, xu)

        #dashes
        if not self.running:
            draw.paths(canvas, self.paths, self.linewidth, "#000")

    def init_ball(self):
        xsp = 0
        ysp = 0
        self.v = 0
        ang = round(float(self.txt_ang.text)) * math.pi / 180
        v = float(self.txt_v.text)
        if 20 >= v > 0:
            self.v = v
        if ang > 0:
            xsp = self.v * math.cos(ang)
            ysp = self.v * math.sin(ang)
        self.ball = physics.ball(1, 0.1)
        self.ball.pos = physics.vector3(self.ball.radius,
                                        self.ball.radius + self.floor_height)
        self.ball.vel = physics.vector3(xsp, ysp)

        self.d = self.v**2 / self.g.mag()
        d = self.d
        if d > 0:
            self.xu = self.cw / (d + 3 * self.ball.radius)

        self.path = 0

    def __init__(self):
        # This sets up a variable for every component on this form.
        # For example, if we've drawn a button called "send_button", we can
        # refer to it as self.send_button:
        self.init_components()

        # Any code you write here will run when the form opens.
        #Uncomment as required.
        self.running = False
        self.reset = True
        self.first = True
        self.dt = self.timer.interval

        self.mousedown = False
        self.mouse = physics.vector3(0, 0, 0)

        self.t = 0
        self.paths = []
        #SET SCALE (pixels per m, or unit used in code)
        self.xu = 6
        self.v = 0

        #APPEND ALL PARAMETER BOXES
        self.param_boxes = [self.txt_v, self.txt_ang]