Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- """
- Coded by Kyle Hovey a.k.a. spel3o
- This is a script that uses the Python Imaging Library to model the eliptical orbit of a planet.
- This is not a perfect model of an orbit, and models an ellipse by use of regular intervals where
- gravity takes a "blow" on the intertial vector of the planet. The vector of the blow is a function
- of gravity vs. distance and thus is an application of inverse square. In other words:
- g = H/(x/K)**2
- Where H and K are the vertical and horizontal scaling constants and x is the distance from the
- orbital body.
- Errors in orbit calculation are found when:
- a.) A vector lands somewhere in the middle of a pixel (can be augmented by scaling)
- b.) The gravity vector's direction is determined (off by less than a degree due to rounding)
- """
- import Image, ImageDraw, getpass, os, math
- user = getpass.getuser()
- path = '/Users/'+user+'/Desktop' #Get current path
- def img_new(x, y, name='0'): #Create function for making new blank images
- img = Image.new('RGBA', (x, y), 'white')
- img.save(path+'/'+name+'.png', 'PNG')
- del img
- def conv_coords(tup, x, y): #Convert cartesian coordinates to PIL coordinates
- return (tup[0], y-tup[1])
- def grav_pull(dist, scale=1, K=6.35, H=6.336): #Determine the gravitational vector length from the distance and two constants
- return scale*(K/((dist/scale)/H)**2)
- def find_center(dim): #Find the center of a rectangle with given dimensions (x,y)
- return (dim[1]/2,dim[0]/2)
- def draw_vector(working_vector, center, color, path, image_no): #Define function for drawing a complete vector between two points
- current_image = Image.open(path+'/'+str(image_no)+'.png') #Vectors are stored with both of their coordinates in a list [(x0,y0),(x1,y1)]
- draw = ImageDraw.Draw(current_image) #Open active image
- draw.line(conv_coords(working_vector[0], center[1], center[0]) + conv_coords(working_vector[1], center[1], center[0]), fill=color, width=4)
- current_image.save(path+'/'+str(image_no)+'.png', 'PNG') #Save image
- def draw_sun(center, path, image_no=0): #Draw a dot in the center of the image for the sun
- draw_vector([(center[0]-1,center[1]+1),(center[0]+1,center[1]-1)], center, '#000', path, image_no)
- 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
- if end[1]-start[1] < 0: #Find if vector will be moving up or down
- y_neg = -1
- else:
- y_neg = 1
- if end[0]-start[0] < 0: #Find if vector will be moving left or right
- x_neg = -1
- else:
- x_neg = 1
- 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
- b = y_neg*math.sqrt(length**2-a**2) #Find the change in the x value by using pythagorean theorem
- new_endpoint = (start[0]+a, start[1]+b)
- arb_vector = [start, new_endpoint]
- draw_vector(arb_vector, center, color, path, image_no) #Draw the new vector
- if ret == 1: #Return the new vector
- return arb_vector
- def iterate(working_vector, center, image_no, path, scale): #Define the function for making a new iteration of the orbit
- vector_color = '#7513D6' #
- inertia_color = '#CF8A15' #Make things pretty
- gravity_color = '#069677' #
- segment_color = '#000'
- draw_sun(center, path, image_no) #Draw the sun
- draw_vector([working_vector[0], center], center, segment_color, path, image_no) #Draw initial vector
- draw_vector(working_vector, center, vector_color, path, image_no) #Draw line from vector start to center
- delta_y = working_vector[1][1]-working_vector[0][1] #
- delta_x = working_vector[1][0]-working_vector[0][0] #Determine the rise and run of the vector
- end_coords = working_vector[1] #Save the end of the original vector for the drawing of the next
- 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
- draw_vector(working_vector, center, inertia_color, path, image_no) #Draw the extended vector copy of the first vector
- 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
- g = grav_pull(distance, scale) #Find gravitational pull
- 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
- working_vector = [working_vector[1], end_coords] #Create new vector starting at the end of the initial vector and ending
- draw_vector(working_vector, center, vector_color, path, image_no) #at the end of the gravity vector, then draw it.
- return [working_vector[1],working_vector[0]] #Return resultant vector for next iteration
- def do_main(x=1000, y=2000): #Start the whole shebang (no pun intended)
- image_no = 0 #Start at image 0
- initial_distance = input('Please enter the starting distance of the orbital body from the sun:') #
- initial_vector = input('Please enter the initial speed vector in cm proportional to velocity:') #Get preliminary data
- scale = input('Please enter the scale of the model:') #
- img_new(y,x) #Create a new image with the default or provided dimensions
- size = (x,y)
- center = find_center(size) #Find center of new image
- working_vector =[(center[0]+initial_distance*scale, center[1]), (center[0]+initial_distance*scale, center[1]+initial_vector*scale)] #Establish the initial vector
- while True:
- questionaire = raw_input('Hit enter to execute an iteration or d for done:') #Begin the iterations
- if questionaire == 'd': #Break out of iterations if d for done is received
- ##compile_gif(path+'/*.png)
- print('Program execution completed.')
- return False
- else:
- working_vector = iterate(working_vector, center, image_no, path, scale) #Create new iteration
- os.system('cp '+path+'/'+str(image_no)+'.png '+path+'/'+str(image_no+1)+'.png') #Copy the image and increase the filename number by one
- image_no += 1 #Increment the image count
- do_main() #Start the prompt
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement