Skip to content

Instantly share code, notes, and snippets.

@eskimoblood
Last active August 29, 2015 14:10
Show Gist options
  • Save eskimoblood/0da25ca40af5f63eb329 to your computer and use it in GitHub Desktop.
Save eskimoblood/0da25ca40af5f63eb329 to your computer and use it in GitHub Desktop.
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