Skip to content

Instantly share code, notes, and snippets.

@jackrusher
Created June 18, 2013 19:14
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 jackrusher/5808351 to your computer and use it in GitHub Desktop.
Save jackrusher/5808351 to your computer and use it in GitHub Desktop.
Euclid’s Elements, Book I, Proposition 1. An example of a functional approach to tweening in Clojure/Quil. Gif of the output here: http://blog.jackrusher.com/post/53286981041/euclids-elements-book-i-proposition-1-i
(ns workbook.euclid
(use quil.core))
(defn hex-to-dec
"Convert hex RGB triples to decimal."
[s]
(map (comp #(Integer/parseInt % 16) (partial apply str))
(partition 2 s)))
(defn hex-stroke
"Converts a text hex color code to RGB, returns it enrobed in a list
and an atom."
[h]
(atom (list #(apply stroke (hex-to-dec h)))))
;; these functions animate a drawing operation ("tween" it) by
;; converting it into a sequence of anonymous functions, each of which
;; executes one step of the animation.
(defn animated-circle
"Animates drawing a circle."
[x y w]
(atom
(for [i (range 0 361 5)]
#(arc x y w w 0 (radians i)))))
(defn animated-line
"Animates drawing a line."
[x0 y0 x1 y1]
(atom
(let [dx (- x1 x0)
dy (- y1 y0)]
(for [x (if (> x1 x0) (range x0 x1 2) (range x0 x1 -2))]
(let [y (* (+ y0 dy) (/ (- x x0) dx))]
#(line x0 y0 x y))))))
;; some variation of this would make an excellent macro
(def drawing
(vector
(hex-stroke "802256")
(animated-line 180 180 340 180)
(hex-stroke "5e5663")
(animated-circle 180 180 320)
(hex-stroke "124e67")
(animated-circle 340 180 320)
(hex-stroke "802256")
(animated-line 260 42 180 180)
(animated-line 260 42 340 180)))
(defn draw []
(smooth)
(background 0xfefefe)
(stroke-weight 2)
(no-fill)
;; walk down the list of drawing operations, executing sub-steps one
;; per frame.
(loop [drawing drawing]
(let [current-op (first drawing)
step (first @current-op)]
(if-not (nil? step) (step))
(if (seq (rest @current-op))
(reset! current-op (rest @current-op))
(when (seq (rest drawing))
(recur (rest drawing)))))))
(defn setup []
(frame-rate 60))
;; this will start the sketch
(defsketch example
:title "Euclid Book I, Prop 1."
:setup setup
:draw draw
:size [520 360])
;; use this function to stop it
(sketch-stop example)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment