Elipticity.py

From GeoMod

Jump to: navigation, search

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

  1. Download this file: elipse-01.py
  2. 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)



Personal tools