# Project 7: Planet Simulator from tkinter import Tk, Canvas from math import sin, cos from time import time from random import random class Planet: def __init__(self, radius=20, orbitradius=100, color="white", period=5): """Create a planet object. Sets planet data. Input: Radius, Orbitradius, color, period""" self.radius = radius self.orbitradius = orbitradius self.color = color self.period = period self.random = 3.14159*2*random() def position_tuple(self, secondselapsed = 0): """Method that computes the x,y positions of a planet. Input: time Output: (x, y)""" #Set converstion between seconds and days (simulation speed) dayspersecond = 80 dayselapsed = secondselapsed*dayspersecond # Calculate x, y, using cos, sin, days elapsed, and the planet's data x = cos(3.14159*2*1/self.period*dayselapsed+self.random)*self.orbitradius y = sin(3.14159*2*1/self.period*dayselapsed+self.random)*self.orbitradius return (x, y) class PlanetaryAnimator: def __init__(self, master): """Initiate Animator Object.""" #Bind the tk object to the animator object self.master = master # Set Resolution self.width, self.height = 1024, 768 # Set resizable OFF master.resizable(width=False, height=False) # Set Title master.title("Planetary Simulation") # Bind "q" to quit the application master.bind("", lambda _: master.destroy()) # Create a canvas object, set background color and size self.canvas = Canvas(master, bg="black", width=self.width, height=self.height) # Pack the canvas object self.canvas.pack() # Create an empty dictionary of planets self.objects = dict() def create_planet(self, planet): """Create a planet on screen. Input: Planet Object""" # Draw the planet's arc using draw_planetary_arc self.draw_planetary_arc(planet) # Get the x, y coordinates at time 0 from the position tuple (x, y) = planet.position_tuple(0) # Translate coordinates using _tktranslation() into Canvas coordinates coords = self._tktranslation(x, y, planet) # Draw a circle to the canvas, save the ID id_ = self.canvas.create_oval(*coords, fill=planet.color) # Save the ID to a dictionary with each ID:Planet object self.objects.update({id_:planet}) def draw_planetary_arc(self, planet): """Draw the planet's arc Input: Planet Object""" # Calculate x0, x1, y0, y1 from the planet's orbit radius x0 = self.width/2-planet.orbitradius x1 = self.width/2+planet.orbitradius y0 = self.height/2+planet.orbitradius y1 = self.height/2-planet.orbitradius # Draw the orbit path to the canvas. ID does not need to be saved. self.canvas.create_oval(x0, y0, x1, y1, outline=planet.color) def animate(self, starttime=time()): """Update the position of each planet with respect to time. Input: current time in seconds""" # For each id, planet in the objects dictionary # claculate coordinates with respect to time # move planet object to the new coordinate for id_, planet in self.objects.items(): (x, y) = planet.position_tuple(time()-starttime) coords = self._tktranslation(x, y, planet) self.canvas.coords(id_, *coords) # Refresh using canvas.after() self.canvas.after(50, self.animate) def _tktranslation(self, x, y, planet): """Method that translates x,y coordinates from a cartesian coordinate system to the Canvas coordinate system Input: Cartesian x, y Output: x0, y0, x1, y1""" x = x + self.width/2 y = -y + self.height/2 x0 = x+planet.radius/2 x1 = x-planet.radius/2 y0 = y+planet.radius/2 y1 = y-planet.radius/2 return (x0, y0, x1, y1) def main(): # Create new tk object root = Tk() # Pass the tk object into the PlanetaryAnimator animator = PlanetaryAnimator(root) # Mercury: p = 87.97 days # Venus: p = 224.7 days # Earth: p = 365.3 days # Mars: p = 686.93 days # Jupiter: p = 11.86*365 days # Saturn: p = 29.42*365 days # Uranus: p = 83.75*365 days # Neptune: p = 163.72*365 days # Create a new planet object for each planet in the # solar system. Input the planet's data. sun = Planet(radius = 70, orbitradius = 0, color = "orange", period = 999) mercury = Planet(radius = 10, orbitradius = 50, color = "red", period = 87.97) venus = Planet(radius = 30, orbitradius = 100, color = "coral", period = 224.7) earth = Planet(radius = 25, orbitradius = 150, color = "blue", period = 365) mars = Planet(radius = 20, orbitradius = 190, color = "tomato2", period = 11.86*365) jupiter = Planet(radius = 40, orbitradius = 230, color = "wheat2", period = 11.86*365) saturn = Planet(radius = 35, orbitradius = 290, color = "gold", period = 29.42*365) uranus = Planet(radius = 30, orbitradius = 340, color = "cyan", period = 83.75*365) neptune = Planet(radius = 30, orbitradius = 390, color = "blue", period = 168.72*365) # Use the method create_planet(Planet Object) to draw the # Graphical representation of each planet animator.create_planet(sun) animator.create_planet(mercury) animator.create_planet(venus) animator.create_planet(earth) animator.create_planet(mars) animator.create_planet(jupiter) animator.create_planet(saturn) animator.create_planet(uranus) animator.create_planet(neptune) # Animate the simulation using the animate() method animator.animate() # Call tk mainloop to begin simulation root.mainloop() if __name__ == '__main__': """This calls the main function""" main()