Skip to content

Instantly share code, notes, and snippets.

@jcollard
Created October 8, 2013 19:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jcollard/6890245 to your computer and use it in GitHub Desktop.
Save jcollard/6890245 to your computer and use it in GitHub Desktop.
Neat Spinning Thing! Tracing a circle that happens to be rotating around an ellipse that is wobbling.
import Automaton
import Graphics.Collage
-- parameters
areaSize = 400 -- size of area to draw in
size = 3 -- size of "pixel"
rate = 32 -- Refresh rate
trail = 100 -- How long
av = 3 -- angular velocity of the inner circle
av' = 5 -- angular velocity of the outer circle
cx = areaSize/2 -- CenterX of the inner circle
cy = areaSize/2 -- CenterX of the inner circle
r = areaSize/3 -- Radius of the inner circle
r' = r/3 -- Radius of the outer circle
-- Calculate the angle at the specified time
angle t = toRad (t*av)
angle' t = toRad (t*av')
-- Calculate positions at the specified time
posX t = cx + r * (cos (3*(angle t)))
posY t = cy + r * (sin (2*(angle t)))
posX' t = (posX t) + r' * (cos (angle' t))
posY' t = (posY t) + r' * (sin (angle' t))
pos' t = (posX' t, posY' t)
-- Draw a single pixel of a particular color and size at the specified time
pixel color time size =
let off = -(areaSize/2) in
let p = pos' time in
let move' (x, y) = move (x+off, y+off) in
move' p (filled color (circle size))
-- Oscillate the colors up and down
osc n = if n <= 255 then n else (255 - (n `mod` 255))
c m t = osc ((t*m) `mod` 510)
red = c 3
green = c 5
blue = c 7
-- Draws elements at the specified time
drawing time =
let times = filter (\x -> x > 0) <| adjust time (\t -> t - 1) trail in
let sizes = adjust size (\s -> s - (size/trail)) trail in
let reds = map red times in
let greens = map green times in
let blues = map blue times in
let alphas = adjust 1 (\a -> a - (1/trail)) trail in
let colors = zipWith4 rgba reds greens blues alphas in
let pixels = zipWith3 pixel colors times sizes in
collage areaSize areaSize pixels
-- Each time step, the time increases by one
theState = Automaton.state 0 (\a b -> b + 1)
-- Step every rate milliseconds
stateSignal = Automaton.run theState 0 <| every <| rate*millisecond
-- Link to this file!!
sourceLink = [markdown|
[Elm Source](circle2.elm)
|]
main = drawing <~ stateSignal
-- Helper functions
zipWith4 : (a -> b -> c -> d -> e) -> [a] -> [b] -> [c] -> [d] -> [e]
zipWith4 f ws xs ys zs =
case ws of
[] -> []
(w::ws) ->
case xs of
[] -> []
(x::xs) ->
case ys of
[] -> []
(y::ys) ->
case zs of
[] -> []
(z::zs) -> (f w x y z)::(zipWith4 f ws xs ys zs)
zipWith3 : (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
zipWith3 f xs ys zs =
case xs of
[] -> []
(x::xs) ->
case ys of
[] -> []
(y::ys) ->
case zs of
[] -> []
(z::zs) -> (f x y z)::(zipWith3 f xs ys zs)
-- Create a list that starts with x and adjusts n times
adjust x by n = case n of
0 -> []
_ -> x::(adjust (by x) by (n-1))
toRad a = (toFloat ((round a) `mod` 360))*(pi/180)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment