GlowScript 2.7 VPython
#Travelling to Mars
#Developed by A.Titus
#pos unit is m
#time unit is s

#pos and vel generated by http://ssd.jpl.nasa.gov/horizons.cgi

#Aug 29, 2015

#no z components
marspos=1000*vec(-1.176389005286295E+08,2.135936464902488E+08,0)
marsvel=1000*vec(-2.027713823922661E+01,-9.661960006152405E+00,0)
earthpos=1000*vec(1.376368513677354E+08,-6.342242292720988E+07,0)
earthvel=1000*vec(1.203162796791987E+01,2.691852057718956E+01,0)

scene = display(width=430, height=400)
scene.append_to_title("""<br>When Earth passes between Mars and the Sun, the simulation will stop.<br> Click the simulation to start it again.<br> The synodic period is the time for Earth to pass between Mars and the Sun.""")
#set the scene's range to avoid autoscaling
scene.range=1.5*mag(marspos)

#constants
AU=1000*149597871 #1 astronomical unit in m
G=6.67384e-11

#diameters for drawing Sun, Mars, and Earth. It is not to scale
Dsun=0.2*AU
Dearth=0.1*AU
Dmars=0.1*AU

# masses
Msun=1.989e30
Mearth=5.97219e24
Mmars=6.4185e23

#define velocity and momentum
vearth=earthvel
vmars=marsvel
pearth=Mearth*vearth
pmars=Mmars*vmars

#time
dt=2*3600 #use 24 to be faster, rocket use 2 written by lookang
day=24*3600
t=0

#create 3D objects
mars=sphere(pos=marspos, radius=Dmars/2, color=color.red, make_trail=True, trail_type="curve",interval=1, retain=1000)

#create labels for displaying time and a message string
tstr="Time: {:.0f} days".format(0)
tlabel=label(pos=vector(0,1.2*mag(marspos),0), text=tstr)
launchstr="Synodic Period: "
launchlabel=label(pos=vector(0,-1.2*mag(marspos),0), text=launchstr)

# relative positions of mars and earth
suntomars=mars.pos-sun.pos
suntoearth=earth.pos-sun.pos

# change in sign of the cross product can be used to find opposition
cproduct=cross(suntoearth,suntomars)
cproductsign=1
oldproductsign=1

#turn off autocaling now that the scene is set
scene.autoscale=False

# times for oppositions; the difference is the synodic period
ti=0
tf=0

while 1:
rate(200)

#starting message
if(t==0):
launchstr="Click to Start"
launchlabel.text=launchstr
scene.waitfor('click')
launchstr="Running..."
launchlabel.text=launchstr

#earth
r=earth.pos-sun.pos
rmag=mag(r)
runit=norm(r)
Fearth=-G*Msun*Mearth/rmag**2*runit
pearth=pearth+Fearth*dt
earth.pos=earth.pos+pearth/Mearth*dt

#mars
r=mars.pos-sun.pos
rmag=mag(r)
runit=norm(r)
Fmars=-G*Msun*Mmars/rmag**2*runit
pmars=pmars+Fmars*dt
mars.pos=mars.pos+pmars/Mmars*dt

#use change in sign of cross product to find opopsition
suntomars=mars.pos-sun.pos
suntoearth=earth.pos-sun.pos
cproduct=cross(suntoearth,suntomars)
oldcproductsign=cproductsign
if(cproduct.z>=0):
cproductsign=1
else:
cproductsign=-1
# opposition occurs
if(oldcproductsign>0 and cproductsign<0):
if(ti==0):
ti=t/day
launchstr="Earth Transit at t="+ti+" days. Click to Continue."
launchlabel.text=launchstr
scene.waitfor('click')
launchstr="Running..."
launchlabel.text=launchstr
else if(ti>0 and tf==0):
tf=t/day
transit=tf-ti
launchstr="Earth Transit at t="+tf+" days.\n Synodic period="+transit+" days = {:.1f} months.\n Click to Continue.".format(transit/30.4)
launchlabel.text=launchstr
scene.waitfor('click')
launchstr="Running..."
launchlabel.text=launchstr

#update time and time label
t=t+dt
tstr="Time: {:.0f} days".format(t/day)
tlabel.text=tstr