Skip to content

Instantly share code, notes, and snippets.

@rm-hull
Last active August 29, 2015 13:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rm-hull/8776719 to your computer and use it in GitHub Desktop.
Save rm-hull/8776719 to your computer and use it in GitHub Desktop.
An animated render of a parametric equation in ClojureScript with big-bang. A curve is swept out where the trajectory of a point is usually represented by a parametric equation with the time as parameter.
(ns big-bang.examples.parametric-equations
(:require
[cljs.core.async :as async]
[dommy.core :refer [insert-after!]]
[enchilada :refer [ctx canvas canvas-size]]
[jayq.core :refer [show]]
[monet.canvas :refer [fill-style fill-rect circle rotate translate]]
[big-bang.core :refer [big-bang]]
[big-bang.components :refer [slider]])
(:require-macros
[dommy.macros :refer [sel1 node]]))
(def dimensions
(let [[width height] (canvas-size)]
{:x (quot width -2) :y (quot height -2) :w width :h height}))
(def initial-state
{:t 0
:k 0.45
:ctx ctx
:persistence 95
:clear? false})
(defn incoming [event world-state]
(merge world-state event (if (:k event) {:clear? true})))
(defn tock [event world-state]
(->
world-state
(update-in [:t] inc)
(assoc :clear? false)))
(defn draw-point! [ctx t k]
(let [t (/ t 60)
a 1
b (/ a k)
a-minus-b (- a b)
x (+ (* a-minus-b (Math/cos t))
(* b (Math/cos (* t (dec k)))))
y (- (* a-minus-b (Math/sin t))
(* b (Math/sin (* t (dec k)))))
scale (if (< k 1.0)
(* 150 k)
200)]
(->
ctx
(fill-style :red)
(circle {:x (* scale x) :y (* scale y) :r 3}))))
(defn render-frame! [{:keys [clear? k t persistence ctx] :as world-state}]
(let [color (if clear?
:white
(str "rgba(255,255,255," (double (/ (- 100 persistence) 100)) ")"))]
(->
ctx
(fill-style color)
(fill-rect dimensions)
(draw-point! t k))))
(let [chan (async/chan)]
(show canvas)
(translate ctx (quot (dimensions :w) 2) (quot (dimensions :h) 2))
(->>
(sel1 :#canvas-area)
(insert-after! (node
[:div
(slider
:id :persistence
:label-text "Persistence:"
:min-value 0
:max-value 100
:initial-value (initial-state :persistence)
:send-channel chan)
[:span {:style "padding-right: 100px"}]
(slider
:id :k
:label-text "k:"
:min-value 0.05
:max-value 10
:step 0.05
:initial-value (initial-state :k)
:send-channel chan)])))
(big-bang
:initial-state initial-state
:receive-channel chan
:on-receive incoming
:on-tick tock
:to-draw render-frame!))

Parametric Equations

Using:

x

y

Where t increases monotonically, and k can be varied with the slider below, the (x,y) co-ordinates sweep out the curve of a distressed Cardioid. When k = 0.5 the curve sweeps out a perfect Cardioid.

The state and rendering are maintained as separate concerns using the Big-bang library. Furthermore, the sliders at the bottom of the canvas area are implemented as self-contained composite big-bang components in their own right: as soon as a change event occurs on one, the slider re-renders the display value and emits the new value on the supplied channel.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment