Skip to content

Instantly share code, notes, and snippets.

@kiras
Created June 26, 2011 21:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kiras/1047989 to your computer and use it in GitHub Desktop.
Save kiras/1047989 to your computer and use it in GitHub Desktop.
Sierpinski Gasket code
(ns sierpinski.core
(:use [penumbra.opengl])
(:require [penumbra.app :as app])
(:require clojure.contrib.math))
(defn make-point [x y z]
{:x x :y y :z z})
(defn make-triangle [p1 p2 p3]
{:p1 p1 :p2 p2 :p3 p3})
(defn generate-random-point
"Generates a random 3D point, with vertex values between 0 (inclusive) and the
corresponding n (default 1) (exclusive)."
([]
(make-point (rand) (rand) (rand)))
([x-n, y-n, z-n]
(make-point (rand x-n) (rand y-n) (rand z-n))))
(defn generate-random-points
"Generates a lazy-seq of n random points. Each point will have vertex values
between 0 (inclusive) and the corresponding n (default 1) (exclusive)."
([n x-n y-n z-n]
(lazy-seq
(when (> n 0)
(cons (generate-random-point x-n y-n z-n)
(generate-random-points (dec n) x-n y-n z-n))))))
(defn sierpinskisize
"Chooses a vertex from tri at random, returning the point halfway between
p and the vertex."
[p tri]
(let [v-num (clojure.contrib.math/floor (rand 3))
vertex (cond (= v-num 0)
(:p1 tri)
(= v-num 1)
(:p2 tri)
(= v-num 2)
(:p3 tri))
halfway-point (fn [p1 p2]
[(/ (+ (:x p1) (:x p2)) 2)
(/ (+ (:y p1) (:y p2)) 2)
(/ (+ (:z p1) (:z p2)) 2)])]
(apply make-point (halfway-point vertex p))))
(defn sierpinski-points
"Generates a lazy-seq of n points describing a Sierpinski gasket. The gasket
will have boundaries set by the vertices of tri."
[n tri initial-point]
(lazy-seq
(let [sierpinski-point (sierpinskisize initial-point tri)]
(when (> n 0)
(cons (sierpinskisize sierpinski-point tri)
(sierpinski-points (dec n) tri sierpinski-point))))))
(defn generate-sierpinski-gasket [n tri initial-point]
"Creates and draws a sierpinski gasket with n points, within the bounds
specified by tri."
(->> (sierpinski-points n tri initial-point)
(map #(vertex (% :x) (% :y) (% :z)))
(dorun)))
;; Callbacks.
(defn init [state]
(app/title! "Sierpinski Gasket"))
(defn reshape [[x y width height] state]
(ortho-view 0.0 100.0 100.0 0.0 0.0 -1.0)
state)
(defn display [[delta time] state]
(draw-points
(color 1.0 0.0 0.0)
(let [tri (make-triangle (make-point 0.0 0.0 0.0)
(make-point 25.0 50.0 0.0)
(make-point 50.0 0.0 0.0))
initial-point (make-point 10 10 10)]
(generate-sierpinski-gasket 10000 tri initial-point))))
(app/start
{:init init, :display display, :reshape reshape}
{})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment