1#!/usr/local/bin/python3.7
2"""       xturtle-example-suite:
3
4          xtx_kites_and_darts.py
5
6Constructs two aperiodic penrose-tilings,
7consisting of kites and darts, by the method
8of inflation in six steps.
9
10Starting points are the patterns "sun"
11consisting of five kites and "star"
12consisting of five darts.
13
14For more information see:
15 http://en.wikipedia.org/wiki/Penrose_tiling
16 -------------------------------------------
17"""
18from turtle import *
19from math import cos, pi
20from time import perf_counter as clock, sleep
21
22f = (5**0.5-1)/2.0   # (sqrt(5)-1)/2 -- golden ratio
23d = 2 * cos(3*pi/10)
24
25def kite(l):
26    fl = f * l
27    lt(36)
28    fd(l)
29    rt(108)
30    fd(fl)
31    rt(36)
32    fd(fl)
33    rt(108)
34    fd(l)
35    rt(144)
36
37def dart(l):
38    fl = f * l
39    lt(36)
40    fd(l)
41    rt(144)
42    fd(fl)
43    lt(36)
44    fd(fl)
45    rt(144)
46    fd(l)
47    rt(144)
48
49def inflatekite(l, n):
50    if n == 0:
51        px, py = pos()
52        h, x, y = int(heading()), round(px,3), round(py,3)
53        tiledict[(h,x,y)] = True
54        return
55    fl = f * l
56    lt(36)
57    inflatedart(fl, n-1)
58    fd(l)
59    rt(144)
60    inflatekite(fl, n-1)
61    lt(18)
62    fd(l*d)
63    rt(162)
64    inflatekite(fl, n-1)
65    lt(36)
66    fd(l)
67    rt(180)
68    inflatedart(fl, n-1)
69    lt(36)
70
71def inflatedart(l, n):
72    if n == 0:
73        px, py = pos()
74        h, x, y = int(heading()), round(px,3), round(py,3)
75        tiledict[(h,x,y)] = False
76        return
77    fl = f * l
78    inflatekite(fl, n-1)
79    lt(36)
80    fd(l)
81    rt(180)
82    inflatedart(fl, n-1)
83    lt(54)
84    fd(l*d)
85    rt(126)
86    inflatedart(fl, n-1)
87    fd(l)
88    rt(144)
89
90def draw(l, n, th=2):
91    clear()
92    l = l * f**n
93    shapesize(l/100.0, l/100.0, th)
94    for k in tiledict:
95        h, x, y = k
96        setpos(x, y)
97        setheading(h)
98        if tiledict[k]:
99            shape("kite")
100            color("black", (0, 0.75, 0))
101        else:
102            shape("dart")
103            color("black", (0.75, 0, 0))
104        stamp()
105
106def sun(l, n):
107    for i in range(5):
108        inflatekite(l, n)
109        lt(72)
110
111def star(l,n):
112    for i in range(5):
113        inflatedart(l, n)
114        lt(72)
115
116def makeshapes():
117    tracer(0)
118    begin_poly()
119    kite(100)
120    end_poly()
121    register_shape("kite", get_poly())
122    begin_poly()
123    dart(100)
124    end_poly()
125    register_shape("dart", get_poly())
126    tracer(1)
127
128def start():
129    reset()
130    ht()
131    pu()
132    makeshapes()
133    resizemode("user")
134
135def test(l=200, n=4, fun=sun, startpos=(0,0), th=2):
136    global tiledict
137    goto(startpos)
138    setheading(0)
139    tiledict = {}
140    a = clock()
141    tracer(0)
142    fun(l, n)
143    b = clock()
144    draw(l, n, th)
145    tracer(1)
146    c = clock()
147    nk = len([x for x in tiledict if tiledict[x]])
148    nd = len([x for x in tiledict if not tiledict[x]])
149    print("%d kites and %d darts = %d pieces." % (nk, nd, nk+nd))
150
151def demo(fun=sun):
152    start()
153    for i in range(8):
154        a = clock()
155        test(300, i, fun)
156        b = clock()
157        t = b - a
158        if t < 2:
159            sleep(2 - t)
160
161def main():
162    #title("Penrose-tiling with kites and darts.")
163    mode("logo")
164    bgcolor(0.3, 0.3, 0)
165    demo(sun)
166    sleep(2)
167    demo(star)
168    pencolor("black")
169    goto(0,-200)
170    pencolor(0.7,0.7,1)
171    write("Please wait...",
172          align="center", font=('Arial Black', 36, 'bold'))
173    test(600, 8, startpos=(70, 117))
174    return "Done"
175
176if __name__ == "__main__":
177    msg = main()
178    mainloop()
179