Waves.py

From GeoMod

Jump to: navigation, search

To run the code, once you have VPython installed, you can either.

  1. Download this file: waves_02.py
  2. or, copy and paste the following code to a file (named "waves_02.py" for example) using your favorite text editor.
from visual import *

class slider:
    def __init__(self, pos=vector(0,0,0), 
                 min_val=0.0, max_val=1.0,
                 init_val=0.0,
                 stop_but= 0, stop_val=0.0,
                 scale=1.0,
                 title = "Control"):
        '''
        pos = position of the slider bar
        min_val = minimum value on the slider bar
        max_val = maximum value on the slider bar
        init_val = initial value of slider bar (if beyond min_val or max_val is reset to min_val or max_val)
        stop_but = set to 0 for no stop button and to 1 for a stop button (not yet in)

        Note: The minimum y position of the slider is 0.0 and the maximum is self.scale
        '''
        self.pos = pos
        self.min_val = min_val
        self.max_val = max_val
        self.stop_val = 0.0
        self.scale = scale
        self.value = init_val
        self.title = title

        self.bits = frame(pos=self.pos)
        self.cyl = cylinder(frame=self.bits, radius=0.05*self.scale, axis=(0,self.scale,0), color=color.yellow)
        self.but = sphere(frame=self.bits, pos=(0,self.get_y(), 0), radius = self.cyl.radius * 2.0, color = color.green)
        self.title = label(frame=self.bits, pos=self.cyl.axis*1.2, text=self.title,height=10, box=0, xoffset=0, yoffset=0, space = 2)
        self.val_label = label(frame=self.bits, pos=self.cyl.axis*-0.2, text=str(round(self.get_val(),1)),height=10, box=0, xoffset=0, yoffset=0, space = 2)
        
        #adjust for boundary values
        self.boundary_set()

    def get_y(self):
        return self.scale * (self.value - self.min_val) / (self.max_val - self.min_val)

    def get_val(self):
        return self.min_val + (self.but.pos.y / self.scale)*(self.max_val - self.min_val)

    def boundary_set(self):
        '''to keep values in bounds'''
        if self.value < self.min_val:
            self.value = self.min_val
            self.but.pos.y = 0.0
        if self.value > self.max_val:
            self.value = self.max_val
            self.but.pos.y = self.scale
            
    def but_move(self, cursor_pos):
        nx = 0.0 #self.bits.x
        ny = cursor_pos.y 
        nz = 0.0 #self.bits.z
        if ny < 0.0: #self.bits.y:
            ny = 0.0 #self.bits.y
            nv = self.min_val
        elif ny > self.cyl.axis.y: #self.bits.y + self.cyl.axis.y:
            ny = self.cyl.axis.y #self.bits.y + self.cyl.axis.y
            nv = self.max_val

        nv = self.min_val + ((ny) / self.scale)*(self.max_val - self.min_val)

        print ny, nv
        self.value = nv
        self.val_label.text = str(round(self.get_val(),1))

        return vector(nx, ny, nz)

class uSwitch:

    def __init__(self, radius=1.0,init_val=0, pos=vector(0,0,0), title="Switch"):

        self.title = title
        self.value = init_val
        

        self.bits = frame(pos=pos)
        self.button = sphere(frame=self.bits, radius = radius, color = self.get_color())
        self.title = label(frame=self.bits, pos=(0,radius*1.2,0),
                           text=self.title, height=10, box=0,
                           xoffset=0, yoffset=0, space = 2)
        self.val_label = label(frame=self.bits, pos=(0,-radius*1.2,0),
                               text=self.get_val(),height=10, box=0, xoffset=0, yoffset=0, space = 2)
        
    def switch(self):
        if self.value == 1:
            self.value = 0
            #self.button.color = color.red
        else:
            self.value = 1
            #self.button.color = color.blue
        self.val_label.text = self.get_val()
        self.button.color = self.get_color()
        #print self.get_val()

    def get_val(self):
        if self.value == 1:
            val = "On"
        else:
            val = "Off"
        return val

    def get_color(self):
        if self.value == 1:
            col = color.red
        else:
            col = color.blue
        return col



sea_level = 5
ws = 10.0   #windspeed

ncells = 180 #number of cells in the model
d_phi = 10  #degrees

b_factor = 1.0 # Factor to reduce the b value in the trochoid
Hmax = ws * ws / 45.0   # Maximum wave height (b in trochoid)
wavelength = b_factor*Hmax * 7.0 # Maximum wave length
radius = wavelength / (2.0 * pi) # Radius of trochoid circle (a in trochoid)
dx = wavelength / (360.0/d_phi) # wave velocity (celerity)


base_wavelength = wavelength
base_waves = 6
x_max = (radius * 2.0 * pi * (base_waves*360) / 360.0) - (Hmax * sin(pi*(base_waves*360)/180.0)) 
ncells = base_waves*360/d_phi

origx = 0
origy = 0
w = 704 #+4+4
h = 576 #+24+4
scene.width=w
scene.height=h
scene.x = origx
scene.y = origy
scene.background = color.white

sphere(pos=(x_max,0,0),color=color.green)


#create a line for the water surface
phi = arange(0, d_phi*ncells, d_phi)
water_surface=curve(x=arange(0, d_phi*ncells, d_phi), color=color.blue, radius=0.5)
water_surface.x = (radius * 2.0 * pi * phi / 360.0) - (b_factor*Hmax * sin(pi*phi/180.0)) 
water_surface.y = sea_level + (radius) + (b_factor*Hmax * cos(pi*phi/180.0)) 

print water_surface.x[-1]

xaxis = curve(color = color.red, radius = 0.25, pos=[(0,0), (water_surface.x[-1],0)])
yaxis = curve(color = color.red, radius = 0.25, pos=[(0,0), (0, water_surface.y[0])])
scene.center = (water_surface.x[-1]/2.0, 0, 0)
scene.autoscale = 0

boat = box(color = color.red, length = 2.0, width = 1.0, height=1.0)
boat.pos = (water_surface.x[ncells/2], water_surface.y[ncells/2]+1.0) 
boat_trail = curve(color=color.green, radius = 0.2)
boat_trail.visible = 0
#boat_trail.append(pos=boat.pos)

#rate(0.05)

#CONTROLS
ws_slide = slider(pos=scene.center+vector(0,2.0* water_surface.y[0],0),
                  min_val = 0, max_val=20.0,
                  init_val=ws, title="Wind speed",scale=5.0)
b_slide = slider(pos=scene.center+vector(0.25*x_max,2.0* water_surface.y[0],0),
                  min_val = 0, max_val=1.0,
                  init_val=b_factor, title="wave height",scale=5.0)
trail_but = uSwitch(pos=scene.center+vector(-0.25*x_max,2.0* water_surface.y[0],0),
                    title="Trails", radius=2.0)


pick=None
start_phi = 0.0
init_x = 0.0

while 1:

        #mouse events
    if scene.mouse.events:
        m1 = scene.mouse.getevent() # obtain drag or drop event
        if m1.drag and (m1.pick == ws_slide.but or b_slide.but):
            drag_pos = m1.pickpos
            pick = m1.pick
            print m1.pick.pos
            scene.cursor.visible = 0 # make cursor invisible
        elif m1.drop:
            pick = None # end dragging
            scene.cursor.visible = 1 # cursor visible
            
        if m1.pick == trail_but.button and m1.release:
            trail_but.switch()
            if trail_but.value == 0:
                boat_trail.visible = 0
            else:
                boat_trail.visible = 1
                boat_trail.pos = []
                

    if pick:
        new_pos = scene.mouse.project(normal=(0,0,1))
        if new_pos != drag_pos:
            pick.pos += new_pos - drag_pos
            drag_pos = new_pos
            if pick == ws_slide.but:
                pick.pos = ws_slide.but_move(pick.pos)
                ws = ws_slide.value   #so e changes when the value of the slider changes
                Hmax = ws * ws / 45.0   # Maximum wave height (b in trochoid)
                wavelength = b_factor*Hmax * 7.0 # Maximum wave length
                radius = wavelength / (2.0 * pi) # Radius of trochoid circle (a in trochoid)
                dx = wavelength / (360.0/d_phi) # wave velocity (celerity)

                water_surface.visible = 0
                nwaves = x_max / wavelength
                max_phi = nwaves * 360.0
                d_phi = int(max_phi / ncells)
                phi = arange(0, d_phi*ncells, d_phi)
                water_surface=curve(x=arange(0, d_phi*ncells, d_phi), color=color.blue, radius=0.5)

            if pick == b_slide.but:
                pick.pos = b_slide.but_move(pick.pos)
                b_factor = b_slide.value


    init_x = init_x + dx
    phi = arange(start_phi, start_phi + d_phi*ncells, d_phi)
    water_surface.x = (radius * 2.0 * pi * phi / 360.0) - (b_factor*Hmax * sin(pi*phi/180.0)) - init_x 
    water_surface.y = sea_level + (radius) + (b_factor*Hmax * cos(pi*phi/180.0)) 
    boat.pos = (water_surface.x[ncells/2], water_surface.y[ncells/2]+1.0)
    if boat_trail.visible:
        boat_trail.append(pos=boat.pos)
    
    rate(30)
    
    start_phi = start_phi + d_phi
    if start_phi >= 360:
        start_phi = start_phi - 360
        init_x = 0.0

Personal tools