-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPenrose.elm
143 lines (111 loc) · 3.67 KB
/
Penrose.elm
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
137
138
139
140
141
142
143
module Main exposing (main)
import Math.Vector2 exposing (add, scale, sub, fromTuple, getX, getY)
import Svg exposing (polygon, svg)
import Svg.Attributes as SvgA
type alias Point =
Math.Vector2.Vec2
type TriangleType
= T36
| T108
type alias Triangle =
{ a : Point
, b : Point
, c : Point
, triangleType : TriangleType
}
main : Svg.Svg msg
main =
let
triangles =
divideTriangles 6 createTrianglesCircle
_ =
Debug.log "triangles count" <| List.length triangles
svgTriangles =
List.map drawTriangle triangles
in
svg
[ SvgA.version "1.1", SvgA.viewBox "-120 -120 300 300" ]
svgTriangles
createTrianglesCircle : List Triangle
createTrianglesCircle =
let
createTriangle i =
let
-- Alternate angle factor between -1 and 1.
b_ =
2 * (i % 2) - 1
c_ =
-1 * b_
triangle =
{ a = fromTuple ( 0, 0 )
, b = fromTuple <| fromPolar ( 100, toFloat (2 * i + b_) * pi / 10 )
, c = fromTuple <| fromPolar ( 100, toFloat (2 * i + c_) * pi / 10 )
, triangleType = T36
}
in
triangle
in
List.map createTriangle <| List.range 1 10
divideTriangles : Int -> List Triangle -> List Triangle
divideTriangles n triangles =
case n of
0 ->
triangles
_ ->
List.append triangles <| divideTriangles (n - 1) <| List.concatMap divideTriangle triangles
divideTriangle : Triangle -> List Triangle
divideTriangle triangle =
let
phi =
(1 + sqrt 5) / 2
in
case triangle.triangleType of
T36 ->
let
p =
add triangle.a <| scale (1 / phi) <| (sub triangle.b triangle.a)
triangle_ =
createTriangle triangle.c p triangle.b T36
triangle__ =
createTriangle p triangle.c triangle.a T108
in
[ triangle_, triangle__ ]
T108 ->
let
p1 =
add triangle.b <| scale (1 / phi) <| (sub triangle.a triangle.b)
p2 =
add triangle.b <| scale (1 / phi) <| (sub triangle.c triangle.b)
triangle_ =
createTriangle p2 triangle.c triangle.a T108
triangle__ =
createTriangle p1 p2 triangle.b T108
triangle___ =
createTriangle p2 p1 triangle.a T36
in
[ triangle_, triangle__, triangle___ ]
createTriangle : Point -> Point -> Point -> TriangleType -> Triangle
createTriangle a b c triangleType =
{ a = a
, b = b
, c = c
, triangleType = triangleType
}
drawTriangle : Triangle -> Svg.Svg msg
drawTriangle triangle =
let
color =
case triangle.triangleType of
T36 ->
"pink"
T108 ->
"#f2a2d2"
in
polygon
[ SvgA.fill color
, SvgA.points <| toString (getX triangle.a) ++ "," ++ toString (getY triangle.a) ++ " " ++ toString (getX triangle.b) ++ "," ++ toString (getY triangle.b) ++ " " ++ toString (getX triangle.c) ++ "," ++ toString (getY triangle.c)
, SvgA.fillOpacity "0.5"
, SvgA.stroke "#ffdbe7"
, SvgA.strokeWidth "0.01"
]
[]