VPython

Simulações com VPython

por Jaime E. Villate. Universidade do Porto, Portugal.

VPhyton

VPython é um módulo adicional para Python, que inclui classes para criar vários tipos de formas geométricas em três dimensões, podendo ser colocadas em movimento facilmente. VPython usa a biblioteca gráfica OpenGL. A versão mais recente, 7, lança as animações dentro dum browser, usando WebGL e Javascript.

VPython é software livre que pode ser descarregado no seu sítio Web e instalado em todos os principais sistemas operativos.

Lançamento de projéteis no ar

 from vpython import *

 def deslocar(corpo):
     global dt
     queda = True
     p = corpo.traj.point(corpo.traj.npoints-1)['pos']
     corpo.pos += dt*corpo.v + dt**2*corpo.a/2.
     if corpo.v.y < 0 and corpo.pos.y < corpo.radius:
         if p.y != corpo.pos.y:
             f = (p.y - corpo.radius)/(p.y - corpo.pos.y)
             corpo.pos -= (1 - f)*(corpo.pos - p)
             corpo.v += f*dt*corpo.a
             corpo.t += f*dt
         queda = False
     else:
         corpo.t += dt
         corpo.v += dt*corpo.a
     corpo.traj.append(pos=vec(corpo.pos))
     corpo.d += mag(corpo.pos - p)
     return queda

 def resultados(corpo):
     p0 = corpo.traj.point(0)['pos']
     alcance = corpo.pos.x - p0.x
     velocidade = corpo.d / corpo.t
     scene.caption += '<b>'+corpo.legenda+'</b>\n'
     scene.caption += 'Tempo de voo         = {:.2f} s\n'.format(corpo.t)
     scene.caption += 'Alcance horizontal   = {:.2f} m\n'.format(alcance)
     scene.caption += 'Distância percorrida = {:.2f} m\n'.format(corpo.d)
     scene.caption += 'Velocidade média     = {:.2f} m/s\n'.format(velocidade)
     return

 def projetar(corpo, vel, ang, leg):
     corpo.v = vel*vec(cos(ang*pi/180.), sin(ang*pi/180.), 0)
     corpo.t = corpo.d = 0
     corpo.legenda = leg
     corpo.traj = curve(pos=vec(corpo.pos),color=corpo.color)

 scene = canvas(title = '<h1>Lançamento de projéteis no ar</h1>',
                forward=vec(-0.5,-0.2,-1))
 scene.caption = ''
 a = 47.
 dt = 0.01
 g = vec(0,-9.8,0)
 q1 = q2 = q3 = True

 bola1 = sphere(pos=vec(-7.5,0.2,1), radius=0.4, color=vec(0.93,1,0.16))
 bola2 = sphere(pos=vec(-7.5,0.1,0), radius=0.2, color=vec(1,0,0))
 bola3 = sphere(pos=vec(-7.5,0.1,-1), radius=0.2, color=vec(1,0.49,0.05))
 chao = box(pos=vec(0,-0.1,0), size=vec(16,0.2,10), texture=textures.wood)
 parede = box(pos=vec(0,2.8,-5.05),size=vec(16,6,0.1), color=vec(0.7,0.7,0.7))
 sitio = text(pos=vec(0,2.8,-5), text='def.fe.up.pt', color=color.blue,
              align='center', depth=0)
 projetar (bola1, 12, 45., 'Bola de ténis')
 projetar (bola2, 12, 45., 'Sem resistência do ar')
 projetar (bola3, 12, 45., 'Bola de ping-pong')
 bola2.a = g

 while q1 or q2 or q3:
     rate(100)
     bola1.a = g - 0.01606*mag(bola1.v)*bola1.v
     bola3.a = g - 0.14176*mag(bola3.v)*bola3.v
     if q1: q1 = deslocar (bola1)
     if q2: q2 = deslocar (bola2)
     if q3: q3 = deslocar (bola3)

 resultados(bola2)
 resultados(bola1)
 resultados(bola3)

Executar o programa no browser

Oscilador harmónico simples

 from vpython import *

 scene = canvas(title='<h1>Oscilador harmónico simples</h1>', autoscale=0,
                width=500, height=500, range=7, forward=vec(0,0,-1))
 chao = box(pos=vec(0,-6.1,0),size=vec(20,0.1,10),texture=textures.wood)
 parede = box(pos=vec(0,3.85,-5.05),size=vec(20,20,0.1), color=vec(0.7,0.7,0.7))
 sitio = text(pos=vec(0,3.85,-5), text='def.fe.up.pt', color=color.blue,
              align='center', depth=0)

 # Mola e cilindro
 bar0 = curve(radius=0.03)
 for ang in arange(pi,-pi/2.,-0.1):
     bar0.append(vec(0, 5.2+0.23*sin(ang), 0.23*cos(ang)))
 bar0.append(pos=vec(0,4.5,0))
 bar0.append(pos=vec(0,4.5,0.3))
 mola1 = helix(pos=vec(0,4.5,0), radius=0.3, thickness=0.05, coils=30,
               axis = vec(0,-5.8,0))

 bar1 = curve(radius=0.03, pos=[vec(0,-1.6,0),vec(0,-1.3,0),vec(0,-1.3,0.3)])
 c1 = cylinder(pos=vec(0,-2,0),radius=0.5,axis=vec(0,0.4,0),
               color=vec(0.3,0.3,0.3))

 # Barras do suporte
 s1 = cylinder(pos=vec(3,5.2,0),radius=0.2, axis=vec(-4,0,0))
 s2 = cylinder(pos=vec(2.5,5.2,0),radius=0.6, axis=vec(-1,0,0),color=vec(0.5,0.5,0.6))
 s3 = cylinder(pos=vec(2,-5,0.4),radius=0.2, axis=vec(0,11,0))
 s4 = cylinder(pos=vec(2,-6.05,0.4),radius=0.8, axis=vec(0,1,0),color=vec(0.9,0.9,0.6))

 # Função que alonga/comprime a mola y1 unidades
 def alongar_mola(y1):
     c1.pos.y = y1 - 2
     bar1.origin = vec(0,y1,0)
     mola1.axis.y = y1 - 5.8

 def uf(rf):          # velocidade no espaço de fase
     a = (-k1*rf.y-b1*rf.z)/m1
     return vec(0,rf.z, a)

 rf = vec(0, 0.9, 0)
 m1 = 0.3; k1 = 16; b1 = 0.02
 dt = 0.01
 alongar_mola(rf.y)

 while True:
     rate(100)
     uf1 = uf(rf)
     uf2 = uf(rf + dt*uf1 / 2.)
     uf3 = uf(rf + dt*uf2 / 2.)
     uf4 = uf(rf + dt*uf3)
     ufm = (uf1 + 2*uf2 + 2*uf3 + uf4)/6.
     rf += dt*ufm
     alongar_mola(rf.y)

Executar o programa no browser

Pêndulo

 from vpython import *
 scene = canvas(title='<h1>Pêndulo</h1>', autoscale=0, range=5,
                center=vec(0,3,0), forward=vec(-0.3,0,-1))
 chao = box(pos=vec(0,-0.85,0),size=vec(20,0.1,10),texture=textures.wood)
 parede = box(pos=vec(0,7.1,-5.05),size=vec(20,16,0.1), color=vec(0.7,0.7,0.7))
 sitio = text(pos=vec(0,7.1,-5), text='def.fe.up.pt', color=color.blue,
              align='center', depth=0)
 barra = box(pos=vec(0,-1.4,0), size=vec(0.2,3.2,0.2), color=vec(1,1,0))
 disco = cylinder(pos=vec(0,-3,-0.2), radius=0.6, axis=vec(0,0,0.4),
                  color=vec(0.5,0.5,0.8))
 pendulo = compound([barra, disco])
 pendulo.pos=vec(0,1.8,0)
 eixo = cylinder(pos=vec(0,3.5,0.3), radius=0.09, axis=vec(0,0,-1),
                 color=vec(0.7,0.4,0.1))
 b1 = box(pos=vec(0,1.7,-1), size=vec(1,4.2,0.6), color=vec(0.7,0.4,0.1))
 b2 = box(pos=vec(0,-0.6,-0.5), size=vec(3,0.4,1.6), color=vec(0.7,0.4,0.1))
 
 pendulo.w = 10
 pendulo.angulo = 0
 pendulo.l = 3
 dt = 0.01
 
 while True:
     rate(100)
     pendulo.a = -98*sin(pendulo.angulo)/pendulo.l
     pendulo.w = pendulo.w + pendulo.a*dt
     pendulo.angulo = pendulo.angulo + pendulo.w*dt
     pendulo.rotate(axis=vec(0,0,1), angle=pendulo.w*dt, origin=vec(0,3.5,0))

Executar o programa no browser