Waves.py
From GeoMod
To run the code, once you have VPython installed, you can either.
- Download this file: waves_02.py
- 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

