Elipticity.py
From GeoMod
To run the code, once you have VPython installed, you can either.
- Download this file: elipse-01.py
- or, copy and paste the following code to a file (named "elipse-01.py" for example) using your favorite text editor.
from visual import *
#from Numeric 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 orbits:
def __init__(self):
self.orbit_path = []
self.planets = []
def draw(self,e=0.0,rad=1.0, mu=10.0, planet_size=1.0, frate=10000000):
self.orbit_path.append( curve(color=color.green,radius=0.075))
self.planets.append( sphere(color=color.red,radius=planet_size))
if e >= 1.0:
e = 0.99
if e < 0.0:
e = 0.0
fx = 2.0 - 2.0*min(abs((1-e*e)/(1-e)), abs(-(1-e*e)/(1+e)))
self.planets[-1].fx = fx
self.planets[-1].e = e
self.planets[-1].rad = rad
for i in range(361):
rate(frate)
theta = radians(float(i))
#h_sq = a*(1-e*e)*mu
r = (1-e*e)/(1-e*cos(theta))
nx = rad*(r*cos(theta) - fx)
ny = rad*r*sin(theta)
#print i, f, r, cos(theta), sin(theta), nx, ny
self.orbit_path[-1].append(pos=(nx, ny, 0.0))
self.planets[-1].pos=vector(nx,ny,0.0)
def re_draw(self,e=0.0,rad=1.0,mu=10.0, frate=10000000):
#redraw last path
if e >= 1.0:
e = 0.99
if e < 0.0:
e = 0.0
fx = 2.0 - 2.0*min(abs((1-e*e)/(1-e)), abs(-(1-e*e)/(1+e)))
self.planets[-1].fx = fx
self.planets[-1].e = e
self.planets[-1].rad = rad
for i in range(361):
rate(frate)
theta = radians(float(i))
#h_sq = a*(1-e*e)*mu
r = (1-e*e)/(1-e*cos(theta))
nx = rad*(r*cos(theta) - fx)
ny = rad*r*sin(theta)
self.orbit_path[-1].pos[i]=vector(nx, ny, 0.0)
def move_planets(self, theta):
for i in self.planets:
#to show the planet orbiting the Sun
theta = radians(float(theta))
r = (1-i.e*i.e)/(1-i.e*cos(theta))
nx = i.rad*(r*cos(theta) - i.fx)
ny = i.rad*r*sin(theta)
i.pos = vector(nx,ny,0.0)
origx = 0
origy = 0
w = 704+4+4
h = 576+24+4
scene.width=w
scene.height=h
scene.x = origx
scene.y = origy
mu = 10.0 #gravitational acceleration
e = 0.6 #eccentricity
a = 10.0 #distance of sun from center of elipse
# to draw an elipse
sun = sphere(color=color.yellow)
#orbitor = sphere()
e_slide = slider(pos=vector(10,5,0), init_val=e, title="elipticity",scale=5.0)
orbs = orbits()
orbs.draw(e=e, rad=a,mu=mu,frate=100,planet_size=0.5)
scene.center = sun.pos
scene.autoscale = 0
runtime = 0.0
framerate = 60
pick = None
planet_angle = 0
while 1:
rate(framerate)
runtime += 1.0/framerate
#mouse events
if scene.mouse.events:
m1 = scene.mouse.getevent() # obtain drag or drop event
if m1.drag and (m1.pick == e_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 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 == e_slide.but:
pick.pos = e_slide.but_move(pick.pos)
e = e_slide.value #so e changes when the value of the slider changes
#print e
#make adjustments based on new value of the slider
orbs.re_draw(e=e, rad=a, mu=mu)
planet_angle += 1
if planet_angle >= 361:
planet_angle = 1
orbs.move_planets(planet_angle)

