a guest Nov 30th, 2012 486 Never
  1. #!/usr/bin/env python
  2. """
  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:
  11. g = H/(x/K)**2
  13. Where H and K are the vertical and horizontal scaling constants and x is the distance from the
  14. orbital body.
  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)
  22. """
  25. import Image, ImageDraw, getpass, os, math
  27. user = getpass.getuser()
  28. path = '/Users/'+user+'/Desktop'                    #Get current path
  30. def img_new(x, y, name='0'):                    #Create function for making new blank images
  31.         img ='RGBA', (x, y), 'white')
  32.'/'+name+'.png', 'PNG')
  33.         del img
  35. def conv_coords(tup, x, y):                                             #Convert cartesian coordinates to PIL coordinates
  36.         return (tup[0], y-tup[1])
  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)
  41. def find_center(dim):                                                   #Find the center of a rectangle with given dimensions (x,y)
  42.         return (dim[1]/2,dim[0]/2)
  44. def draw_vector(working_vector, center, color, path, image_no):                                         #Define function for drawing a complete vector between two points
  45.         current_image ='/'+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.'/'+str(image_no)+'.png', 'PNG')                                                #Save image
  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)
  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
  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
  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
  110. do_main()                                                                                                                                                                                       #Start the prompt
RAW Paste Data