Created
June 18, 2013 19:14
-
-
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
This file contains 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
(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