Advertisement
Guest User

Eliptical_Orbit.py

a guest
Nov 30th, 2012
598
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.52 KB | None | 0 0
  1. #!/usr/bin/env python
  2. """
  3.  
  4.  
  5. Coded by Kyle Hovey a.k.a. spel3o
  6. This is a script that uses the Python Imaging Library to model the eliptical orbit of a planet.
  7. This is not a perfect model of an orbit, and models an ellipse by use of regular intervals where
  8. gravity takes a "blow" on the intertial vector of the planet. The vector of the blow is a function
  9. of gravity vs. distance and thus is an application of inverse square. In other words:
  10.  
  11. g = H/(x/K)**2
  12.  
  13. Where H and K are the vertical and horizontal scaling constants and x is the distance from the
  14. orbital body.
  15.  
  16. Errors in orbit calculation are found when:
  17. a.) A vector lands somewhere in the middle of a pixel (can be augmented by scaling)
  18. b.) The gravity vector's direction is determined (off by less than a degree due to rounding)
  19.  
  20.  
  21.  
  22. """
  23.  
  24.  
  25. import Image, ImageDraw, getpass, os, math
  26.  
  27. user = getpass.getuser()
  28. path = '/Users/'+user+'/Desktop'                #Get current path
  29.  
  30. def img_new(x, y, name='0'):                    #Create function for making new blank images
  31.     img = Image.new('RGBA', (x, y), 'white')
  32.     img.save(path+'/'+name+'.png', 'PNG')
  33.     del img
  34.    
  35. def conv_coords(tup, x, y):                     #Convert cartesian coordinates to PIL coordinates
  36.     return (tup[0], y-tup[1])
  37.  
  38. def grav_pull(dist, scale=1, K=6.35, H=6.336)#Determine the gravitational vector length from the distance and two constants
  39.     return scale*(K/((dist/scale)/H)**2)
  40.    
  41. def find_center(dim):                           #Find the center of a rectangle with given dimensions (x,y)
  42.     return (dim[1]/2,dim[0]/2)
  43.  
  44. def draw_vector(working_vector, center, color, path, image_no):                     #Define function for drawing a complete vector between two points
  45.     current_image = Image.open(path+'/'+str(image_no)+'.png')                       #Vectors are stored with both of their coordinates in a list [(x0,y0),(x1,y1)]
  46.     draw = ImageDraw.Draw(current_image)                                            #Open active image
  47.     draw.line(conv_coords(working_vector[0], center[1], center[0]) + conv_coords(working_vector[1], center[1], center[0]), fill=color, width=4)
  48.     current_image.save(path+'/'+str(image_no)+'.png', 'PNG')                        #Save image
  49.    
  50. def draw_sun(center, path, image_no=0):                                             #Draw a dot in the center of the image for the sun
  51.     draw_vector([(center[0]-1,center[1]+1),(center[0]+1,center[1]-1)], center, '#000', path, image_no)
  52.    
  53. def draw_arb_vector(start, end, length, center, color, image_no, path, ret=1):      #Define a function to draw an arbitrarily long vector towards another point
  54.     if end[1]-start[1] < 0:                                                         #Find if vector will be moving up or down
  55.         y_neg = -1
  56.     else:
  57.         y_neg = 1
  58.     if end[0]-start[0] < 0:                                                         #Find if vector will be moving left or right
  59.         x_neg = -1
  60.     else:
  61.         x_neg = 1
  62.     a = x_neg*math.sqrt(length**2/(1+((start[1]-end[1])/(start[0]-end[0]))**2))     #Find the change in the y value by solving for slope (rise/run) and pythagorean theorem a^2+b^2=c^2
  63.     b = y_neg*math.sqrt(length**2-a**2)                                             #Find the change in the x value by using pythagorean theorem
  64.     new_endpoint = (start[0]+a, start[1]+b)
  65.     arb_vector = [start, new_endpoint]
  66.     draw_vector(arb_vector, center, color, path, image_no)                          #Draw the new vector
  67.     if ret == 1:                                                                    #Return the new vector
  68.         return arb_vector
  69.    
  70. def iterate(working_vector, center, image_no, path, scale):                         #Define the function for making a new iteration of the orbit
  71.     vector_color = '#7513D6'                                                        #
  72.     inertia_color = '#CF8A15'                                                       #Make things pretty
  73.     gravity_color = '#069677'                                                       #
  74.     segment_color = '#000'
  75.     draw_sun(center, path, image_no)                                                                #Draw the sun
  76.     draw_vector([working_vector[0], center], center, segment_color, path, image_no)                 #Draw initial vector
  77.     draw_vector(working_vector, center, vector_color, path, image_no)                               #Draw line from vector start to center
  78.     delta_y = working_vector[1][1]-working_vector[0][1]                                             #
  79.     delta_x = working_vector[1][0]-working_vector[0][0]                                             #Determine the rise and run of the vector
  80.     end_coords = working_vector[1]                                                                              #Save the end of the original vector for the drawing of the next
  81.     working_vector = [working_vector[1], (working_vector[1][0]+delta_x, working_vector[1][1]+delta_y)]          #Apply the change in rise and run for the first vector to double it
  82.     draw_vector(working_vector, center, inertia_color, path, image_no)                                          #Draw the extended vector copy of the first vector
  83.     distance = math.sqrt((working_vector[0][0]-center[0])**2+(working_vector[0][1]-center[1])**2)               #Use Pythagorean theorem to find distance to center
  84.     g = grav_pull(distance, scale)                                                                              #Find gravitational pull
  85.     working_vector = draw_arb_vector(working_vector[1], (center[0]+delta_x,center[1]+delta_y), g, center, gravity_color, image_no, path)      #Draw the gravity vector
  86.     working_vector = [working_vector[1], end_coords]                                                            #Create new vector starting at the end of the initial vector and ending
  87.     draw_vector(working_vector, center, vector_color, path, image_no)                                           #at the end of the gravity vector, then draw it.
  88.     return [working_vector[1],working_vector[0]]                                                                #Return resultant vector for next iteration
  89.    
  90. def do_main(x=1000, y=2000):                                                                                    #Start the whole shebang (no pun intended)
  91.     image_no = 0                                                                                                #Start at image 0
  92.     initial_distance = input('Please enter the starting distance of the orbital body from the sun:')            #
  93.     initial_vector = input('Please enter the initial speed vector in cm proportional to velocity:')             #Get preliminary data
  94.     scale = input('Please enter the scale of the model:')                                                       #
  95.     img_new(y,x)                                                                                                #Create a new image with the default or provided dimensions
  96.     size = (x,y)
  97.     center = find_center(size)                                                                                  #Find center of new image      
  98.     working_vector =[(center[0]+initial_distance*scale, center[1]), (center[0]+initial_distance*scale, center[1]+initial_vector*scale)]     #Establish the initial vector
  99.     while True:
  100.         questionaire = raw_input('Hit enter to execute an iteration or d for done:')                            #Begin the iterations
  101.         if questionaire == 'd':                                                                                 #Break out of iterations if d for done is received
  102.             ##compile_gif(path+'/*.png)
  103.             print('Program execution completed.')
  104.             return False
  105.         else:
  106.             working_vector = iterate(working_vector, center, image_no, path, scale)                 #Create new iteration
  107.             os.system('cp '+path+'/'+str(image_no)+'.png '+path+'/'+str(image_no+1)+'.png')         #Copy the image and increase the filename number by one
  108.             image_no += 1                                                                           #Increment the image count
  109.  
  110. do_main()                                                                                           #Start the prompt
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement