Last active
March 22, 2016 19:48
-
-
Save joshy/968b9762819974c92c9f to your computer and use it in GitHub Desktop.
Bezier curve in Elm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Mouse | |
import Window | |
import Signal as S | |
import Color exposing (..) | |
import List exposing (..) | |
import Graphics.Collage exposing (..) | |
main = S.map2 draws Window.dimensions stateSignal | |
-- A Point on the screen (x-coord, y-coord) | |
type alias Point = (Float, Float) | |
-- State of this program is a list of points | |
type alias State = List Point | |
-- Initally we have no points stored | |
initialState = [] | |
update : Point -> State -> State | |
update newPoint previousState = newPoint :: previousState | |
mouseClickPos : Signal (Int, Int) | |
mouseClickPos = S.sampleOn Mouse.clicks Mouse.position | |
mousePos : Signal (Float, Float) | |
mousePos = S.map2 convert mouseClickPos Window.dimensions | |
stateSignal : Signal State | |
stateSignal = S.foldp update initialState mousePos | |
draws (w,h) p = collage w h [ traced (solid orange) <| bezierCurve p | |
, traced (solid blue) <| take 4 p | |
] | |
bezierCurve : List Point -> List Point | |
bezierCurve controlPoints = if | length controlPoints < 4 -> [] | |
| otherwise -> map (\x -> bezierPoint x (take 4 controlPoints)) resolution | |
bezierPoint : Float -> List Point -> Point | |
bezierPoint t points = if | (length points == 1) -> case (head points) of | |
Just x -> x | |
Nothing -> (0,0) | |
| otherwise -> bezierPoint t (map2 (interpolatePoint t) points (case (tail points) of | |
Just x -> x | |
Nothing -> [])) | |
interpolatePoint : Float -> Point -> Point -> Point | |
interpolatePoint t (x0, y0) (x1, y1) = (interpolate t x0 x1, interpolate t y0 y1) | |
{-- | |
An array [0, 0.01, 0.02, ..., 1] which defines the resolution of the curve | |
--} | |
resolution : List Float | |
resolution = generate 0 1.0 0.01 | |
{-- | |
Converts a mouse position to a canvas position | |
--} | |
convert : (Int, Int) -> (Int, Int) -> Point | |
convert (x,y) (w,h) = (toFloat x - (toFloat w/2), (toFloat h/2) - toFloat y) | |
{-- | |
interpolate: Interpolates between two values a and b. | |
t has a range of [0..1]. | |
t = 0 -> a | |
t = 1 -> b | |
--} | |
interpolate : Float -> Float -> Float -> Float | |
interpolate t a b = t * b + (1 - t) * a | |
{-- | |
generate: Creates a array of floats beginning from the given start value | |
until end value. Values in between are start value plus multiples | |
of step value until end is reached or exceeded. | |
--} | |
generate : Float -> Float -> Float -> List Float | |
generate start end step = if | end <= start -> [] | |
| start + step >= end -> [start, end] | |
| otherwise -> [start] ++ generate (start + step) end step |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment