Skip to content

Instantly share code, notes, and snippets.

@joshy
Last active March 22, 2016 19:48
Show Gist options
  • Save joshy/968b9762819974c92c9f to your computer and use it in GitHub Desktop.
Save joshy/968b9762819974c92c9f to your computer and use it in GitHub Desktop.
Bezier curve in Elm
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