1#!/usr/bin/env python3
2"""      turtle-example-suite:
3
4        tdemo_fractalCurves.py
5
6This program draws two fractal-curve-designs:
7(1) A hilbert curve (in a box)
8(2) A combination of Koch-curves.
9
10The CurvesTurtle class and the fractal-curve-
11methods are taken from the PythonCard example
12scripts for turtle-graphics.
13"""
14from turtle import *
15from time import sleep, clock
16
17class CurvesTurtle(Pen):
18    # example derived from
19    # Turtle Geometry: The Computer as a Medium for Exploring Mathematics
20    # by Harold Abelson and Andrea diSessa
21    # p. 96-98
22    def hilbert(self, size, level, parity):
23        if level == 0:
24            return
25        # rotate and draw first subcurve with opposite parity to big curve
26        self.left(parity * 90)
27        self.hilbert(size, level - 1, -parity)
28        # interface to and draw second subcurve with same parity as big curve
29        self.forward(size)
30        self.right(parity * 90)
31        self.hilbert(size, level - 1, parity)
32        # third subcurve
33        self.forward(size)
34        self.hilbert(size, level - 1, parity)
35        # fourth subcurve
36        self.right(parity * 90)
37        self.forward(size)
38        self.hilbert(size, level - 1, -parity)
39        # a final turn is needed to make the turtle
40        # end up facing outward from the large square
41        self.left(parity * 90)
42
43    # Visual Modeling with Logo: A Structural Approach to Seeing
44    # by James Clayson
45    # Koch curve, after Helge von Koch who introduced this geometric figure in 1904
46    # p. 146
47    def fractalgon(self, n, rad, lev, dir):
48        import math
49
50        # if dir = 1 turn outward
51        # if dir = -1 turn inward
52        edge = 2 * rad * math.sin(math.pi / n)
53        self.pu()
54        self.fd(rad)
55        self.pd()
56        self.rt(180 - (90 * (n - 2) / n))
57        for i in range(n):
58            self.fractal(edge, lev, dir)
59            self.rt(360 / n)
60        self.lt(180 - (90 * (n - 2) / n))
61        self.pu()
62        self.bk(rad)
63        self.pd()
64
65    # p. 146
66    def fractal(self, dist, depth, dir):
67        if depth < 1:
68            self.fd(dist)
69            return
70        self.fractal(dist / 3, depth - 1, dir)
71        self.lt(60 * dir)
72        self.fractal(dist / 3, depth - 1, dir)
73        self.rt(120 * dir)
74        self.fractal(dist / 3, depth - 1, dir)
75        self.lt(60 * dir)
76        self.fractal(dist / 3, depth - 1, dir)
77
78def main():
79    ft = CurvesTurtle()
80
81    ft.reset()
82    ft.speed(0)
83    ft.ht()
84    ft.getscreen().tracer(1,0)
85    ft.pu()
86
87    size = 6
88    ft.setpos(-33*size, -32*size)
89    ft.pd()
90
91    ta=clock()
92    ft.fillcolor("red")
93    ft.begin_fill()
94    ft.fd(size)
95
96    ft.hilbert(size, 6, 1)
97
98    # frame
99    ft.fd(size)
100    for i in range(3):
101        ft.lt(90)
102        ft.fd(size*(64+i%2))
103    ft.pu()
104    for i in range(2):
105        ft.fd(size)
106        ft.rt(90)
107    ft.pd()
108    for i in range(4):
109        ft.fd(size*(66+i%2))
110        ft.rt(90)
111    ft.end_fill()
112    tb=clock()
113    res =  "Hilbert: %.2fsec. " % (tb-ta)
114
115    sleep(3)
116
117    ft.reset()
118    ft.speed(0)
119    ft.ht()
120    ft.getscreen().tracer(1,0)
121
122    ta=clock()
123    ft.color("black", "blue")
124    ft.begin_fill()
125    ft.fractalgon(3, 250, 4, 1)
126    ft.end_fill()
127    ft.begin_fill()
128    ft.color("red")
129    ft.fractalgon(3, 200, 4, -1)
130    ft.end_fill()
131    tb=clock()
132    res +=  "Koch: %.2fsec." % (tb-ta)
133    return res
134
135if __name__  == '__main__':
136    msg = main()
137    print(msg)
138    mainloop()
139