Penrose Tiling in Elm
module Penrose where | |
import List(foldr, map) | |
import Graphics.Collage(..) | |
import Graphics.Element(..) | |
import Color(..) | |
goldenRatio = (1 + sqrt 5) / 2 | |
type alias Point = (Float, Float) | |
type Triangle | |
= Kite (Point, Point, Point) | |
| Dart (Point, Point, Point) | |
interpolate : Float -> Float -> Float | |
interpolate v0 v1 = v0 + (v1-v0) / goldenRatio | |
split : Point-> Point -> Point | |
split (x1,y1) (x2,y2) = (interpolate x1 x2, interpolate y1 y2) | |
subDivide : Triangle -> List Triangle | |
subDivide tr = | |
case tr of | |
Kite (p1,p2,p3) -> | |
let p4 = split p1 p2 | |
in [ | |
Kite (p3, p4, p2), | |
Dart (p4, p3, p1) | |
] | |
Dart (p1,p2,p3) -> | |
let p4 = split p2 p1 | |
p5 = split p2 p3 | |
in [ | |
Dart (p5, p3, p1), | |
Dart (p4, p5, p2), | |
Kite (p5, p4, p1) | |
] | |
subDivideTriangles : List Triangle -> number-> List Triangle | |
subDivideTriangles tr i = | |
if | i == 0 -> tr | |
| otherwise -> subDivideTriangles (foldr (\t l -> subDivide t ++ l) [] tr) (i-1) | |
toForm : Triangle -> Form | |
toForm tr = | |
case tr of | |
Kite (p1,p2,p3) -> (filled red [p1,p2,p3]) | |
Dart (p1,p2,p3) -> (filled blue [p1,p2,p3]) | |
pointOnCircle : Point ->Float -> Float -> Point | |
pointOnCircle (x,y) r a = (x + cos a * r, y + sin a * r) | |
createTriangle : Float -> Triangle | |
createTriangle i = | |
let | |
o = if (round i) % 2 == 0 then 1 else -1 | |
a1 = (2*i - 1 * o) * pi / 10 | |
a2 = (2*i + 1 * o) * pi / 10 | |
c = (-100.0, 40.0) | |
pointAt = pointOnCircle c 400 | |
in | |
Kite (c, pointAt a1, pointAt a2) | |
trs = map createTriangle [1..10] | |
path = subDivideTriangles trs 4 | |
main : Element | |
main = collage 800 800 (map toForm path) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment