-- Complex Domain Colouring -- https://en.wikipedia.org/wiki/Domain_coloring -- You need to know what a complex number is to understand what this is for. -- Example where the points we click on are coloured according to the function z^2 + 1. -- z = x + i * y -- z^2 + 1 = (x + i*y) * (x + i*y) + 1 -- = ( x*x - y*y + 1 ) + i * ( 2 * x * y) myShapes model = -- List.map applies the function drawAt to all the positions List.map drawAt model.positions ++ -- draw axes ( List.map ( \ y -> rect 192 0.25 |> filled black |> move (0,10 * toFloat y) ) <| List.range -6 6 ) ++ ( List.map ( \ x -> rect 0.25 128 |> filled black |> move (10 * toFloat x, 0) ) <| List.range -9 9 ) ++ -- to catch taps everywhere, draw a clear rect above all shapes [ rect 192 128 |> filled (rgba 0 0 0 0.01) |> notifyTapAt TapAt ] -- draw a red spot at a point drawAt : (Float,Float) -> Shape Msg drawAt (xIn,yIn) = let -- 10 pixels per unit x = 0.1 * xIn y = 0.1 * yIn -- calculate z2plus1 xNew = x*x - y*y + 1 yNew = 2 * x * y -- 10 pixels per unit xOut = 10 * xNew yOut = 10 * yNew in circle 1 |> filled (magPhase xOut yOut) -- colour according to z^2 + 1 |> move (xIn,yIn) -- but plot in position of z -- calculate a colour value where -- hue=angle, and -- lightness increases with magnitude but never goes above 1 magPhase x y = let angle = atan2 y x m = sqrt (x^2 + y^2) -- magnitude in hsl angle 1 ( 0.07 * m / ( 1 + 0.07 * m) ) type Msg = Tick Float GetKeyState | TapAt (Float,Float) | StartAgain update msg model = case msg of Tick t _ -> { model | time = t } StartAgain -> { model | positions = [] } TapAt pos -> { model | positions = pos :: model.positions } init : { time : Float, positions : List (Float,Float) } init = { time = 0, positions = [] }