-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfractals.hs
136 lines (83 loc) · 2.76 KB
/
fractals.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
data Turtle = Stand | Turn Double Turtle | Move Double Turtle
deriving(Show)
done :: Turtle
done = Stand
turn :: Double -> Turtle
turn a = Turn a done
step :: Double -> Turtle
step d = Move d done
(>>>) :: Turtle -> Turtle -> Turtle
Turn a p >>> t = Turn a (p >>> t)
Move d p >>> t = Move d (p >>> t)
Stand >>> t = t
square :: Turtle
square = foldl (>>>) done (replicate 4 (step 50 >>> turn 90))
type Point = (Double, Double)
type Line = (Point, Point)
turtleToLines :: Turtle -> [Line]
turtleToLines turtle =
plotTurtle turtle 0 (1000,100)
where
plotTurtle :: Turtle -> Double -> Point -> [Line]
plotTurtle Stand d s = []
plotTurtle (Move l t) d start@(x,y) =
let nextX = x + l * sin(d * ((2 * pi) / 360)) in
let nextY = y + l * cos(d * ((2 * pi) / 360)) in
let end = (nextX,nextY) in
((start,end):plotTurtle t d end)
plotTurtle (Turn a t) d start =
let nextD = d + a in
plotTurtle t nextD start
linesToSVG :: [Line] -> String
linesToSVG lines =
let header = "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">" in
let body = convertLines lines in
let footer = "</svg>\n" in
header ++ "\n" ++ body ++ footer
where
convertLines :: [Line] -> String
convertLines [] = ""
convertLines (((x1,y1),(x2,y2)):ls) =
"<line x1=\"" ++ show x1 ++ "\" y1=\"" ++ show y1 ++ "\" x2=\"" ++ show x2
++ "\" y2=\"" ++ show y2 ++ "\" stroke=\"blue\" stroke-width=\"4\" />\n"
++ convertLines ls
-- "/Users/Reinert/Desktop/MySvg.svg"
writeSVG :: FilePath -> Turtle -> IO ()
writeSVG path turtle = writeFile path $ linesToSVG $ turtleToLines turtle
data Fractal = Done | Twist Double Fractal | Step Fractal
deriving(Show)
fdone :: Fractal
fdone = Done
fturn :: Double -> Fractal
fturn d = Twist d fdone
fstep :: Fractal
fstep = Step fdone
(>->) :: Fractal -> Fractal -> Fractal
Twist d f1 >-> f2 = Twist d (f1 >-> f2)
Step f1 >-> f2 = Step (f1 >-> f2)
Done >-> f = f
concretize :: Double -> Fractal -> Turtle
concretize d (Twist a f) = Turn a $ concretize d f
concretize d (Step f) = Move d $ concretize d f
concretize d (Done) = Stand
refine :: Fractal -> Fractal -> Fractal
refine expan (Step f) = expan >-> refine expan f
refine expan (Twist a f) = Twist a (refine expan f)
refine expan (Done) = Done
times :: Int -> (a -> a) -> (a -> a)
times n f
| n > 0 = f . times (n-1) f
| otherwise = id
exam :: Fractal -> Fractal -> Int -> Double -> FilePath -> IO ()
exam prog expan n size path =
writeSVG path $ concretize size $ (times n $ refine expan) prog
expansion =
fstep >-> fturn (60) >->
fstep >-> fturn (-120) >->
fstep >-> fturn (60) >->
fstep
program =
fstep >-> fturn (-120) >->
fstep >-> fturn (-120) >->
fstep
--