Functions
From GeoMod
Introducing functions. The first example uses the 2d array of tiles. The second uses the bouncing ball example code.
2d tiles
In the code for the 2d array of tiles we create a set of tiles with the top left corner of the tiles at the position (0,0,0),
from visual import *
from random import uniform
# define parameters
nx = 5
lx = 4.0
nz= 4
lz=4.0
# initialize variables
dx = lx/nx
dz= lz/nz
# create tiles (top left at 0,0,0)
tiles=[]
for i in range (nx):
for j in range (nz):
tiles.append(box(length=dx,
width=dz,
height=.5,
color=(uniform(0.5,1),0,0) ))
tiles[-1].pos.x=0+i*dx
tiles[-1].pos.z=0+j*dz
#print i,j, tiles[-1].pos
#create axes
xaxis= cylinder(axis=(4,0,0), color=color.red, radius=.05)
yaxis= cylinder(axis=(0,4,0), color=color.blue, radius=.05)
zaxis= cylinder(axis=(0,0,4), color=color.yellow, radius=.05)
To move the tiles so that the center of the set of tiles is at (0,0,0) we add the following code to the end of the program.
#translate tiles so center of grid is 0,0,0
for i in tiles:
i.pos.x=i.pos.x-(nx-1)*dx/2.0
i.pos.z=i.pos.z-(nz-1)*dz/2.0
print (nx-1)/2.0, (nz-1)/2.0, i.pos
Functions
What if we had a number of sets of tiles that we wanted to translate to different locations? We have used functions before; in the code above, the function "uniform(0.5,1)" selects a random number between 0.5 and 1. The code for the uniform() function is imported in the second line of the program.
from random import uniform
Well, we can also create our own functions. Here is an adaptation of the above code, but with the translation of the tiles done by a function.
from visual import *
from random import uniform
def translate(lst, x_late=0, y_late=0, z_late=0):
'''program to translate all objects in list (lst)'''
for i in lst:
i.pos.x=i.pos.x-x_late
i.pos.z=i.pos.z-z_late
print i.pos
# define parameters
nx = 5
lx = 4.0
nz= 4
lz=4.0
# initialize variables
dx = lx/nx
dz= lz/nz
# create tiles (top left at 0,0,0)
tiles=[]
for i in range (nx):
for j in range (nz):
tiles.append(box(length=dx,
width=dz,
height=.5,
color=(uniform(0.5,1),0,0) ))
tiles[-1].pos.x=0+i*dx
tiles[-1].pos.z=0+j*dz
#print i,j, tiles[-1].pos
#create axes
xaxis= cylinder(axis=(4,0,0), color=color.red, radius=.05)
yaxis= cylinder(axis=(0,4,0), color=color.blue, radius=.05)
zaxis= cylinder(axis=(0,0,4), color=color.yellow, radius=.05)
###translate tiles so center of grid is 0,0,0
translate(tiles, (nx-1)*dx/2.0, 0.0, (nz-1)*dz/2.0)
In this code we create a new function called translate which moves all objects in the list by the amount specified. This produces the same result as the previous code.
The function is defined in the line
def translate(lst, x_late=0, y_late=0, z_late=0):
which defines the name of the function (translate) and the variables that need to be sent to the function. This function requires that a list of objects be sent to it. When the list gets to the function it is called lst no matter what the original name of the array (in this example the original name is tiles). You can also tell the function how much to translate the array of tiles in the x, y and z directions. These translation values are held in the variables x_late, y_late and z_late. These three values are optional. If they are not entered they take the default values given in the line (0 for all three).
The call to the function is the line
translate(tiles, (nx-1)*dx/2.0, 0.0, (nz-1)*dz/2.0)
which gives the name of the list that is to be translated, and the x, y and z translations.
Bouncing ball
In the following code (posted by Beth Bradshaw) a function called contact is defined that determines if two balls hit one another. The function takes two arguments (ball1 and ball2) that are spheres and calculates the distance between the spheres and compares it to the sum of the radii to see if the balls overlap or touch. If the balls touch the function returns True and if not it returns False.
from visual import *
from random import uniform,seed
def contact(ball1,ball2):
hit=false
#calculate distance
a=ball1.pos.z-ball2.pos.z
b=ball1.pos.x-ball2.pos.x
d=ball1.pos.y-ball1.pos.y
c=((a*a)+(b*b)+(d*d))**0.5
#sum radii
r=ball1.radius+ball2.radius
#determine if there is a hit
if c <= r:
hit=true
return hit
scene.forward = (0, -0.5,1)
scene.up = (0,0,1)
scene.forward = (0, 1,0)
scene.lights = [vector(0, -10, 0)]
xaxis = curve(pos=[ (20, 0, 0), (0, 0,0)], color=(1,0,0))
yaxis = curve(pos=[ (0, 10, 0), (0, 0,0)], color=(0,1,0))
zaxis = curve(pos=[ (0, 0, 10), (0, 0,0)], color=(0,0,1))
balls=[]
seed(4)
nballs=5
vx=zeros((nballs,))
vz=zeros((nballs,))
for i in range(nballs):
rad=uniform(0.5,2)
vx[i]=uniform(1,2)
balls.append(sphere(radius=rad,pos=(i,0,10)))
'''gravity constant'''
g = -9.8
'''change in time'''
dt = 0.01
'''initial z velocity'''
velz = 0.0
'''initial time'''
t = 0.0
print vx,vz
while t==0.0:
rate(60)
'''time'''
t = t + dt
vz=vz+g*dt
for n,i in enumerate(balls):
i.pos.z = i.pos.z + vz[n] * dt #+ 0.5 * g * dt * dt
i.pos.x = i.pos.x + vx[n] * dt
if i.pos.z < i.radius:
vz[n] = -vz[n] * 0.75
vx[n] = vx[n] * 0.75
i.pos.z = i.radius
for n in range(nballs-1):
for m in range (n+1,nballs):
ball1=balls[n]
ball2=balls[m]
print 'contact',n,m
if contact(ball1,ball2):
print n,m



