1#!/usr/bin/env python3
2"""       turtle-example-suite:
3
4        tdemo_planets_and_moon.py
5
6Gravitational system simulation using the
7approximation method from Feynman-lectures,
8p.9-8, using turtlegraphics.
9
10Example: heavy central body, light planet,
11very light moon!
12Planet has a circular orbit, moon a stable
13orbit around the planet.
14
15You can hold the movement temporarily by
16pressing the left mouse button with the
17mouse over the scrollbar of the canvas.
18
19"""
20from turtle import Shape, Turtle, mainloop, Vec2D as Vec
21
22G = 8
23
24class GravSys(object):
25    def __init__(self):
26        self.planets = []
27        self.t = 0
28        self.dt = 0.01
29    def init(self):
30        for p in self.planets:
31            p.init()
32    def start(self):
33        for i in range(10000):
34            self.t += self.dt
35            for p in self.planets:
36                p.step()
37
38class Star(Turtle):
39    def __init__(self, m, x, v, gravSys, shape):
40        Turtle.__init__(self, shape=shape)
41        self.penup()
42        self.m = m
43        self.setpos(x)
44        self.v = v
45        gravSys.planets.append(self)
46        self.gravSys = gravSys
47        self.resizemode("user")
48        self.pendown()
49    def init(self):
50        dt = self.gravSys.dt
51        self.a = self.acc()
52        self.v = self.v + 0.5*dt*self.a
53    def acc(self):
54        a = Vec(0,0)
55        for planet in self.gravSys.planets:
56            if planet != self:
57                v = planet.pos()-self.pos()
58                a += (G*planet.m/abs(v)**3)*v
59        return a
60    def step(self):
61        dt = self.gravSys.dt
62        self.setpos(self.pos() + dt*self.v)
63        if self.gravSys.planets.index(self) != 0:
64            self.setheading(self.towards(self.gravSys.planets[0]))
65        self.a = self.acc()
66        self.v = self.v + dt*self.a
67
68## create compound yellow/blue turtleshape for planets
69
70def main():
71    s = Turtle()
72    s.reset()
73    s.getscreen().tracer(0,0)
74    s.ht()
75    s.pu()
76    s.fd(6)
77    s.lt(90)
78    s.begin_poly()
79    s.circle(6, 180)
80    s.end_poly()
81    m1 = s.get_poly()
82    s.begin_poly()
83    s.circle(6,180)
84    s.end_poly()
85    m2 = s.get_poly()
86
87    planetshape = Shape("compound")
88    planetshape.addcomponent(m1,"orange")
89    planetshape.addcomponent(m2,"blue")
90    s.getscreen().register_shape("planet", planetshape)
91    s.getscreen().tracer(1,0)
92
93    ## setup gravitational system
94    gs = GravSys()
95    sun = Star(1000000, Vec(0,0), Vec(0,-2.5), gs, "circle")
96    sun.color("yellow")
97    sun.shapesize(1.8)
98    sun.pu()
99    earth = Star(12500, Vec(210,0), Vec(0,195), gs, "planet")
100    earth.pencolor("green")
101    earth.shapesize(0.8)
102    moon = Star(1, Vec(220,0), Vec(0,295), gs, "planet")
103    moon.pencolor("blue")
104    moon.shapesize(0.5)
105    gs.init()
106    gs.start()
107    return "Done!"
108
109if __name__ == '__main__':
110    main()
111    mainloop()
112